【问题标题】:What's the best way to call an application helper from a controller?从控制器调用应用程序助手的最佳方式是什么?
【发布时间】:2017-04-11 05:23:38
【问题描述】:

我想格式化 JSON 响应的值,使其与视图中的值相同。

考虑对象,user = { id: 323 };已经创建了一个辅助方法 (format_name) 以使值在视图中更直观:

<div>
  <%= format_name(user[:id]) %> 
  <% # appears as: <span class="user" data-user-id="323">John Doe</span> %>
</div>

由于已知原因,此功能在控制器中不可用。以下失败:

class ApplicationHelper

  def format_name
    # ...
  end
end


class UserController < ApplicationController

  def view

    # ...<setup user info>...

    user_formatted = {
      id: user[:id], 
      formatted: format_name(user[:id]) # helper method
    }

    respond_to do |format|
       format.json { render json: user_formatted.to_json }
    end
  end

end

我很好奇如何在控制器中使用辅助方法。

我试过了:

  • view_context.format_name
  • 创建一个部分(例如,_view.json.erb)来调用帮助程序并渲染 json
  • 在 ApplicationController 中设置 helper_method :format_name

【问题讨论】:

  • 我会成为一天中的那个 :)。对于您描述的用例,您应该使用序列化库,例如ActiveModel::Serializer。在控件中格式化 JSON 通常是不好的做法。您可以在序列化程序中使用视图助手(您可以将其视为 JSON 的“视图”)。它使格式化代码远离您的控制器。
  • @chrismanderson 自从我进行了广泛的 Rails 开发以来,已经很长时间了;我欢迎任何明智的建议。
  • 那么一定要看看 AMS。它现在是 Rails API 的默认序列化程序,并且是 rails-api 设置的一部分。
  • 请问,format_name 在控制器中不可用的已知原因是什么。
  • @AlejandroMontilla 如果我正确理解了你的问题,据我所知,帮助者主要是为了观点,除非以某种方式明确说明,我正试图通过我的问题弄清楚。

标签: ruby-on-rails view-helpers


【解决方案1】:

您可以通过在控制器中包含您的辅助模块来做到这一点,或者您可以使用module_function 将您的辅助方法声明为可直接在模块上调用,有点像类方法。

假设你的辅助函数是在这个辅助模块中声明的:

module ApplicationHelper
  def format_name(user_id)
    # do stuff
  end
  module_function :format_name  # Here's the "magic" line
end

通过添加 module_function :format_name 行,您现在可以像在控制器中调用 ApplicationHelper.format_name(user[:id]) 一样调用您的辅助函数。

【讨论】:

  • MyHelper 来自哪里?那是另一个模块吗? ApplicationHelper.format_name 时收到错误消息
  • 对不起,我的错。我忘了更新我的答案的那部分。编辑:现在更新了。
  • 啊,我试过了,得到了一个错误,但我认为这与辅助函数更相关......现在检查一下,谢谢
  • 当您在上面的代码示例中编写辅助函数时,它缺少一个参数,但您使用一个参数调用它。如果您编写的示例与您的代码完全一样,那可能就是原因。否则,它可能只是一些逻辑错误。哦,如果您在该辅助函数中使用任何实例变量 (@something),则可能必须替换它们,因为辅助函数与控制器的作用域不同。
  • 我没有,但我遇到了障碍,因为我在帮助程序中使用了allow?,这是一条未定义的消息。由于这似乎与所问的问题不同,我猜这已经足够好了。
【解决方案2】:

(将其从评论移至答案)我建议不要在您的控制器中进行这种格式化,而是使用ActiveModelSerializer 来处理它。它是 rails-api 设置的一部分,现在默认在 Rails 5 中提供。对于您的情况,您可以执行以下操作:

class UserSerializer < ActiveModel::Serializer
  include ApplicationHelper

  attributes :id, :formatted

  def formatted
    format_name(object)
  end
end

在你的控制器中,你可以这样做

def show
  render json: User.find(params[:id)
end

【讨论】:

    【解决方案3】:
    ###helper    
    module MyHelper
      def format_name(user_id)
         #code goes here
      end
    end
    
    ###html
    <div>
      <%= format_name(user[:id]) %> 
    </div>
    
    ###controller
    class SampleController < ApplicationController
      include MyHelper
    
      def view
        puts format_name(user[:id])
      end
    end
    

    【讨论】:

    • 这很有帮助,我没有选择它的原因是因为我认为它向控制器公开了所有功能,并且选择的答案似乎在防止副作用方面做得更好。不过,我确信这种方法可以适应这种担忧
    猜你喜欢
    • 2011-08-12
    • 1970-01-01
    • 2018-10-09
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    相关资源
    最近更新 更多