1

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

chodorowicz
  • 1,062
  • 1
  • 15
  • 19

1 Answers1

1

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
Björn Nilsson
  • 3,703
  • 1
  • 24
  • 29
  • Thanks a a lot! Your code was almost perfect and guided me to sth what seems to work. I had a problem with attr_reader and my form (they fail when composition and artist are not initialized). I've wrote sth like this (can it be done better?) http://pastebin.com/7WvCaDBZ I've also changed saving to this, since I want to have always unique pairs of artist and composition: http://pastebin.com/ZapzvBF5 – chodorowicz Jul 29 '11 at 12:55
  • A better way to do this is to not use composition_name or artist_name at all. just access transcription.composition.artist.name and transcription.composition.name. Read about "nested forms" and I'm sure you will get some good ideas. http://guides.rubyonrails.org/2_3_release_notes.html#nested-object-forms If something seems awkward in rails there is very likely a better way of doing it. – Björn Nilsson Jul 29 '11 at 22:04
  • Thanks a lot again for guiding me through. I'll probably stay for the time with the current solution since almost all examples for nested forms are when you have child models inside your form. I have it on opposite direction (belongs_to is the main model). I've found several examples when belongs_to model is the main model for the form, but I haven't found any examples with two level deep association as I have. This could get complex... – chodorowicz Jul 30 '11 at 15:37