# Overwriting association accesor

**URL:** <https://www.ruby-forum.com/t/overwriting-association-accesor/124710>\
**Category:** Rails\
**Created:** [January 1, 2008, 2:36pm UTC](https://www.ruby-forum.com/t/overwriting-association-accesor/124710 "2008-01-01T14:36:49Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Borja\_MartSSS\_n](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/f08c70/32.png) [@Borja\_MartSSS\_n](https://www.ruby-forum.com/u/Borja_MartSSS_n)\
**Post date:** [January 1, 2008, 2:36pm UTC](https://www.ruby-forum.com/t/overwriting-association-accesor/124710/1 "2008-01-01T14:36:49Z")

</div>

Hi,  
first of all I would like to wish a happy new year to all the list  
members.

Here is my problem. I have a model class where I need to overwrite an  
accessor method in order to add some extra behaviour:

class LineItem \< ActiveRecord::Base

belongs\_to :item, :polymorphic =\> true

# add\_item

# 

def item=(item)  
write\_attribute(:item, item)  
self.price = item.price  
end

# item

# 

def item  
read\_attribute(:item)  
end  
end

The problem is that when I overwrite the item= method, the item\_id and  
item\_type attributes aren’t stored in the database when I save the  
object so the associated item is missed. I know I could manually set the  
item\_id and item\_type values with something like this:

def item=(item)  
write\_attribute(:item, item)  
self.price = item.price  
self.item\_id = item.id  
self.item\_type = item.class.to\_s  
end

but the problem with this solution resides on that the given item  
probably has no id as it should handled as a new record too.  
Is there any way I could use the default association behaviour(that is  
to automatically set the item\_id and item\_type attributes and saving the  
item first when necessary) and still being able to overwrite the writer  
method too? I also tried it by aliasing the item= method but with no  
success.

Thanks in advance.

–  
/\*\*

- dagi3d v4 | [http://dagi3d.net](http://dagi3d.net)  
\*/

---

<div class="post-metadata">

**Author:** ![Borja\_MartSSS\_n](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/f08c70/32.png) [@Borja\_MartSSS\_n](https://www.ruby-forum.com/u/Borja_MartSSS_n)\
**Post date:** [January 1, 2008, 5:22pm UTC](https://www.ruby-forum.com/t/overwriting-association-accesor/124710/2 "2008-01-01T17:22:20Z")

</div>

Borja Martín wrote:

> Hi,  
> first of all I would like to wish a happy new year to all the list members.

Thank you Borja.

> Here is my problem. I have a model class where I need to overwrite an  
> accessor method in order to add some extra behaviour:

Look here:  
[http://groups.google.com/group/rubyonrails-talk/browse\_thread/thread/4fe057494c6e23e8](http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/4fe057494c6e23e8)

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![Borja\_MartSSS\_n](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/f08c70/32.png) [@Borja\_MartSSS\_n](https://www.ruby-forum.com/u/Borja_MartSSS_n)\
**Post date:** [January 1, 2008, 5:58pm UTC](https://www.ruby-forum.com/t/overwriting-association-accesor/124710/3 "2008-01-01T17:58:39Z")

</div>

Thanks Mark, I solved it by using the alias\_method\_chain as you  
suggested:

class LineItem \< ActiveRecord::Base

belongs\_to :item, :polymorphic =\> true

def item\_with\_price\_check=(item)  
self.item\_without\_price\_check = item  
self.price = item.price  
end

alias\_method\_chain :item=, :price\_check

end

Regards

Mark Reginald J.  
escribió:\> Borja Martín wrote:

> > 
> 
> Look here: [http://groups.google.com/group/rubyonrails-talk/browse\_thread/thread/4fe057494c6e23e8](http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/4fe057494c6e23e8)

–  
/\*\*

- dagi3d v4 | [http://dagi3d.net](http://dagi3d.net)  
\*/

---

<div class="post-metadata">

**Author:** ![Borja\_MartSSS\_n](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/f08c70/32.png) [@Borja\_MartSSS\_n](https://www.ruby-forum.com/u/Borja_MartSSS_n)\
**Post date:** [January 3, 2008, 6:38pm UTC](https://www.ruby-forum.com/t/overwriting-association-accesor/124710/4 "2008-01-03T18:38:01Z")

</div>

Borja MartÃ­n wrote:

> Hi,  
> first of all I would like to wish a happy new year to all the list  
> members.
> 
> Here is my problem. I have a model class where I need to overwrite an  
> accessor method in order to add some extra behaviour:
> 
> class LineItem \< ActiveRecord::Base
> 
> belongs\_to :item, :polymorphic =\> true
> 
> # add\_item
> 
> # 
> 
> def item=(item)  
> write\_attribute(:item, item)  
> self.price = item.price  
> end
> 
> # item
> 
> # 
> 
> def item  
> read\_attribute(:item)  
> end  
> end

What you need are association callbacks. The following is from the  
ActiveRecord::Association::ClassMethods Page in the RDoc:

Association callbacks

Similiar to the normal callbacks that hook into the lifecycle of an  
Active Record object, you can also define callbacks that get trigged  
when you add an object to or removing an object from a association  
collection. Example:

class Project  
has\_and\_belongs\_to\_many :developers, :after\_add =\>  
:evaluate\_velocity

```
def evaluate_velocity(developer)
  ...
end

```

end

Itâ€˜s possible to stack callbacks by passing them as an array. Example:

class Project  
has\_and\_belongs\_to\_many :developers, :after\_add =\>  
[:evaluate\_velocity, Proc.new { |p, d| p.shipping\_date = Time.now}]  
end

Possible callbacks are: before\_add, after\_add, before\_remove and  
after\_remove.

Should any of the before\_add callbacks throw an exception, the object  
does not get added to the collection. Same with the before\_remove  
callbacks, if an exception is thrown the object doesnâ€˜t get removed.
