Consider the following polymorphic relationship
class Person
has_many :photos, :as => :attachable
end
class Animal
has_many :photos, :as => :attachable
end
class Photo
belongs_to :attachable, :polymorphic => true
end
The view pages of a Person or Animal object contains a gallery of their respective photos.
The pages contain the following code:
...
<%= link_to(image_tag(photo.image_url(:thumb).to_s), [@attachable, photo]) %>
...
However in the view page of my photo, I want to present different information depending on whether it belongs to a Person or an Animal. For example, if it is a Person it should display his/her height, list of pets; if it is an Animal, it should display its breed, owner, etc.
What is the best solution to do this?
I can think of two possible solutions:
One way could be to direct to a separate controller action in the photo for each class.
Something like
<%= link_to(image_tag(photo.image_url(:thumb).to_s), show_person_path[@attachable, photo]) %>
<%= link_to(image_tag(photo.image_url(:thumb).to_s), show_animal_path[@attachable, photo]) %>
However I think this approach introduces improper delegation of view logic in the polymorphic class.
Another approach is to introduce a controller action in each Person and Animal class to display their corresponding information. The gallery should link to this action instead of the one above, and the action should render the photo.
However I feel like the corresponding information to be displayed is only few to merit its own action for each of the class. Maybe helpers are enough, but I am not sure of the right approach (please correct me if the above assumptions are true).
If the differences between Animal and Person do not justify a separate controller, you could have one controller and in the action for the gallery, just render different views based on the type of your @attachable:
The only downside I see here is that you would need to come back and extend the logic whenever you introduce a new type of attachable. You could add a default gallery view to mitigate this.