Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow after_add callback #35

Open
jcm opened this issue Aug 12, 2011 · 3 comments
Open

allow after_add callback #35

jcm opened this issue Aug 12, 2011 · 3 comments

Comments

@jcm
Copy link

jcm commented Aug 12, 2011

Hi,

What do you think of adding an :after_add option for the has_any :children relation ?
It would allow to cleanly set some fields that ibherits from parent when creating children with
model.children.build (for a nested form for instance)

@skyeagle
Copy link
Owner

Does this can't be done with AR callbacks in special case? I am not really understand what do you suggest. Try to be more clear, please. It will much better if you provide an example.

@jcm
Copy link
Author

jcm commented Aug 16, 2011

Hi,

Here is a detailed example.

After_add is an AR callback :
http://edgeguides.rubyonrails.org/association_basics.html chapter 4.5

It's the only solution to be able to setup some initialization dependant from the parent to a newly created child before a nested form, for instance. A before_create callback is called only when saving a new record, and to prepare objects for a nested form, they need to be only built but not created. I tried too to write an after_initialize method, but there the parent_id (from the relation) is not set and therefore, cannot be accessed to inherit.

Example with a simple Flower model:

> rails new nestedsettest -J -d postgresql
> cd nestedsettest
> echo "gem 'nested_set', '~> 1.6.7'" >> Gemfile
> bundle install
> rails g scaffold Flower ref:string seeded_at:date species_id:integer parent_id:integer lft:integer rgt:integer
> rake db:create
> rake db:migrate
> rails console
>> f1 = Flower.create( :species_id =>1, :ref => "Rose 1", :seeded_at => DateTime.now )
>> f2 = Flower.create( :species_id =>2, :ref => "Camelia 1", :seeded_at => DateTime.now )
>> f3 = f2.children.build
=> #<Flower id: nil, ref: nil, seeded_at: nil, species_id: nil, parent_id: 2, lft: nil, rgt: nil, created_at: nil, updated_at: nil>

I would like to have the species_id inherit from the parent. The only callback to set values in a has_many.build call is :after_add.

Let's change the Flower model:

class Flower < ActiveRecord::Base
#  acts_as_nested_set
  belongs_to :parent, :class_name => 'Flower', :foreign_key => :parent_id
  has_many :children, :class_name => 'Flower', :foreign_key => :parent_id, :after_add => :populate

  def populate(f)
    f.species_id = f.parent.species_id
  end
end

Now in console:

>> f2 = Flower.find 2
>> f3 = f2.children.build
=> #<Flower id: nil, ref: nil, seeded_at: nil, species_id: 2, parent_id: 2, lft: nil, rgt: nil, created_at: nil, updated_at: nil>

The species was correctly set by the callback.

I simply wish I could do it with

class Flower < ActiveRecord::Base
  acts_as_nested_set :after_add => :populate

  def populate(f)
    f.species_id = f.parent.species_id
  end
end

which implies adding an option to pass an after_add method name.

@skyeagle
Copy link
Owner

Ah.. Ok. But I don't see a big difference with before_save callback. If you need this functionality feel free to provide a pull request and I'll merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants