loading...

Dynamic view with STI in Rails

n350071 profile image n350071🇯🇵 ・1 min read

🤔 Situation

I have a STI model named Media which has two chirdren models which are Photo and Video. And I've wanted to not change the view logic by each class.

Example

<% @album.media.each do |medium| %>
  <div>
    <%= file_content(medium) %>
  </div>
<% end %>

😅 But I didn't want to write like this.

If I ask object about class and then switch the logic, it's not OOP anymore. I have to write again when I add a new class like 'text', 'sound'.

module MediaHelper
  def file_content(medium)
    return nil unless medium.file.attached?
    if medium.class == Photo
      return photo_content(medium)
    else
      return video_content(medium)
    end
  end
end

👍 How have I solved it?

I wrote the helper like this.

module MediaHelper
  def file_content(medium)
    return nil unless medium.file.attached?
    send("#{medium.class.name.underscore}_content", medium)
  end
end
module PhotosHelper
  def photo_content(medium)
    # do something
  end
end

module VideosHelper
  def video_content(medium)
    # do something
  end
end

🦄 But, I believe there is a better way.

I don't know it works. But I hope I will change my code like this.

1. remove the parent helper

# module MediaHelper
#   def file_content(medium)
#     return nil unless medium.file.attached?
#     send("#{medium.class.name.underscore}_content", medium)
#   end
# end

2. align the children's helper names.

module PhotosHelper
  def file_content(medium)
    # do something
  end
end

module VideosHelper
  def file_content(medium)
    # do something
  end
end

Posted on by:

n350071 profile

n350071🇯🇵

@n350071

Ruby Web Developer. Freelancer. Tokyo.

Discussion

pic
Editor guide