【问题标题】:Different Ways to use simple_form in Ruby on Rails | What is the difference?在 Ruby on Rails 中使用 simple_form 的不同方式有什么不同?
【发布时间】:2018-05-22 16:36:33
【问题描述】:

这些处理“包”编辑表单的方法有什么区别?

这些不同的方法如何影响应用程序的稳定性?是多功能的吗?

这些会在哪里遇到重大问题?为什么一个比另一个好?

  1. 通过“方法?” <%= simple_form_for Pack.find(params[:id]), method: :patch do |f| %>
  2. 通过对象<%= simple_form_for @pack, url: pack_path(@pack), method: :patch do |f| %>
  3. 通过符号<%= simple_form_for :pack, url: pack_path(@pack), method: :patch do |f| %>

任何信息都会很好,我很想知道!

【问题讨论】:

    标签: ruby-on-rails ruby simple-form


    【解决方案1】:

    1。和 2. - 将表单助手绑定到模型实例

    除了在 2. 中您从实例变量引用模型实例而不只是传递方法调用的返回值这一事实之外,基本相同。

    最终结果是您获得了一个绑定到模型实例的表单。这意味着输入的值属性将包含来自模型的值。

    事实上,所有这些都会给出相同的结果:

    <% 
      @pack = Pack.find(params[:id]) 
      pack = Pack.find(params[:id]) 
    
    %>
    
    <%= simple_form_for Pack.find(params[:id]), method: :patch do |f| %>
    <%= simple_form_for @pack |f| %>
    <%= simple_form_for pack |f| %>
    

    但第一个不太理想,因为您应该避免直接从视图中进行查询。视图应该从控制器接收数据并使用它来创建 HTML 并尽可能简单和声明性。另一个主要问题是.find 会引发ActiveRecord::RecordNotFoundError,如果 id 无效,它应该在控制器中更早地被捕获。

    3。用符号调用表单助手:

    <%= simple_form_for :pack, url: pack_path(@pack), method: :patch do |f| %>
    

    这会创建一个“范围”的表单,而不必绑定到特定的模型实例。举个例子:

    <%= simple_form_for :thing do  |f| %>
      <%= f.input :name %>
    <% end %>
    

    这会生成以下 HTML:

    <form novalidate="novalidate" class="simple_form thing" action="/things/new" accept-charset="UTF-8" method="post">
      <input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="F4r1gLuboZc1CKIdn9qac0sefxSVIvkjxk9KsD+sRl1wnVtEIKzHvWY0mPuLPvHI1Kcv3TIWD883YXHKXA+yJQ==" />
      <div class="input string required thing_name">
        <label class="string required" for="thing_name"><abbr title="required">*</abbr> Name</label>
        <input class="string required" type="text" name="thing[name]" id="thing_name" />
      </div>
    </form>
    

    注意name="thing[name]" 这意味着它会给出一个参数哈希,就像我们有一个模型实例一样:

    {
       thing: {
         name: "foo"
       }
    }
    

    这并不常用(至少不正确),因为大多数时候您都在操作模型实例,但它在搜索表单等特殊情况下确实有用。

    请注意,Rails 将尝试解析局部变量 @thing,但如果它为 nil,则不会引发错误。因此,通常不建议使用此表单,因为它会掩盖错误。

    了解这种行为的最佳方式是阅读 ActionView::FormHelpers 的文档,SimpleForm 只是其中的糖。

    【讨论】:

    • 当您遵循约定优于配置时,也不是不需要指定url: pack_path(@pack), method: :patch。 Rails 通过调用.new_record? 判断HTTP 方法是POST 还是PATCH。并根据模型名称猜测有pack_path或packs_path路径助手。¨
    • "请注意,Rails 将尝试解析局部变量 @thing,但如果它为 nil,则不会引发错误。因此,通常不建议使用这种形式,因为它可以掩盖错误。"我最近遇到了这个,有没有办法禁用实例变量解析?我最终转储了 form_for 帮助器,转而使用 form_tag 进行搜索,因为在某些页面上它会预先填充或引发错误,因为我提供了一个符号到一个不是真实属性的字段。
    • @max 因此,从本质上删除 (@pack) 仍然会使表单正常运行,但由于这是猜测,它是否容易受到包括对象在内的任何异常错误的影响?
    • @JohanWentholt 我不知道有任何配置选项可以关闭 form_for 发生的变量解析,但 Rails 5.1 form_with 帮助器旨在替换 form_tag 和 @ 987654339@ 通过要求您使用消除任何潜在歧义的model: 选项来解决这个问题。
    【解决方案2】:

    所有三种方法都产生相同的形式(假设您将 @pack 设置为 Pack.find(params[:id]),但是需要权衡取舍:

    1. 不建议在视图代码中调用 ActiveRecord。视图应该只负责布局表单,而不是查询数据库。保持这种分离将使长期维护更加直接。使用变量还意味着您可以在new 和edit 屏幕上使用相同的表单,方法是在控制器中为new 视图设置@pack = Pack.new。由于这些原因,我建议不要使用选项 [1]。

    2. 使用对象 (@pack) 或符号 (:pack) 会产生相同的结果,因为 Rails form_for 助手在内部使用符号来查找变量。恕我直言选项 [2] 并直接引用对象“更好”,因为发生的魔法更少,因此项目新手(或一年后的您)更容易理解。选项 [2] 也与 Rails docs 和 SimpleForm 文档一致,因此人们看到它并不感到意外。

    【讨论】:

    • 我也遇到了调用符号:pack 将无法通过&lt;%= render 'shared/error_messages', object: f.object %&gt; 加载ruby 错误消息的问题,这仅仅是因为.object 吗?还是打电话给symbol: f.symbol 来解决这个问题?
    • 使用符号的最大问题实际上是它会掩盖 nil 错误。因此,您会得到一堆翻译错误或其他东西,而不是得到一个零错误,因为表单没有绑定到不太明显的模型。
    【解决方案3】:

    如果您在控制器中使用@pack = Pack.find(params[:id]),则 1 和 2 是相同的(通常建议这样做)。

    3 是你不要做的事情,因为simple_form_for 期望一个对象作为第一个参数而不是一个符号(你可能会将它与form.input :name 之类的东西混淆)。我建议您阅读 gem 的 README。

    【讨论】:

    • simple_form_for 确实接受符号作为第一个参数。它会产生与 1 和 2 相同的结果
    • 哦,你是对的,但第二个参数应该是 record_object 并且整个东西被传递给 fields_for 而不是 form_for 作为名称 @987654329 @会建议。 rubydoc.info/github/plataformatec/simple_form/master/SimpleForm/… 我个人不会使用它,因为它没有在 README 中描述,您必须阅读 API 代码才能找出区别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 2011-10-28
    • 2019-09-21
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多