When Joining Table, Rails Anyway Makes Additional Request When Accessing Fields from Joined Table

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. Replace belongs_to :job_review with belongs_to :review
  • the job_review_params method should be renamed to job_params as it is in fact a Job 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



Leave a reply



Submit