Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to "touch" a parent model of a `belongs_to` association only if certain conditions are met?

I am using Rails 3.1.0 and I would like to "touch" a parent model of a belongs_to association only if certain conditions are met.

For example, at this time I have:

belongs_to :article,
  :touch => true

I would "touch" the parent model only if it is "public". That is, the Article class has an attribute named access (@article.access => public or private) and I would like to check this value before "touching": if this value is not public, then "touch" it!

Is it possible to make that "directly" in the belongs_to association statement? If so, how?

like image 759
Backo Avatar asked Jan 15 '12 15:01

Backo


People also ask

How would you choose between Belongs_to and Has_one?

They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user . To determine who "has" the other object, look at where the foreign key is.

Does Rails have one ruby?

has_one means that there is a foreign key in another table that references this class. So has_one can ONLY go in a class that is referenced by a column in another table. For a two-way association, you need one of each, and they have to go in the right class. Even for a one-way association, it matters which one you use.

What is a polymorphic association in Rails?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.


1 Answers

You can try lambda as you said but I'm not sure if its going to work. Something like this:

belongs_to :article, :touch => Proc.new{|o| o.article && o.article.public }

According to the implementation maybe you can try to return nil instead of false in the proc, when it's not available

belongs_to :article, :touch => Proc.new{|o| o.article && o.article.public ? true : nil }

If this doesn't works use a before save callback like this:

class Model < ActiveRecord::Base
  belongs_to :article

  before_save :touch_public_parent

  def touch_public_parent
    article.touch if article && article.public?
  end
end

Let me know if you have any questions.

Update #1

The relevant part from add_touch_callbacks:

if touch_attribute == true
  association.touch unless association.nil?
else
  association.touch(touch_attribute) unless association.nil?
end

So if you pass true, then does a simple touch on updated_at attribute. If you pass a field name then updates that field unless you pass nil. If you pass nil doesn't updates nothing. That's why I said that maybe you can try the second version of belongs_to association.

like image 154
dombesz Avatar answered Sep 25 '22 06:09

dombesz