Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

has_many :through or has_many_and_belongs_to_many support #86

Closed
ghost opened this issue Jun 29, 2013 · 6 comments
Closed

has_many :through or has_many_and_belongs_to_many support #86

ghost opened this issue Jun 29, 2013 · 6 comments

Comments

@ghost
Copy link

ghost commented Jun 29, 2013

Hello,

I have not been able to work out how to make this work with a has_many :through association.

The easiest example I can think of is Playlists have many Songs and Songs belong to many Playlists. The position would have to be added to the intermediary table, because the position can be different in different playlists.

Does this gem support those associations?

@conzett
Copy link
Contributor

conzett commented Jun 30, 2013

It works if you use acts_as_list on the join table. For example if you have a playlist model and a track model you would have the playlists_tracks join table act as the list. I've built an app that does pretty much exactly that, except with issues and multiple trackers as opposed to tracks and lists, so it's very much possible.

@ghost
Copy link
Author

ghost commented Jun 30, 2013

Alright, I did as you said and when adding items not in the list it does add them at the bottom of the list. However updating the object with a different order doesn't trigger any change in the db ( as seen below).

class Playlist < ActiveRecord::Base

    has_many :playlist_contents, ->{ order "position"}c
    has_many :media, through: :playlist_contents, dependent: :destroy
    attr_accessible :medium_ids
end

class PlaylistContent < ActiveRecord::Base
    belongs_to :playlist
    belongs_to :medium
    attr_accessible :position
    acts_as_list scope: :playlist
end

rails console
Loading development environment (Rails 4.0.0)
irb(main):001:0> p = Playlist.first
Playlist Load (0.6ms) SELECT "playlists".* FROM "playlists" ORDER BY "playlists"."id" ASC LIMIT 1
=> #<Playlist id: 1, name: "shita", created_at: "2013-06-29 18:32:30", updated_at: "2013-06-29 21:22:46">

irb(main):002:0> p.medium_ids
=> [2, 3, 1]

irb(main):003:0> p.medium_ids= [1,2,3]
Medium Load (2.0ms) SELECT "media".* FROM "media" WHERE "media"."id" IN (1, 2, 3)
(0.2ms) begin transaction
(0.1ms) commit transaction
=> [1, 2, 3]

irb(main):004:0> p.reload
Playlist Load (2.1ms) SELECT "playlists".* FROM "playlists" WHERE "playlists"."id" = ? LIMIT 1 [["id", 1]]
=> #<Playlist id: 1, name: "shita", created_at: "2013-06-29 18:32:30", updated_at: "2013-06-29 21:22:46">

irb(main):005:0> p.medium_ids
=> [2, 3, 1]

irb(main):006:0> p.update_attributes medium_ids: [1,2,3]
(0.2ms) begin transaction
Medium Load (1.4ms) SELECT "media".* FROM "media" WHERE "media"."id" IN (1, 2, 3)
(0.1ms) commit transaction
=> true

irb(main):007:0> p.reload
Playlist Load (1.4ms) SELECT "playlists".* FROM "playlists" WHERE "playlists"."id" = ? LIMIT 1 [["id", 1]]
=> #<Playlist id: 1, name: "shita", created_at: "2013-06-29 18:32:30", updated_at: "2013-06-29 21:22:46">

irb(main):008:0> p.medium_ids
(1.7ms) SELECT "media".id FROM "media" INNER JOIN "playlist_contents" ON "media"."id" = "playlist_contents"."medium_id" WHERE "playlist_contents"."playlist_id" = ? ORDER BY position [["playlist_id", 1]]
=> [2, 3, 1]


The same thing happens when updating p.playlist_contents_ids.

Do you know why that doesn't work, or might you have any code or documentation I can look at to understand why this isn't working?

@conzett
Copy link
Contributor

conzett commented Jun 30, 2013

When you're executing p.update_attributes medium_ids: [1,2,3] are you trying to move multiple items at once, or are just trying to move item 1 to position one?

If you're just trying to move one item you can achieve the automatic list reordering just updating that item's position.

p.playlist_contents.where(id: 1).first.update_attributes(position: 1) Will move the playlist content to position 1 and shuffle the other items correctly in the list. This is because acts_as_list works via an after_update callback on the model that is acting as a list item.

@ghost
Copy link
Author

ghost commented Jun 30, 2013

I had to remove a post in between, because it was just wrong.

I'm trying to do a big update. The user will move around items in the list and click on "Save".

@conzett
Copy link
Contributor

conzett commented Jun 30, 2013

This might be a little tricky with the way acts_as_list was designed, where it re-roders the list after saving each individual list item. A bulk update could be accomplished with a callback after the playlist is saved where it loops through each changed playlist_content item and calls insert_at on it. This would execute the same number of SQL queries as updating each list item individually though.

@brendon
Copy link
Owner

brendon commented Apr 17, 2016

I'm closing this for now due to inactivity.

@brendon brendon closed this as completed Apr 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants