【问题标题】:how to DRY a respond_to that is the same in all actions?如何干燥所有动作中都相同的respond_to?
【发布时间】:2015-06-09 17:05:04
【问题描述】:

我有一个控制器,它将为小部件提供服务:

class WidgetsController < ApplicationController
  def widget1
    respond_to do |format|
      format.html
      format.js { render js: js_constructor }
    end
  end

  def widget2
    respond_to do |format|
      format.html
      format.js { render js: js_constructor }
    end
  end

  private
  def js_constructor
    content = render_to_string(params[:action], layout: false)
    "document.write(#{content.to_json})"
  end
end

这个控制器会变大,所以我想避免在所有动作中重复这段代码:

respond_to do |format|
  format.html
  format.js { render js: js_constructor }
end

有什么想法吗?

编辑:只是为了提供一些上下文...

路由灵活/动态:get 'widgets/:action', to: 'widgets#:action'

所以,如果我访问widgets/widget1,它将渲染视图widget1.html.erb

如果我将脚本包含在另一台服务器中,它将在那里构建 widget1:

<script type='text/javascript' src='http://localhost:3000/widgets/widget1.js'></script>

【问题讨论】:

  • 如果小部件之间实际上没有区别,为什么要为它们创建多个路由?
  • 每个动作都返回其各自视图的内容。只有一种灵活的路线(get 'widgets/:action', to: 'widgets#:action')。所以html格式用于开发,js会在别的地方构造视图(&lt;script type='text/javascript' src='http://localhost:3000/widgets/widget1.js'&gt;&lt;/script&gt;)。
  • @Makoto:我已经编辑了我的问题以提供一些背景信息。我希望现在很清楚;)
  • 你可以写alias widget2 widget1more_widgets = %w|widget2 widget3|; w.each { |w| alias_method w.to_sym, :widget1 }def method_missing(m) { |m| (m.to_s =~ /^widget\d+$/) ? widget1 : super }

标签: ruby-on-rails ruby respond-to


【解决方案1】:

我会编写一个将“视图”作为参数的操作。您基本上是在执行一个呈现不同视图的#show 操作。

get 'widgets/:template', to: 'widgets#show'

class WidgetsController < ApplicationController
  def show
    respond_to do |format|
      format.html { render params.require(:template) }
      format.js { render js: js_constructor }
    end
  end

  private
  def js_constructor
    content = render_to_string(params.require(:template), layout: false)
    "document.write(#{content.to_json})"
  end
end

【讨论】:

  • 在安全性和可维护性方面,您应该使用包含所有有效模板的数组并提供默认模板。
【解决方案2】:

答案是元编程:

class WidgetsController < ApplicationController
  [:widget1, :widget2].each do |name|
    define_method(name) do
      respond_to do |format|
        format.html
        format.js { render js: js_constructor }
      end
    end
  end

  private

  def js_constructor
    content = render_to_string(params[:action], layout: false)
    "document.write(#{content.to_json})"
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 2014-05-08
    相关资源
    最近更新 更多