ruby-on-railsrails-activerecordhas-many-through

has_many when primary_key's are available without a definite model


There is a model named: Author which has many books.

For legacy reasons, there is a column in the authors table, named: favorite_books which is basically an array of the ids of the favorite books by an author.

I'd like to define a has_many association in the Author model to books based on those ids in the favorite_books column. Something like the following:

  class Author < ApplicationRecord
    has_many :books, through: -> { favorite_books } # it's invalid code as of now
  end

Through the documentation, there are options like source & source_type that we can pass, but I'm not sure if it's possible to pass a column.


Solution

  • Unfortunately you can't build an association like that. You have two options

    Define a method like this which will return a collection

    def favorite_books
      Booke.where(id: self.favorite_books)
    end
    

    This is not a full fledged association, so you won't have nice things like author.favourite_books << Book.new and so on.

    Alternative approach, but requiring more work, is to refactor this into many to many relationship between Author and Book. There are two way to go about it in Rails, either has_many through or has_and_belongs_to_many`. Rails Guides has an excellent section on how to choose one over the other https://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many

    Second solution would require a data migration which would possibly be a multi step process:

    Happy to expand the answer if you have any follow up questions.