嵌套表单 - 我无法将所有属性参数传递给我的强参数

Posted

技术标签:

【中文标题】嵌套表单 - 我无法将所有属性参数传递给我的强参数【英文标题】:Nested Form - I cannot get all of the attributes params to pass through to my strong params 【发布时间】:2021-04-08 20:24:57 【问题描述】:

使用 has_many_through 连接表和连接表上的附加属性处理项目。我的模型是葡萄酒、食物,连接表是配对。我没有让所有属性参数都传递给我的强参数。我尝试过几种不同的方法——通过食物控制器和配对控制器,但通过葡萄酒控制器似乎是最直接的途径。在 wines new 表单上,我询问有关葡萄酒的基本信息,允许用户从之前输入的所有食物中选择要搭配的食物,并允许他们输入新食物并指出它是哪种搭配类型(是连接表上的附加属性)。从表格中,我从预先存在的食物中获取 food_ids,并且我正在获取配对类型的配对属性,但我没有获取食物属性。

型号:

class Wine < ApplicationRecord
    belongs_to :user
    has_many :wine_tasting_notes
    has_many :tasting_notes, :through => :wine_tasting_notes
    has_many :pairings, inverse_of: :wine
    has_many :foods, :through => :pairings
    accepts_nested_attributes_for :pairings, :allow_destroy => true
    accepts_nested_attributes_for :foods

        def pairings_attributes=(attributes)
            attributes.values.each do |att|
                if !att[:food_id].blank? || !att[:food_attributes].blank?
                    pairing = Pairing.new(att)
                    pairing.wine = self
                    self.pairings << pairing
                end
            end
        end
              
   
end
class Food < ApplicationRecord
    has_many :pairings, inverse_of: :food
    has_many :wines, :through => :pairings
    accepts_nested_attributes_for :pairings, :allow_destroy => true
    accepts_nested_attributes_for :wines

end

class Pairing < ApplicationRecord
    belongs_to :wine
    belongs_to :food

    def food_attributes=(attributes)
        food = Food.find_or_create_by(attributes)
        self.food_id = food.id
        binding.pry
    end
 
end

Wines_Controller

class WinesController < ApplicationController

    def index
        # binding.pry
        @wines = Wine.where(:user_id => current_user.id)
        
    end

    def new
        # binding.pry
        @wine = Wine.new
        @wine.user_id = current_user.id
        @pairings = @wine.pairings.build
        @food = @pairings.build_food
        
        binding.pry
        
    end

    def show
        # binding.pry
        @wine = Wine.find(params[:id])
    end

    def create
        binding.pry
        @wine = Wine.new(wine_params)
               
        binding.pry
        # @wine.user_id = current_user.id
        if @wine.save
            # binding.pry
            redirect_to @wine, notice: "Successfully created Wine"
        else
            # binding.pry
            render :new
        end
    end

    private

    def wine_params
        params.require(:wine).permit(:id, :wine_name, :color, :grape, :avg_price, :acidity, :sweetness, :user_id, pairings_attributes: [:id, :pairing_type], food_ids:[],\
        food_attributes: [:id, :food_name, :food_acidity, :food_sweetness])
    end

end

新酒表格

<h1>Add a Wine</h1>
<br>
<%= form_for @wine do |f| %>
    <div class ="settings">
    <%= f.hidden_field :user_id %>
    <%= f.label :wine_name %><%= f.text_field :wine_name %>
    
    <%= f.label :color %><%= f.text_field :color %>
    
    <%= f.label :grape %><%= f.text_field :grape %>
        
    <%= f.label :avg_price %><%= f.text_field :avg_price %>
    
    <%= f.label :acidity %><%= f.text_field :acidity %>
    
    <%= f.label :sweetness %><%= f.text_field :sweetness %>
    </div>
    <br>
    Food Pairings:
    <br>
    <%= hidden_field_tag "wine[food_ids][]", nil %>
    <% Food.all.each do |food| %>
        <%= check_box_tag "wine[food_ids][]", food.id, @wine.food_ids.include?(food.id), id: dom_id(food) %>
        <%= label_tag dom_id(food), food.food_name %><br>
    <% end %>
    <br>
    <strong><em>To Add a New Food Pairing:</em></strong>
    <br>
    <%= f.fields_for :food do |ff| %>
        <%= ff.hidden_field :id %>
        <%= ff.label :"Food Name:" %>
        <%= ff.text_field :food_name %>
        <%= ff.label :"Food Acidity:" %>
        <%= ff.text_field :food_acidity %>
        <%= ff.label :"Food Sweetness:" %>
        <%= ff.text_field :food_sweetness %>
        
        <br>
        <br>
    <% end %>
    <strong>Type of Pairing: </strong>
    
    <%= f.fields_for :pairings do |fff| %>
    <%= fff.label :pairing_type, "Congruent", "value" => "Congruent" %><%= fff.radio_button :pairing_type, "Congruent", checked: true %>
    <%= fff.label :pairing_type, "Contrasting", "value" => "Contrasting" %><%= fff.radio_button :pairing_type, "Contrasting", checked: false %>
    <% end %>      
    <br>
    <br>
    <%= f.submit %>
<% end %>

提交表单时的常规参数

[2] pry(#<WinesController>)> params
=> <ActionController::Parameters "authenticity_token"=>"MQy7Or4AjBLi11uEFEgBVAZnCT9kgaltqMPxIZ4X2d2BnMZwshQZkUKKCAzeQzE77pycsZN7SVOiX6NsPH/Dng==", "wine"=><ActionController::Parameters "user_id"=>"1", "wine_name"=>"Molly Dooker The Boxer", "color"=>"Red", "grape"=>"Shiraz", "avg_price"=>"29", "acidity"=>"3.6", "sweetness"=>"4", "food_ids"=>["", "1", "2"], "food"=>"id"=>"", "food_name"=>"Duck", "food_acidity"=>"8", "food_sweetness"=>"3", "pairings_attributes"=>"0"=>"pairing_type"=>"Congruent" permitted: false>, "commit"=>"Create Wine", "controller"=>"wines", "action"=>"create" permitted: false>

强参数 - wine_params

[1] pry(#<WinesController>)> wine_params
Unpermitted parameter: :food
=> <ActionController::Parameters "wine_name"=>"Molly Dooker The Boxer", "color"=>"Red", "grape"=>"Shiraz", "avg_price"=>"29", "acidity"=>"3.6", "sweetness"=>"4", "user_id"=>"1", "pairings_attributes"=><ActionController::Parameters "0"=><ActionController::Parameters "pairing_type"=>"Congruent" permitted: true> permitted: true>, "food_ids"=>["", "1", "2"] permitted: true>

欣赏任何见解-

【问题讨论】:

【参考方案1】:

你不应该在 wine 模型中为 :food 使用接受嵌套属性,因为你有 has_many through: 食物和葡萄酒之间的间接关系。

您应该使用accepts_nested_attributes_for :foods 与单数符号配对模型,即:食物

有一个look

【讨论】:

以上是关于嵌套表单 - 我无法将所有属性参数传递给我的强参数的主要内容,如果未能解决你的问题,请参考以下文章

如何将枚举作为字符串参数传递给 Authorize 属性?

如何将参数传递给servlet

Apollo Server:将参数传递给嵌套解析器

将ajax请求中的多个参数传递给函数后面的C#代码

如何将向量作为参数传递给另一个向量?

如何正确地将参数传递给rails表单