Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With Active Model Serializers, how do you render a partial?

I'm creating a newsfeed and have a JSON response set up with Active Model Serializers gem. I'd like to render a regular ERB partial and have it as one of the attributes in the JSON.

controllers/posts_controller.rb:

def index
  @posts = Post.all
  respond_to do |format|
    format.json { render json: @posts.to_a, each_serializer: PostSerializer }
  end
end

serializers/post_serializer.rb:

def event_html
  ApplicationController.new.render_to_string(:partial => 'events/event', :locals => { :event => object.event }) if object.event
end

Unfortunately, my view has some code that uses helpers and the request object (urls), and I'm getting errors when I try to do this.

events/_event.html.erb:

<div class="event">
  <h4 class="title"><%= link_to event.name, event %></h4>
  <div class="date"><%= date_range event.start_at, event.end_at %></div>
  <div class="description"><%= event.description.html_safe %></div>
</div>

undefined method `host' for nil:NilClass

Any ideas of a good way to solve this problem?

like image 347
mscriven Avatar asked Oct 01 '22 08:10

mscriven


1 Answers

That happens because your controller lacks response attribute.

You may set the request for the controller as follows:

def event_html
  ApplicationController.new.tap {|c|  
    c.request = ActionController::TestRequest.new(host: "localhost")
  }.render_to_string(:partial => 'events/event', :locals => { :event => object.event }) if object.event
 end

However, for your case I would pass an existing controller as a context to the serializer

controllers/posts_controller.rb:

def index
  @posts = Post.all
  respond_to do |format|
    format.json { render json: @posts.to_a, each_serializer: PostSerializer, context: self }
  end
end
# ... or ...
def default_serializer_options
  {
    context: self
  }
end

serializers/post_serializer.rb:

def event_html
  context.render_to_string(:partial => 'events/event', :locals => { :event => object.event }) if object.event
end
like image 57
senya Avatar answered Nov 04 '22 20:11

senya