Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
577 views
in Technique[技术] by (71.8m points)

ruby on rails - Refactor association out of view from a loop

Just getting started in rails and trying to refactor down a bit of my view, and I'm a bit stumped as to where to go for the answer since I'm inside an each loop I need access to the |item|.

I'm pulling the writer from a CSV file, using a creator table and a HABTM assocation with books. The reason is sometimes the writer is also the illustrator and also the editor, I didn't want 3 (and more maybe) tables for each specific role of a book author.

Books Model ( with CSV import )

    writer = Creator.where(name: row['writer']).first_or_create!(row.to_hash.slice(:writer))
    book.creators << writer
    book.writer_id = writer.id

Book View

   books.each do |book|
     link_to book.creators.detect{|w| w.id == book.writer_id}.name, creator_path(id: book.writer_id)

And then I duplicate that for artist, editor, etc...

I first tried a @books in the controller, but I need to know which book from the loop. I'm not sure the next step to learn about so I can remove the ugly. I've seen lots of things I want to go read up on, but not sure which suits this need. Helpers? Named scopes?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Part of the complexity here is introduced by the fact by using writer_id etc. instead of an actual association, which would probably make things a little bit easier. If you're going to stick with your current structure though, what you have is probably pretty close to what you want, although you may want to change that link_to line to the more simple:

link_to book.creators.find(book.writer_id).name, creator_path(book.writer_id)

Another option would be to setup custom getter method for writer and illustrator in your model, which would let you simplify things even more:

# book.rb
def writer
  creators.find(writer_id) # This should allow you to still eager load it if you want
end

def illustrator
  creators.find(illustrator_id)
end

# in your view
link_to book.writer.name, creator_path(book.writer_id)

(You could also write setter methods, although this would be a little bit more complex, and possibly not worth it unless you're planning on changing the creators.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...