开发者

callbacks on active record associations

I have a vacation approval model that has_many :entries is there a way that if I destroy one of those entries to have the rest destroyed? I also want to send one email if they are, but not one for each entry. Is there a way开发者_JAVA技巧 to observe changes to the collection as a whole?


A callback probably isn't a good choice because:

class Entry < ActiveRecord::Base
  def after_destroy
    Entry.where(:vacation_id => self.vacation_id).each {|entry| entry.destroy}
  end
end

would produce some bad recursion.

It could be that you should do it in the controller:

class EntriesController < ApplicationController
  def destroy
    @entry = Entry.find(params[:id])
    @entries = Entry.where(:vacation_id => @entry.vacation_id).each {|entry| entry.destroy}
    #send email here
    ...
  end
end


You can use the before_destroy callback.

class VacationRequest < ActiveRecord::Base
  has_many :entries
end

class Entry < ActiveRecord::Base
  belongs_to :vacation_request
  before_destroy :destroy_others
  def destroy_others
    self.vacation_request.entries.each do |e|
      e.mark_for_destruction unless e.marked_for_destruction?
    end
  end
end

Definitely test that code before you use it on anything important, but it should give you some direction to get started.


I think this ought to work:

class Entry < ActiveRecord::Base
  belongs_to :vacation_request, :dependent => :destroy

  # ...
end

class VacationApproval < ActiveRecord::Base
  has_many :entries, :dependent => :destroy

  # ...
end

What should happen is that when an Entry is destroyed, the associated VacationApproval will be destroyed, and subsequently all of its associated Entries will be destroyed.

Let me know if this works for you.


So What i ended up doing is

class VacationApproval < ActiveRecord::Base
  has_many :entries , :conditions => {:job_id => Job.VACATION.id }, :dependent => :nullify

class Entry < ActiveRecord::Base
  validates_presence_of :vacation_approval_id ,:if => lambda {|entry| entry.job_id == Job.VACATION.id} , :message => "This Vacation Has Been Canceled. Please Delete These Entries."

and then

@entries.each {|entry| entry.destroy if entry.invalid? }

in the index action of my controller. and

`raise "Entries are not valid, please check them and try again ( Did you cancel your vacation? )" if @entries.any? &:invalid?` 

in the submit action

The problem with deleting the others at the same time is if my UI makes 10 Ajax calls to selete 10 rows, and it deletes all of them the first time I end up with 9 unahandled 404 responses, which was undesirable.

Since I don't care it they remain there, as long as the Entry cannot be submitted its OK.

This was the easiest / safest / recursion friendly way for me, but is probably not the best way. Thanks for all your help!


To anyone curious/ seeking info

I ended up solving this later by setting The Vacation APProval model like this

class VacationApproval < ActiveRecord::Base
    has_many :entries , :conditions => {:job_id => Job.VACATION.id }, :dependent => :delete_all
end

and My Entry Model like this

class Entry < ActiveRecord::Base  
  after_destroy :cancel_vacation_on_destory
  def cancel_vacation_on_destory
    if !self.vacation_approval.nil?
      self.vacation_approval.destroy
    end
  end
end

Using :delete_all does not process callbacks, it just deletes them

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜