简体   繁体   中英

Rendering a view of controller action from around_action callback

I'm rendering a js.erb partial which enables ajax functionality to like/dislike a restaurant dish. I recently came across the around_action callback and figured yield would help perform the controller action first and render the template second. Unfortunately I'm getting a 500 (Internal Server Error) due to the respond_to never getting called.

The respond_to method works if I place it inside the controller action but not inside the callback. What am I doing wrong?

class DishesController < ApplicationController
  before_action :set_dish_and_restaurant
  around_action :render_vote_partial

  def like
    @dish.liked_by current_user
  end

  ...

  private
    def set_dish_and_restaurant
      @dish = Dish.find(params[:id])
    end

    def render_vote_partial
      yield
      respond_to { |format| format.js { render "vote.js.erb" } }
    end
end

Console Error

ActionView::MissingTemplate (Missing template dishes/like, application/like with {:locale=>[:en], :formats=>[:js, "application/ecmascript", "application/x-ecmascript", :html, :text, :js, :css, :ics, :csv, :vcf, :png, :jpeg, :gif, :bmp, :tiff, :mpeg, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :pdf, :zip], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in:
  * "/app/views"
  * "/Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/app/views"
):
  app/controllers/dishes_controller.rb:29:in `render_vote_partial'

Okay so with your stack trace it is pretty clear what is happening. You have to understand the default rails behavior of convention over configuration.

As soon as you call yield , your controller action gets called. Now all controller actions by default look to render views with the same name as action, once the actions are done executing.

So calling render_to after yield doesn't make any sense, as controller action you yielded to has already called its render :)

In any case what you are trying to do is a bad design pattern, rendering views should be left to actions

Update

Theoretically speaking : As you wish to keep things DRY you could render the same view after each action by creating a common method calling it after every action. However, think about it, your render will have one line, and calling that same method will need one line too :) so where's the DRY.

In short, DRY should not be over done at the cost of simplicity. In my opinion KISS trumps DRY :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM