Forum: Ruby on Rails active record associations

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
98208c10adcf9b7bd9cbe6c23ec2c50d?d=identicon&s=25 Franz Obenhauser (obenhauser)
on 2008-11-06 05:39
(Received via mailing list)
I want to accomplish the following. I have an object that can be
edited.  However, it can occur that two people might edit the object
at the same time.  Instead of locking the object down, I prefer to
tell the user how their version differs from the last version that was
committed.

Kinda like:

respond_to do |format|
  @document = Document.find_by_id(1)
  @document.attributes = params[:document]
  @changes = @document.diff(Document.find_by_id(1))
   format.html { render :action => "edit" }
end

The edit screen then renders the changes for the user to compare.  The
user can then apply some changes or ignore the changes and save.

This works fine for regular fields, but when the object has has_many
assoctiations, then the following would occur.

respond_to do |format|
  @document = Document.find_by_id(1)
  @document.attributes = params[:document]  # => this call would
update the database for all has_many associations
  @changes = @document.diff(Document.find_by_id(1))  #=> retrieving
the previous object state from the database is not possible since the
associations have changed
   format.html { render :action => "edit" }
end

I also tried to compare the object to the attributes kinda like this;

respond_to do |format|
  @document = Document.find_by_id(1)
  @changes = @document.diff(params[:document])
   format.html { render :action => "edit" }
end

But then the user's changes aren't stored on the object and all
updates are lost.

Any help is appreciated.
3ff9c2544554b13c6c7877e76684751b?d=identicon&s=25 Lee Smith (smitjel)
on 2008-11-06 17:55
(Received via mailing list)
This sounds like the dirty object feature of Rails 2.1 would work
great:
http://ryandaigle.com/articles/2008/3/31/what-s-ne...

Maybe even try to utilize some callback methods so you can capture and
display the changes to the user:
http://railsforum.com/viewtopic.php?id=23001
98208c10adcf9b7bd9cbe6c23ec2c50d?d=identicon&s=25 Franz Obenhauser (obenhauser)
on 2008-11-07 04:18
(Received via mailing list)
The dirty object feature doesn't work for has_many associations.  I
solved the problem by wrapping a transaction around the code to revert
the changes in the database.  I kinda wish, ror could keep the
functionality between regular fields and association fields consistent
to avoid confusion.

kinda like:

class Person
  has_many :cars
end

>> person = Person.find_by_name("Jack")
>> person.cars
=> [#<Car id: 2, name: "BMW", created_at: "2008-11-04 03:04:46",
updated_at: "2008-11-04 03:04:46">]
>> person.cars=[Car.find_by_name("Porsche"), Car.find_by_name("VW")]
>> person.cars
=> [#<Car id: 1, name: "Porsche", created_at: "2008-11-04 03:04:46",
updated_at: "2008-11-04 03:04:46">, #<Car id: 3, name: "VW",
created_at: "2008-11-04 03:04:46", updated_at: "2008-11-04 03:04:46">]
>> person.changed?
=> true
>> person.changes
=> {"cars"=>[[#<Car id: 2, name: "BMW", created_at: "2008-11-04
03:04:46", updated_at: "2008-11-04 03:04:46">], [#<Car id: 1, name:
"Porsche", created_at: "2008-11-04 03:04:46", updated_at: "2008-11-04
03:04:46">, #<Car id: 3, name: "VW", created_at: "2008-11-04
03:04:46", updated_at: "2008-11-04 03:04:46">]]}
>> person.save  #associations are saved in the database

However ror returns the following

>> person = Person.find_by_name("Jack")
>> person.cars
=> [#<Car id: 2, name: "BMW", created_at: "2008-11-04 03:04:46",
updated_at: "2008-11-04 03:04:46">]
>> person.cars=[Car.find_by_name("Porsche"), Car.find_by_name("VW")]  #associations are 
saved in the database
>> person.cars
=> [#<Car id: 1, name: "Porsche", created_at: "2008-11-04 03:04:46",
updated_at: "2008-11-04 03:04:46">, #<Car id: 3, name: "VW",
created_at: "2008-11-04 03:04:46", updated_at: "2008-11-04 03:04:46">]
>> person.changed?
=> false
>> person.changes
=> {}
This topic is locked and can not be replied to.