3

I have a data model where a User can like a Project, Suggestion, Comment, or other objects. The models are set up correctly, and likes/show.rabl works if we were just to support the Project child

object @like
attributes :id, :created_at, :target_type, :target_id, :user_id
child :user => :user do
  extends "users/show"
end
child :target do
  node do |project|
    partial('projects/show', :object => project)
  end
end

However, I want to be able to use partials of suggestions/show, comments/show as well depending on target_type.

I tried this but it's not working:

child :target do |u|
  u.target.map do |r|
    if r.is_a?(Suggestion)
      partial("suggestions/show", :object => r)
    elsif r.is_a?(Project)
      partial("projects/show", :object => r)
    end
  end
end

I get undefined method target for <Rabl::Engine:0x69fb988>. However, I don't get this error in the first case. Any ideas?

netwire
  • 7,108
  • 12
  • 52
  • 86

3 Answers3

3

Have you tried using extends instead of partial?

Perhaps you could try something like this?

child :target do |u|
  u.target.map do |r|
    if r.is_a?(Suggestion)
      extends "suggestions/show"
    elsif r.is_a?(Project)
      extends "projects/show"
    end
  end
end

In this case, when you use extends, you don't need to pass in an :object because you're already in the scope of iterating through with the object r.

richsinn
  • 1,341
  • 1
  • 12
  • 27
3

This is what I ended up using and it worked.

Thanks to this post: https://github.com/nesquena/rabl/issues/273#issuecomment-6580713

child :target do
  node do |r|
    if r.is_a?(Suggestion)
      partial("suggestions/show", :object => r)
    elsif r.is_a?(Project)
      partial("projects/show", :object => r)
    end
  end
end
netwire
  • 7,108
  • 12
  • 52
  • 86
1

There is another way to do this, where you do not have to list all possible polymorphic relations. It may be a bit hacky, but it works.

Like this:

child :target do |u|
  # The regexp snippet selects everything from the last / and to the end
  extends u.to_partial_path.gsub(/\/([^\/]+)$/, '/show')
end

This uses the .to_partial_path of your object. If your object is called Suggestion, the .to_partial_path will return suggestions/suggestion. This is why i'm using gsub() to replace whatever comes after / with /show.

With this solution you do not have to update this file each time you add another polymorphic relation. You only have to make sure that the new object has a rabl template called show.json.rabl

Pål
  • 958
  • 2
  • 13
  • 18