kibaekr
kibaekr

Reputation: 1349

Rails: changing existing association from "Has_many, Belongs_to" gracefully?

Currently, a User can create a Track(just think of document). Users can also bookmark these tracks. I would like to add a Co-Author feature, where many users can edit a single track. How would I change the existing 'User has_many tracks, Tracks belong_to User' relationship, while maintaining the current author?

User.rb:

#authors(creates) track
has_many :creations, :class_name => "Track", :foreign_key => "author_id"

#bookmarks track
has_many :track_users
has_many :tracks, :through => :track_users 

Track.rb:

belongs_to :author, :class_name => "User", :foreign_key => "author_id"

#bookmarked users
has_many :track_users
has_many :users, :through => :track_users 

Would I just have to create another join table like I did with bookmarking(":through => :track_users"), and use a script to move the authors to the new join table?

Upvotes: 0

Views: 522

Answers (1)

jvnill
jvnill

Reputation: 29599

you can go with this at least 2 ways

  1. keep the author association and just create a join table. you can probably use habtm with this one if you're not planning on adding more attributes on this join table
  2. you can drop author_id on track and add an author boolean to the join table.

i prefer the second solution so let's do that. create a migration that creates the join table and moves the author to the join table

def up
  create_table :track_authors do |t|
    t.integer :user_id
    t.integer :track_id
    t.boolean :author, default: false
  end

  add_index :track_authors, :user_id
  add_index :track_authors, :track_id

  # let's call the join table track_authors
  Track.find_each do |track|
    TrackAuthor.create(user_id: track.author_id, track_id: track.id, author: true)
  end
end

then in your model, you can do this

# track.rb
has_many :track_authors
has_many :authors, through: :track_authors
has_one :author, through: :track_authors, conditions: { track_authors: { author: true } }

# track_author.rb
belongs_to :author, class_name: 'User'
belongs_to :track

# user.rb
has_many :track_authors
has_many :tracks, through: :track_authors
has_many :authored_trackes, through: :track_authors, conditions: { track_authors: { author: true } }

Upvotes: 1

Related Questions