acts_as_list with has_and_belongs_to_many relationship
Asked Answered
C

4

11

I've found an old plugin called acts_as_habtm_list - but it's for Rails 1.0.0.

Is this functionality built in acts_as_list now? I can't seem to find any information on it.

Basically, I have an artists_events table - no model. The relationship is handled through those two models specifying :has_and_belongs_to_many

How can I specify order in this situation?

Conjugate answered 16/2, 2010 at 17:35 Comment(2)
Could you be more specific? What exactly are you trying to achieve? Also a link to the plugin you found would be nice.Comeback
When looking for the plugin, I found a newer one that I might be able to use: github.com/SFEley/habtm_list I'm trying to accomplish the order of artists at events - say you go to a concert with a headliner and two openers. I'd like for it to show the order that the artists are playing in.Conjugate
R
23

I'm assuming that you have two models - Artist and Event.

You want to have an habtm relationship between them and you want to be able to define an order of events for each artist.

Here's my solution. I'm writing this code from my head, but similar solution works in my case. I'm pretty sure there is a room for improvement.

I'm using rails acts_as_list plugin.

That's how I would define models:

class Artist < ActiveRecord::Base
  has_many :artist_events
  has_many :events, :through => :artist_events, :order => 'artist_events.position'
end

class Event < ActiveRecord::Base
  has_many :artist_events
  has_many :artists, :through => :artist_events, :order => 'artist_events.position'
end

class ArtistEvent < ActiveRecord::Base
  default_scope :order => 'position'
  belongs_to :artist
  belongs_to :event
  acts_as_list :scope => :artist
end

As you see you need an additional model ArtistEvent, joining the other two. The artist_events table should have two foreign ids and additional column - position.

Now you can use acts_as_list methods (on ArtistEvent model, unfortunately) but something like

Artist.find(:id).events

should give you a list of events belonging to specific artist in correct order.

Rival answered 16/2, 2010 at 20:48 Comment(3)
My only qualm with accepting this answer is that I'm using :has_and_belongs_to_many and I don't have a model. Is this code equivalent?Conjugate
has_and_belongs_to_many is considered by many as deprecated. Join model solution gives you the same functionality as habtm method, but is much more flexible.Rival
See Tricia's update below. You have to add a :primary to the intermediate table for this to work.Folly
D
2

Additional update for the accepted answer: for Rails 4 and Rails 5:

has_many :events, -> { order 'artist_events.position ASC' }, through: :artist_events
has_many :artists, -> { order 'artist_events.position ASC' }, through: :artist_events
Despain answered 8/6, 2019 at 14:58 Comment(0)
C
1

I trying with self-referencing like that

class Product < ActiveRecord::Base
  has_many :cross_sales
  has_many :cross_sales_products, :through => :cross_sales, :order => 'cross_sales.position'
end

class CrossSale < ActiveRecord::Base
  default_scope :order => 'cross_sales.position'
  belongs_to :product
  belongs_to :cross_sales_product, :class_name => "Product"
  acts_as_list :scope => :product
end

create_table :cross_sales, :force => true, :id => false do |t|
  t.integer :product_id, :cross_sales_product_id, :position
end

But the field cross_sales.position is never updated ...

An idea ?

Update: Ok the field 'id' it's necessary in the case of additional model with has_many :through option. It's work well now

Collywobbles answered 31/3, 2010 at 20:18 Comment(0)
N
0

In the accepted answer, note that :order => 'artist_events.position' is referencing the table artist_events and not the model.

I ran into this minor hiccup when moving from a habtm association to has_many :through.

Nerin answered 12/7, 2013 at 23:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.