# Reordering associated "has\_many" objects

**URL:** <https://www.ruby-forum.com/t/reordering-associated-has-many-objects/157503>\
**Category:** Rails\
**Created:** [January 12, 2009, 12:23pm UTC](https://www.ruby-forum.com/t/reordering-associated-has-many-objects/157503 "2009-01-12T12:23:24Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![jens](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/d2c977/32.png) [@jens](https://www.ruby-forum.com/u/jens)\
**Post date:** [January 12, 2009, 12:23pm UTC](https://www.ruby-forum.com/t/reordering-associated-has-many-objects/157503/1 "2009-01-12T12:23:24Z")

</div>

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[x]}” works fine.  
Also in irb, “self.foobar\_order.collect { |x| self.foobars[x] }”  
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[x] }  
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[x] }  
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

---

<div class="post-metadata">

**Author:** ![jens](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/d2c977/32.png) [@jens](https://www.ruby-forum.com/u/jens)\
**Post date:** [January 12, 2009, 12:59pm UTC](https://www.ruby-forum.com/t/reordering-associated-has-many-objects/157503/2 "2009-01-12T12:59:53Z")

</div>

On 12 Jan 2009, at 11:22, Jens wrote:

> In irb (script/console), stuff like “a = [:a,:b, :c] ; a = [1 2  
> 0].collect {|x| a[x]}” works fine.  
> Also in irb, “self.foobar\_order.collect { |x| self.foobars[x] }”  
> correctly returns the re-sorted elements.  
> However, in Collection#do\_reorder, “self.foobars = …” does not  
> update the object’s “foobars”.

Because it’s not an actual array you’re assigning to. It’s futzing  
with db stuff and actually doesn’t touch objects that don’t need to be  
added/removed to the collection. The relevant bit of code is at

> <https://github.com/rails/rails/blob/2-2-stable/activerecord/lib/active_record/associations/association_collection.rb#L309>

Fred

> before\_validation :do\_reorder  
> def Foobar \< AR::Base  
> belongs\_to :collection  
> 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)?

Look at Array#replace (and either way right now you’re not copying AR  
objects)
