与form_with的“ belongs_to”关联

时间:2018-07-06 11:01:29

标签: ruby-on-rails

此问题与Rails中新的 form_with 帮助器有关。特殊情况是表单用于属于另一个的模型。这是一些代码。

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

问题

此代码似乎有效,但我认为我可以对其进行改进。当我在create动作中查看参数时,会看到以下内容:

<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 =>哈希参数下,这使我的强大参数无法找到它。有更好的方法吗?

第二,这导致我编写如下的create动作:

@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. 我主要通过谷歌搜索和反复试验来解决问题。那是最佳实践吗?

1 个答案:

答案 0 :(得分:3)

您的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过滤器