Search code examples
ruby-on-railsbelongs-tovirtual-attribute

Setting model association in Rails - saving 'from grandchild side'


I'm a Ruby newbie so please forgive if some of these is complete ignorance. I want to set following associations:

  • Transcription belongs to Composition
  • Composition has many transcriptions, belongs to Artist
  • Artist has many compositions (and transcriptions through compositions)

I don't want to have any stand-alone forms for creating compositions and artists. Users just create transcriptions - the form for transcription has text fields fort artist and composition and database entries should be dynamically created (if they don't already exist).

How should I set up models? Should I use some virtual attributes in Transcription?

# transcription.rb
def artist_name
  artist.name if self.artist
end

def artist_name=(name)
  self.artist = Artist.find_or_create_by_name(name) unless name.blank?
end 

and later create Composition with find_or_create_by_name using artist I've found or created before?

Any help appreciated! Thanks in advance


Solution

  • You can't set artist in transcription because Artist has many Compositions and not Transcriptions, you need to access Artist through Composition. I hope this code explains it better.

    I'm tired and probably messed something up but here we go (not tested):

    # transcription.rb
    
    attr_writer :composition_name, :artist_name
    before_save :set_artist_and_composition
    validates_presence_of :artist_name, :composition_name
    
    def composition_name
      composition.name
    end
    
    def artist_name
      composition.artist.name
    end
    
    def set_artist_and_composition
      artist = Artist.find_or_create_by_name(@artist_name)
      self.composition = Composition.find_or_create_by_name(@composition_name)
      self.composition.artist = artist
    end