When joining table, rails anyway makes additional request when accessing fields from joined table
Try includes
as in Company.includes(:city).first.city.title
.
Adding an extra field to the join table in has_many through association
First of all:
- there is a mistake in the
JobReview
model. Replacebelongs_to :job_review
withbelongs_to :review
- the
job_review_params
method should be renamed tojob_params
as it is in fact aJob
object that you assign params to.
When you assign reviews
to a job
passing the review_ids
parameter, Rails tries to automatically create the job_reviews
association. It fails because Rails can't automatically calculate the user_id
value and it is not passed properly.
Although you have the user_id
parameter in the form, it is passed as job
's attribute. Rails doesn't know what to do with it.
One of the ways to solve the problem is to assign reviews
to a job
manually:
job_params[:review_ids].each do |review_id|
@job.job_reviews.build(review_id: review_id, user_id: current_user.id)
end
@job.save
In this case you don't have to send user_id
through the form because it is available in the controller:
= simple_form_for @job do |f|
= f.association :reviews, collection: Review.all, as: :check_boxes, include_hidden: false, label: false
= f.button :submit, class: 'btn btn-success'
Unable to update extra attribute in join table in Rails
Knowing that your TodolistsTodo
has the :row_oder
, and knowing, there can be only one TodolistTodo
for each Todolist and ToDo, assuming that @parent is the todolist, use
@parent = Todolist.find params[:todolist_id]
@item = @parent.todolists_todo.where(todo_id: params[:todo][:todo_id]).first
@item.update_attribute :row_order, todo_params[:todolists_attributes][:row_order]
Rails Joins and include columns from joins table
I don't think that you can load users and profiles with join in Rails. I think that in earlier versions of Rails ( < 2.1) loading of associated models was done with joins, but it was not efficient. Here you have some explanation and links to other materials.
So even if you explicite say that you want to join it, Rails won't map it to associated models. So if you say Profile.whatever_here
it will always be mapped to Profile
object.
If you still want to do what you said in question, then you can call custom sql query and process results by yourself:
p = ActiveRecord::Base.connection.execute("SELECT * FROM profiles JOIN users ON profiles.user_id = users.id LIMIT 1")
and get results row by row with:
p.fetch_row
It will already be mappet to an array.
Your errors are because you are calling first_name
and user
method on AciveRecord::Relation
object and it stores an array of Profile
objects, not a single object. So
p = Profile.joins(:user).limit(1)
p[0].first_name
shoud work.
Better way to fetch only one record is to call:
p = Profile.joins(:user).first
p.first_name
p.user
But when you call p.user
it will query database. To avoid it, you can use include
, but if you load only one profile object, it is useless. It will make a difference if you load many profiles at a time and want to inlcude users table.
Left join and .includes()
Got it: we need to use .references()
in conjunction with .includes
; then, Rails performs LEFT JOIN
and we can reference joined table in SQL query.
So, this works:
Company.includes(:people).references(:people).includes(:city).references(:city)
Well, this seems messy area.
Elegantly set join table attributes on has_many through: association
The model layer itself does not have knwoledge of the current_user
, so you have to pass it in from the controller layer somehow.
The most elegant solution I can come up with is to create an add_article
-method in the Collection
model:
def add_article(article, by_user)
self.collection_articles.create(article: article, user: by_user)
end
..and call that from the controller
Rails - Sort by join table data
I would suggest to avoid using default_scope
, especially on something like price on another table. Every time you'll use that table, join and ordering will take place, possibly giving strange results in complex queries and anyway making your query slower.
There's nothing wrong with a scope of its own, it's simpler and it's even clearer, you can make it as simple as:
scope :ordered, -> { includes(:availabilities).order('availabilities.price') }
PS: Remember to add an index on price
; Also see other great answers in here to decide between join/include.
Related Topics
Rails + Google Calendar API Events Not Created
Mongomapper Many to Many Issue with Array
Reply to Thread Google-Api-Ruby-Client
How to Set Up These Crud Controller Actions for Has_Many_Polymorphs and an Error
Refactoring Pokemon Type Weekness
Placing Sub Arrays in Neat Rows
Making Hashes Find Each Other by Their Values Using Ruby
Jruby on Rails VS. Ruby on Rails, What's Difference
Capistrano Deploy Fails After I Changed the Repository Url
Find Values in Common Between Two Arrays
Error: Missing Rvm Environment File After Doing Rvm Upgrade Command - Passenger 4.0.23
Using Sed to Append Lines to File During Vagrant Provisioning
Consolidating Duplicate Array Items
How to Install Version Specified Ruby Using Apt
Adding a String in Front of a Parameter for a Form
Unexpected =>, Expecting '}' in Rspec Expect
Ruby String Prepend '\' Character
Ruby/Watir/Rasta: Pass the Value from the Excel/Rasta to an Array in Ruby