Hello,
I’ve tried to set up a class with acts_as_list with a scope argument
that restricts a list to records with the same foreign key.
For example :
database :
CREATE TABLE families
(
id
int(11) NOT NULL auto_increment,
name
varchar(255) NOT NULL default ‘’,
PRIMARY KEY (id
)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
INSERT INTO families
VALUES (1, ‘Smith’);
INSERT INTO families
VALUES (2, ‘Jones’);
CREATE TABLE people
(
id
int(11) NOT NULL auto_increment,
name
varchar(255) NOT NULL default ‘’,
family_id
int(11) default NULL,
position
int(5) NOT NULL default ‘0’,
PRIMARY KEY (id
)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
INSERT INTO people
VALUES (1, ‘Robert’, 1, 1);
INSERT INTO people
VALUES (2, ‘Brian’, 1, 2);
INSERT INTO people
VALUES (3, ‘John-Paul’, 2, 1);
INSERT INTO people
VALUES (4, ‘Grace’, 2, 2);
class Family < ActiveRecord::Base
has_many :people
end
class Person < ActiveRecord::Base
belongs_to :family, :order => ‘position’
acts_as_list :scope => ‘family_id’
validates_uniqueness_of :position, :scope => ‘family_id’
end
Now, all this works fine, I can execute commands like
person.move_higher, person.move_to_bottom, etc. So the class behaves as
expected with acts_as_list, updating the position column all by itself :
@person = Person.find_by_id(2)
=> #<Person:0x239cd64 @attributes={“family_id”=>“1”, “name”=>“Brian”,
“id”=>“2”, “position”=>“2”}>@person.move_higher
=> true@person.position
=> 1
Except for one thing : when I change a Person’s scope (thus changing the
value for family_id), nothing gets updated except the scope value. The
position column doesn’t change :
@person.family_id = 2
=> 2@person
=> #<Person:0x239cd64 @attributes={“family_id”=>2, “name”=>“Brian”,
“id”=>“2”, “position”=>1}>
I would expect the “acts_as_list with scope” behavior to ;
a) update all the positions of the objects in the original scope to mend
the gap left by the departure of the updated record moved to another
scope,
b) the moved object to be added to the bottom of the list corresponding
to its new family_id scope.
This appears not to be the case.
The validation method raises an error if the position of the object to
update already exists in the new scope (though not in console).
This is what I have tried, although not working. I somehow can’t access
params() from the callback method, and I can’t figure out what’s wrong.
class Person < ActiveRecord::Base
belongs_to :family, :order => ‘position’
acts_as_list :scope => ‘family_id’
validates_uniqueness_of :position, :scope => ‘family_id’
before_validation_on_update :reorder_positions
private
def reorder_positions
@updated_family_id = params[:person][:family_id]
unless @updated_family_id == self.family_id
self.move_to_bottom # reorder original list
params[:person][:family_id] =
Family.find_by_id(@updated_family_id).people.length + 1
end
end
end
When I update a Person by changing its family_id, I get this error
message :
“undefined local variable or method `params’ for #Person:0x22e5060”
Can someone help me figure it all out?
Am I making this more complicated than it really is?
Thanks in advance !
Bernard.