从 around_action 回调中呈现控制器操作的视图
Rendering a view of controller action from around_action callback
我正在渲染一个 js.erb 部分,它可以为 like/dislike 一道菜提供 ajax 功能。我最近遇到了 around_action
回调,并认为 yield
将有助于首先执行控制器操作,然后再呈现模板。不幸的是,由于 respond_to
从未被调用,我收到 500 (Internal Server Error)
。
如果我将 respond_to
方法放在控制器操作中而不是回调中,它就会起作用。我做错了什么?
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
控制台错误
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'
好的,通过堆栈跟踪可以很清楚发生了什么。您必须了解约定优于配置的默认 rails 行为。
只要您调用 yield
,您的控制器操作就会被调用。现在,一旦动作执行完毕,所有控制器动作都会默认呈现与动作同名的视图。
所以在 yield
之后调用 render_to
没有任何意义,因为您 屈服于 的控制器操作已经调用了它的渲染 :)
无论如何你试图做的是一个糟糕的设计模式,渲染视图应该留给 actions
Update
从理论上讲:由于您希望让事情保持干燥,您可以通过创建一个在每个操作后调用它的通用方法来在每个操作后呈现相同的视图。但是,想一想,您的渲染将只有一行,而调用相同的方法也将需要一行 :) 那么 DRY 在哪里。
简而言之,DRY 不应以简单为代价而过度完成。在我看来 KISS 胜过 DRY :)
我正在渲染一个 js.erb 部分,它可以为 like/dislike 一道菜提供 ajax 功能。我最近遇到了 around_action
回调,并认为 yield
将有助于首先执行控制器操作,然后再呈现模板。不幸的是,由于 respond_to
从未被调用,我收到 500 (Internal Server Error)
。
如果我将 respond_to
方法放在控制器操作中而不是回调中,它就会起作用。我做错了什么?
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
控制台错误
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'
好的,通过堆栈跟踪可以很清楚发生了什么。您必须了解约定优于配置的默认 rails 行为。
只要您调用 yield
,您的控制器操作就会被调用。现在,一旦动作执行完毕,所有控制器动作都会默认呈现与动作同名的视图。
所以在 yield
之后调用 render_to
没有任何意义,因为您 屈服于 的控制器操作已经调用了它的渲染 :)
无论如何你试图做的是一个糟糕的设计模式,渲染视图应该留给 actions
Update
从理论上讲:由于您希望让事情保持干燥,您可以通过创建一个在每个操作后调用它的通用方法来在每个操作后呈现相同的视图。但是,想一想,您的渲染将只有一行,而调用相同的方法也将需要一行 :) 那么 DRY 在哪里。
简而言之,DRY 不应以简单为代价而过度完成。在我看来 KISS 胜过 DRY :)