【问题标题】:'belongs_to' association with form_with'belongs_to' 与 form_with 的关联
【发布时间】:2018-07-06 11:01:28
【问题描述】:

这个问题是关于 Rails 中新的 form_with 助手的。特殊情况是表单适用于 belongs_to 另一个模型。这是一些代码。

Routes.rb

resources :contents do
  resources :translations
end

迁移

class CreateTranslations < ActiveRecord::Migration[5.2]
  def change
    create_table :translations do |t|
      t.text :translation
      t.string :to_lang
      t.references :content, foreign_key: true, dependent: :delete
      t.timestamps
    end
  end
end

表格

<%= form_with(model: @translation, url: [@content, @translation], local: true) do |form| %>
  <% if translation.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(translation.errors.count, "error") %> prohibited this translation from being saved:</h2>

      <ul>
      <% translation.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label "Target Language", class: "label" %>
    <div class="select"> 
      <%= form.select(:to_lang, options_for_select([["English", "en"], ["French", "fr"], ["Spanish", "es"]])) %>
    </div>
  </div>

  <div class="field">
    <%= form.label "Original Content" %>
    <%= form.label translation.content.text %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

Translation_controller.rb

def new
   @content = Content.find(params[:content_id])
   @translation = @content.translations.new
end

def create
  @content = Content.find(params[:content_id])
  @translation = @content.translations.build(translation_params)
  respond_to do |format|
    if @translation.save
      format.html { redirect_to contents_path, notice: 'Translation was successfully created.' }
      format.json { render :show, status: :created, location: @translation }
    else
      format.html { render :new }
      format.json { render json: @translation.errors, status: :unprocessable_entity }
    end
  end
end

问题

这段代码似乎可以工作,但我认为我可以改进它。当我查看创建操作中的参数时,我看到:

<ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"dFdTw+d85qA2BsLb0OW4TcaVfkMIaNEYgXcPvE8ff5ANprfoL58clGlx5kSC5zzoSOM0nSf9kaNvH8ebpUj5JQ==", "translation"=>{"to_lang"=>"en"}, "commit"=>"Create Translation", "controller"=>"translations", "action"=>"create", "content_id"=>"1"} permitted: false>
  1. 如您所见,content_id 参数不在 translation => hash 参数下,这使得我的强参数找不到它。有没有更好的方法?

其次,这导致我编写这样的创建操作:

@content = Content.find(params[:content_id])
@translation = @content.translations.build(translation_params)
  1. 这似乎不对,因为我再次绕过了强大的参数。我知道这纯粹是一个美学问题,我认为不会损害安全性或其他什么。有没有更好的方法?

我的 form_with 也是这样的:

<%= form_with(model: @translation, url: [@content, @translation], local: true) do |form| %>
  1. 我主要是通过谷歌搜索和反复试验得到的。这是最佳做法吗?

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    您的 content_id 不在 Rails 设计的翻译哈希中。但是,您可以执行以下操作来稍微清理一下

    class TranslationsController < ApplicationController
      before_action :set_content, only: [:new, :create]
    
      def new
        @translation = @content.translations.new
      end
    
      def create
        @translation = @content.translations.build(translation_params)
        ...
      end
    
      private
    
      def set_content
        # use params.require to use strong params
        @content = Content.find(params.require(:content_id))
      end
    end
    

    如果您在其他操作中使用@content,只需相应调整before_action 过滤器

    【讨论】:

    • 谢谢,这很有帮助。我们怎么知道这是预期的设计?据你所知,原因是什么?
    • hmm,如果您阅读 Rails Routing, Outside in,路径中的任何引用变量都会将其显示为顶级 params 元素。文档中至少包含 5 个示例,包括:guides.rubyonrails.org/routing.html#adding-more-restful-actions - 我不确定原因,但它是一致的,并且假定路由路径中没有关系
    猜你喜欢
    • 1970-01-01
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-08
    • 2011-04-30
    相关资源
    最近更新 更多