Robert Hulme
2006-Jul-20 14:59 UTC
[Rails] How can I make has_many prevent a delete that would lead to orphans?
e.g. class Asset < ActiveRecord::Base validates_presence_of :asset_number, :make, :model, :location, :name, :serial_number validates_numericality_of :asset_number validates_uniqueness_of :asset_number belongs_to :user belongs_to :location belongs_to :asset_type, :foreign_key => ''type_id'' end class Location < ActiveRecord::Base validates_presence_of :name validates_uniqueness_of :name has_many :assets end If I create a Location, with name ''London'' and then create an Asset with that location it makes sense for me to be able to delete the asset but not to delete the location. If the location is deleted I have a situation where the asset now has a foreign key pointing to a non-existant record. In other words it become orphaned. I know that there are ways (in http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html) to make the foreign keys be set to null, or to delete all the orphans (a bit like ON DELETE CASCADE), but what I want is to prevent the delete of the location if it has assets which belong to it. I was expecting some way to do this would be fairly easy and built into AR but my hopes of that are fading... Hopefully it''s just that I''ve missed something though. If there is no way to do it that is built into AR how might I mod AR or something to add that functionality? Presumably some kind of call to location.assets.is_empty? to check if the delete is going to be allowed? -Rob -- ------------------------------------------------------ "On two occasions, I have been asked [by members of Parliament], ''Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?'' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question." -- Charles Babbage (1791-1871) "98.5% of DNA is considered to be junk DNA with no known purpose. Maybe it''s XML tags." -- Anon http://www.robhulme.com/ http://robhu.livejournal.com/
Daniel N
2006-Jul-20 15:08 UTC
[Rails] How can I make has_many prevent a delete that would lead to orphans?
On 7/21/06, Robert Hulme <rob@robhulme.com> wrote:> > e.g. > > class Asset < ActiveRecord::Base > validates_presence_of :asset_number, :make, :model, :location, > :name, :serial_number > validates_numericality_of :asset_number > validates_uniqueness_of :asset_number > belongs_to :user > belongs_to :location > belongs_to :asset_type, :foreign_key => ''type_id'' > end > > class Location < ActiveRecord::Base > validates_presence_of :name > validates_uniqueness_of :name > has_many :assets > end > > > If I create a Location, with name ''London'' and then create an Asset > with that location it makes sense for me to be able to delete the > asset but not to delete the location. > > If the location is deleted I have a situation where the asset now has > a foreign key pointing to a non-existant record. In other words it > become orphaned. > > I know that there are ways (in > > http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html > ) > to make the foreign keys be set to null, or to delete all the orphans > (a bit like ON DELETE CASCADE), but what I want is to prevent the > delete of the location if it has assets which belong to it. > > I was expecting some way to do this would be fairly easy and built > into AR but my hopes of that are fading... Hopefully it''s just that > I''ve missed something though. > > If there is no way to do it that is built into AR how might I mod AR > or something to add that functionality? Presumably some kind of call > to location.assets.is_empty? to check if the delete is going to be > allowed? > > -Rob > > -- > ------------------------------------------------------ > "On two occasions, I have been asked [by members of Parliament], > ''Pray, Mr. Babbage, if you put into the machine wrong figures, will > the right answers come out?'' I am not able to rightly apprehend the > kind of confusion of ideas that could provoke such a question." > -- Charles Babbage (1791-1871) > > "98.5% of DNA is considered to be junk DNA with no known purpose. > Maybe it''s XML tags." -- Anon > > http://www.robhulme.com/ > http://robhu.livejournal.com/ > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >I think a before_destroy on the Location should automatically stop the destroy action if a false is returned. before_destroy :check_assets protected def check_assets self.assets.count == 0 end -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060720/e4dd2b90/attachment.html
Robert Hulme
2006-Jul-20 15:16 UTC
[Rails] How can I make has_many prevent a delete that would lead to orphans?
> I think a before_destroy on the Location should automatically stop the > destroy action if a false is returned. > > before_destroy :check_assets > > protected > > def check_assets > self.assets.count == 0 > endThanks - that does work, but it makes me wonder why there isn''t a built in way of saying to behave like this whenever there is a has_many relationship. Wouldn''t that be a sensible default? Otherwise you end up with orphans so when you come to say list the assets Rails blows up. Is there a simple way to propogate an error up ''Some assets still use this location'' or something? -Rob -- ------------------------------------------------------ "On two occasions, I have been asked [by members of Parliament], ''Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?'' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question." -- Charles Babbage (1791-1871) "98.5% of DNA is considered to be junk DNA with no known purpose. Maybe it''s XML tags." -- Anon http://www.robhulme.com/ http://robhu.livejournal.com/
Daniel N
2006-Jul-20 15:23 UTC
[Rails] How can I make has_many prevent a delete that would lead to orphans?
On 7/21/06, Robert Hulme <rob@robhulme.com> wrote:> > > I think a before_destroy on the Location should automatically stop the > > destroy action if a false is returned. > > > > before_destroy :check_assets > > > > protected > > > > def check_assets > > self.assets.count == 0 > > end > Thanks - that does work, but it makes me wonder why there isn''t a > built in way of saying to behave like this whenever there is a > has_many relationship. > > Wouldn''t that be a sensible default? Otherwise you end up with orphans > so when you come to say list the assets Rails blows up. > > Is there a simple way to propogate an error up ''Some assets still use > this location'' or something? > > -Rob > > -- > ------------------------------------------------------ > "On two occasions, I have been asked [by members of Parliament], > ''Pray, Mr. Babbage, if you put into the machine wrong figures, will > the right answers come out?'' I am not able to rightly apprehend the > kind of confusion of ideas that could provoke such a question." > -- Charles Babbage (1791-1871) > > "98.5% of DNA is considered to be junk DNA with no known purpose. > Maybe it''s XML tags." -- Anon > > http://www.robhulme.com/ > http://robhu.livejournal.com/ > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >This could be a good plugin / patch to write and submit to the core team. It does seem like a good default behavior. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060720/4010f2d8/attachment.html
Kevin Olbrich
2006-Jul-20 15:48 UTC
[Rails] How can I make has_many prevent a delete that would lead
On Thursday, July 20, 2006, at 4:15 PM, Robert Hulme wrote:>> I think a before_destroy on the Location should automatically stop the >> destroy action if a false is returned. >> >> before_destroy :check_assets >> >> protected >> >> def check_assets >> self.assets.count == 0 >> end >Thanks - that does work, but it makes me wonder why there isn''t a >built in way of saying to behave like this whenever there is a >has_many relationship. > >Wouldn''t that be a sensible default? Otherwise you end up with orphans >so when you come to say list the assets Rails blows up. > >Is there a simple way to propogate an error up ''Some assets still use >this location'' or something? > >-Rob > >-- >------------------------------------------------------ >"On two occasions, I have been asked [by members of Parliament], >''Pray, Mr. Babbage, if you put into the machine wrong figures, will >the right answers come out?'' I am not able to rightly apprehend the >kind of confusion of ideas that could provoke such a question." >-- Charles Babbage (1791-1871) > >"98.5% of DNA is considered to be junk DNA with no known purpose. >Maybe it''s XML tags." -- Anon > >http://www.robhulme.com/ >http://robhu.livejournal.com/ >_______________________________________________ >Rails mailing list >Rails@lists.rubyonrails.org >http://lists.rubyonrails.org/mailman/listinfo/railsIIRC, the default behavior is to destroy all children of a record when it is destroyed. Of course the best solution here would be for you to protect the record at the controller level too. Here are a couple of strategies you can use. 1. a helper method for the model like ''can_destroy?'' so you can do something like this.. def destroy @item = Item.find(params[:id]) if @item.can_destroy? @item.destroy flash[:notice] = ''record destroyed'' else flash[:warning] = ''record not destroyed'' end end 2. having the before_destroy callback raise an exception... def destroy begin Item.destroy(params[:id]) flash[:notice] = ''record destroyed'' rescue flash[:warning] = ''record not destroyed'' end end I would probably go with the first one and write a function that recursively tests all the children for dependents. Otherwise, you might end up with a partial destroy if the rails first tries to destroy a dependent object that has no children before encountering one that did. _Kevin www.sciwerks.com -- Posted with http://DevLists.com. Sign up and save your mailbox.
Robert Hulme
2006-Jul-21 15:37 UTC
[Rails] How can I make has_many prevent a delete that would lead to orphans?
> This could be a good plugin / patch to write and submit to the core team. > It does seem like a good default behavior.If someone could tell me how I could sensibly bubble up an exception / error code or something that would fit into how things are done in rails I''ll look at making a patch for core. -- ------------------------------------------------------ "On two occasions, I have been asked [by members of Parliament], ''Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?'' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question." -- Charles Babbage (1791-1871) "98.5% of DNA is considered to be junk DNA with no known purpose. Maybe it''s XML tags." -- Anon http://www.robhulme.com/ http://robhu.livejournal.com/