Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing touch option in Rails has_many relation

I have 2 Rails models: Book and Category, where a book belongs_to a category, a category has_many books.

The category name is shown in each book's page, and pages are cached.

If I change a category name (say, from 'Sci Fi' to 'Science Fiction'), then all corresponding book pages will be stale, and books need to be "touched" in order to trigger HTML regeneration.

It would seem to make sense to be able to do:

class Category << ActiveRecord::Base
  has_many :books, touch: true
end

But the option is unavailable, I guess because the touch mechanism would instantiate each object, which could result in a major performance hit for has_many relationships.

To avoid that, I am using raw SQL as follows:

class Category << ActiveRecord::Base
  has_many :books
  after_update -> {
    ActiveRecord::Base.connection.execute "UPDATE books SET updated_at='#{current_time_string}' WHERE category_id=#{id})"
  }
end

Which is pretty terrible. Is there a better way?

like image 395
Giuseppe Avatar asked Oct 29 '15 08:10

Giuseppe


People also ask

What is the difference between Has_one and Belongs_to?

The only difference between hasOne and belongsTo is where the foreign key column is located. Let's say you have two entities: User and an Account. In short hasOne and belongsTo are inverses of one another - if one record belongTo the other, the other hasOne of the first.

What does touch do in Rails?

In rails touch is used to update the updated_at field for persisted objects. But if we pass other attributes as arguments, it will update those fields too along with updated_at . Even it will update non-date-time fields if passed as arguments.

What is has_ many?

A has_many association is similar to has_one , but indicates a one-to-many connection with another model. You'll often find this association on the "other side" of a belongs_to association. This association indicates that each instance of the model has zero or more instances of another model.


1 Answers

You can't use touch on has_many association, it works only with belongs_to, that's a fact.

If I understand correctly what you want, the answers with touch:true in the Book model won't work, because the Book object will not be updated when You change the Category model and the view will not regenerating.

So I think your solution is the best for that. (You can use also books.update_all(updated_at: Time.now))

like image 80
Szegedi Róbert Avatar answered Oct 26 '22 08:10

Szegedi Róbert