Hi,
I have two objects, lets call them Collection and Foobar (see below). I want to be able to specify the order of foobars in a collection using e.g.
@collection.foobar_order = [4, 2, 1, 0, 3] @collection.save
In irb (script/console), stuff like "a = [:a,:b, :c] ; a = [1 2 0].collect {|x| a}" works fine. Also in irb, "self.foobar_order.collect { |x| self.foobars }" correctly returns the re-sorted elements. However, in Collection#do_reorder, "self.foobars = ..." does not update the object's "foobars".
Why?
Thank you!
Code:
def Collection < AR::Base has_many :foobars, :order => :position before_validation :do_reorder private def do_reorder self.foobars = self.foobar_order.collect { |x| self.foobars } self.foobars.each_with_index do |f,i| f.position = i # save position in DB for later fetching in correct order end end end
def Foobar < AR::Base belongs_to :collection end
Additional info (not strictly needed for my question):
I have looked at acts_as_list's features, but I do not need to move objects up and down, and acts_as_list also has the (big) downside of acting directly on the DB, and not updating the object instances. All objects get loaded once and all sorting is done use a Scriptaculous Sortable instance using pure JS, no AJAX (= no server load). Upon form submit, Sortable saves the current sorting order as an array in a hidden field called "foobar_order", which is then used by the above code.
Possibly related question: I have tried to implement Array#reorder and Array#reorder! (in-place) using the above code like
def Array # e.g. " a=[:a,:b,:c] ; o=[1 2 0] ; a.reorder(o) #=> [:b, :c, :a] def reorder(o) o.collect {|x| self } end def reorder!(o) self = self.reorder(o) end end
reorder works, but reorder! does not work since you cannot assign something to "self". How would you implement in-place reordering of Arrays? Perhaps even without having to create copies (since it might be an Array of AR objects)?
Thank you!
Jens