Hi Mark,
In the trunk version of better nested set, parent_id is a protected
attribute.This prevents data corruption: if someone updated the
parent_id without changing the lft/rgt values, queries using lft/rgt
would produce incorrect results.
So instead of
n = Node.create(:parent_id => 3) # will be ignored
you need to use the move_to methods
n = Node.create
n.move_to_child_of(3) # sets the parent and updates the lft/rgt values
If for some reason you need to get around this, you can use
Node.update_all, specifying the id of the record. If you are migrating
a large amount of data, it may be faster to set the parent_ids with
update_all, then when you have them loaded, run #renumber_all to set
the lft/rgt values.
Regards,
Krishna
On 3/18/07, Mark Noten <mark.noten at itfc.be>
wrote:> Hi all,
>
> I''m using better nested set (trunk revision 52) with Rails 1.2.2
and
> ruby 1.8.5 (2006-12-25 patchlevel 12) [x86_64-linux]. I''m having a
> problem with a data migration where the parent_id is always nil even
> when I set it for a child. I created a parent "ben_kunnen" and
add a
> child "Noten Mark" to it with this migration:
>
> class AddAgentsData < ActiveRecord::Migration
> def self.up
> down
> dela = Product.find_or_create_by_name(''DELA'')
> level_1 = dela.levels.detect{ |l| l.code == ''1'' }
> level_3 = dela.levels.detect{ |l| l.code == ''3'' }
> ben_kunnen = Agent.create(:last_name => "Kunnen",
:first_name =>
> "Ben", :identification => "BKU", :product_id =>
dela.id, :parent_id =>
> nil, :level_id => level_3.id)
> Agent.create(:last_name => "Noten", :first_name =>
"Mark",
> :identification => "MNO", :product_id => dela.id,
:parent_id =>
> ben_kunnen.id, :level_id => level_1.id)
> end
>
> def self.down
> Agent.delete_all
> end
> end
>
> mysql> select * from agents;
>
+----+-----------+------------+----------------+------------+-----------+-----+-----+----------+
> | id | last_name | first_name | identification | product_id | parent_id
> | lft | rgt | level_id |
>
+----+-----------+------------+----------------+------------+-----------+-----+-----+----------+
> | 1 | Kunnen | Ben | BKU | 1 | NULL
> | 1 | 2 | 4 |
> | 2 | Noten | Mark | MNO | 1 | NULL
> | 3 | 4 | 2 |
>
+----+-----------+------------+----------------+------------+-----------+-----+-----+----------+
>
> The parent_id column for the child "Noten Mark" remais always
NULL in
> the database.
>
> The agent model is quite simple:
>
> class Agent < ActiveRecord::Base
> acts_as_nested_set :scope => :product_id
> belongs_to :level
> has_many :proposals
>
> validates_presence_of :last_name, :first_name, :identification,
> :product_id, :level_id
> validates_length_of :last_name, :first_name, :maximum => 30
> validates_length_of :identification, :maximum => 10
> validates_uniqueness_of :identification, :scope => :product_id
> # left out some methods that are not called in the migration
> end
>
> I tried the same statements in my Rails console and it gave me the same
> results:
>
> $>script/console
> Loading development environment.
> >> dela = Product.find_or_create_by_name(''DELA'')
> => #<Product:0x2aaaae15d1b8
> @attributes={"image_url"=>"/images/logo-dela.gif",
"name"=>"DELA",
> "id"=>"1", "description"=>"DELA is
de specialist in uitvaartverzekering
> en -verzorging met meer dan 70 jaar ervaring."}>
> >> level_1 = dela.levels.detect{ |l| l.code == ''1''
}
> => #<Level:0x2aaaae13fe88
@attributes={"name"=>"Verkoper",
"code"=>"1",
> "product_id"=>"1", "id"=>"2",
"description"=>nil,
> "commission_per_unit"=>"6.20"}>
> >> level_3 = dela.levels.detect{ |l| l.code == ''3''
}
> => #<Level:0x2aaaae13fde8
@attributes={"name"=>"Sectorchef",
> "code"=>"3",
"product_id"=>"1", "id"=>"4",
"description"=>nil,
> "commission_per_unit"=>"9.17"}>
> >> ben_kunnen = Agent.create(:last_name => "Kunnen",
:first_name =>
> "Ben", :identification => "BKU", :product_id =>
dela.id, :parent_id =>
> nil, :level_id => level_3.id)
> => #<Agent:0x2aaaae0b0d00 @new_record=false,
@attributes={"level_id"=>4,
> "identification"=>"BKU", "lft"=>1,
"product_id"=>1, "id"=>3,
> "first_name"=>"Ben", "rgt"=>2,
"parent_id"=>nil, "last_name"=>"Kunnen"},
> @errors=#<ActiveRecord::Errors:0x2aaaae0adf88 @errors={},
> @base=#<Agent:0x2aaaae0b0d00 ...>>,
@new_record_before_save=true>
> >> ben_kunnen.id
> => 3
> >> Agent.create(:last_name => "Noten", :first_name
=> "Mark",
> :identification => "MNO", :product_id => dela.id,
:parent_id =>
> ben_kunnen.id, :level_id => level_1.id)
> => #<Agent:0x2aaaae088df0 @new_record=false,
@attributes={"level_id"=>2,
> "identification"=>"MNO", "lft"=>3,
"product_id"=>1, "id"=>4,
> "first_name"=>"Mark", "rgt"=>4,
"parent_id"=>nil, "last_name"=>"Noten"},
> @errors=#<ActiveRecord::Errors:0x2aaaae086078 @errors={},
> @base=#<Agent:0x2aaaae088df0 ...>>,
@new_record_before_save=true>
> >> ben_kunnen.id
> => 3
>
> You can see that the parent_id column of the child "Mark Noten"
is nil.
> The strange thing is that when I execute above the statement
> ben_kunnen.id then it gives me the right id! So why can''t I use
the
> statement ben_kunnen.id set it set the right value for the child "Mark
> Noten"?
>
> Can anyone help me with this?
>
> Kind regards,
>
> Mark Noten
> Software engineer
> ITFC gcv
> E-mail: mark.noten at itfc.be
> GSM: +32 (484) 698 333
>
> _______________________________________________
> Betternestedset-talk mailing list
> Betternestedset-talk at rubyforge.org
> http://rubyforge.org/mailman/listinfo/betternestedset-talk
>