【问题标题】:Rails - Displaying associated attributes - unpermitted parametersRails - 显示关联的属性 - 不允许的参数
【发布时间】:2015-12-30 23:52:21
【问题描述】:

我正在尝试在 Rails 4 中制作应用程序。

我有一个简介模型、一个资格模型和一个愿景模型。

这些关联是:

profile.rb

has_many :qualifications  
 accepts_nested_attributes_for :qualification 

  has_one :vision
    accepts_nested_attributes_for :vision    

资格.rb

belongs_to :profile

视觉.rb

belongs_to :profile

我还有其他几个与资格和愿景相似的模型(即它们属于个人资料)。

所有相关属性都已包含在模型的强参数中以及它们的嵌套位置以及配置文件强参数中。

def profile_params
      params[:profile].permit(:user_id, :title, :hero, :overview, :research_interest, :occupation, :external_profile, 
        :working_languages, :tag_list,
          personality_attributes: [:average_day, :fantasy_project, :preferred_style],
          vision_attributes: [:long_term, :immediate_challenge], 
          qualifications_attributes: [:id, :level, :title, :year_earned, :institution, :_destroy] )
    end

表格设置为:

<%= simple_form_for(@profile) do |f| %>
            <%= f.error_notification %>

              <div class="form-inputs">

<div class="intpol2">
              Your professional qualifications
            </div>

              <%= render 'qualifications/form', f: f %>     

          </div>

 <div class="intpol2">
              Your research vision
            </div>

            <%= render 'visions/form', f: f %>
          </div>

<div class="form-actions">
                <%= f.button :submit, "Submit", :class => 'formsubmit' %>
              </div>
        <% end %>

然后在资格表中,我有:

<%= simple_fields_for :qualification do |f| %>

  <div class="form-inputs">


    <div class="row">
        <div class="col-md-6">
            <%= f.input :title, :label => "Your award" %> 
        </div>

        <div class="col-md-6">


        </div>


    </div>

    <div class="row">
        <div class="col-md-6">
            <%= f.input :level,   collection: [ "Bachelor's degree", "Master's degree", "Ph.D", "Post Doctoral award"] %>
        </div>


        <div class="col-md-6">
        <%= f.input :year_earned, :label => "When did you graduate?", collection: (Date.today.year - 50)..(Date.today.year) %>
        </div>

  </div>




  </div>
<% end %>

同样,在视觉形式中,我有:

<%= simple_fields_for :vision do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :long_term, as: :text, :label => "What is your long term research vision?", :input_html => {:rows => 10} %>

    <%= f.input :immediate_challenge, as: :text, :label => "What do you see as the immediate challenge to be addressed in pursuit of your long-term vision?",  :input_html => {:rows => 10} %>

  </div>

<% end %>

问题是,当我在配置文件表单上按提交时,这些属性没有保存。控制台显示这两个表中都没有输入。

这个过程还有其他步骤吗?

我认为问题更深层次。这是因为我有另一个名为 address.rb 的模型。它是多态的。

这些关联是:

地址.rb

 belongs_to :addressable, :polymorphic => true

profile.rb

has_many :addresses, as: :addressable

在我的个人资料显示中,我有:

<%= render 'profiles/geography'  %>

在我的地理部分中,我有:

<% if @profile.addresses.any? %>
        <%= @profile.addresses.first.country_name.titlecase %> 
    <% else %>
        <span class="profileeditlink">
            <%= link_to "Add your location", new_address_path %>
        </span>
    <% end %>   

控制台显示我有 4 个保存的地址。我只有一个用户。

个人资料显示页面显示 else 条件(即添加地址),即使已保存地址也是如此。

在我的配置文件显示页面上成功显示的唯一属性是配置文件表中的属性。所有关联的属性都只是显示为空白。那些有资格/有远见的人不会存到数据库中。

我不明白为什么这一切都搞砸了。

这个问题的另一个角度是我的资格表现在已经保存了一个条目。它显示在 rails 控制台中。但是,我的资格部分应该显示该条目,只显示标题。

<div class="profilequalificationstitle">
                    Qualifications
                </div>  
            </div>
        </div>


        <% Qualification.all.sort_by(&:year_earned).each do |qual| %>

        <div class="row">

                  <div class="col-md-12">
                    <div class="profilequalifications">
                        <%= @profile.try(:qualification).try(:title) %>
                    </div>  
                  </div>    
        </div>

        <div class="row">
                <div class="col-md-4">
                    <div class="intpolmin">
                        <%= @profile.try(:qualification).try(:year_earned) %>: 
                    </div>  
                </div>
                <div class="col-md-8">
                    <div class="intpolmin">
                        <%= @profile.try(:qualification).try(:institution) %>
                    </div>  
                </div>
        </div>  

          <% end %>

    </div>
</div>               

接受 RICH PECK 的以下建议:

我在配置文件控制器中更改了强参数定义的格式,使其不使用 rails 脚手架提供的格式,而是显示为:

def profile_params
     params.require(:profile).permit(:user_id, :title, :hero, :overview, :research_interest, :occupation, :external_profile, 
        :working_languages, :tag_list,
          user_attributes: [:avatar],
          personality_attributes: [:average_day, :fantasy_project, :preferred_style],
          vision_attributes: [:long_term, :immediate_challenge], 
          qualifications_attributes: [:id, :level, :title, :year_earned, :institution, :_destroy] )
    end

所有相关模型仍然使用 rails 脚手架格式 - 即:

def vision_params
      params[:vision].permit(:profile_id, :long_term, :immediate_challenge)
    end

profiles 控制器中的新方法有:

def new
    @profile = Profile.new
    @profile.qualifications.build
    @profile.vision.build
    @profile.personality.build

    authorize @profile
  end

至于关联的表达方式,保持关联的嵌套属性是个人喜好。我可以看到这个建议使用更少的行来实现相同的目标,但我的偏好是与嵌套属性声明有关联。

我的个人资料模型关联是:

belongs_to :user
  has_many :addresses, as: :addressable

  has_one :personality
    accepts_nested_attributes_for :personality

  has_many :qualifications  
    accepts_nested_attributes_for :qualifications,  reject_if: :all_blank, allow_destroy: true

  has_one :vision
    accepts_nested_attributes_for :vision    

然后,我的个人资料显示页面会尝试以多种方式使用其他模型的属性。当我尝试使用用户模型中的属性(配置文件属于用户)时,它可以成功运行。

当我尝试使用属于配置文件的模型的属性时,它不起作用。

我有以下使用这些属性的方法 - 没有一个有效:

  1. 渲染部分:

Qualifications 
    <div class="row">

              <div class="col-md-12">
                <div class="profilequalifications">
                     <!-- @qualification.award.profile  -->
                </div>  
              </div>    
    </div>
  1. 直接引用属性:

那么 - 我的视觉和个性的嵌套形式是这种格式:

<%= f.simple_fields_for :profile do |f| %>
      <%= f.simple_fields_for :vision do |ff| %>


  <div class="form-inputs">
    <%= ff.input :long_term, as: :text, :label => "What is your long term research vision?", :input_html => {:rows => 10} %>

    <%= ff.input :immediate_challenge, as: :text, :label => "What do you see as the immediate challenge to be addressed in pursuit of your long-term vision?",  :input_html => {:rows => 10} %>

  </div>

<% end %>
<% end %>

我的资格表格略有不同,因为它使用茧宝石添加功能以重复该表格以获得多个资格。

进一步调查

我找到了线索。

在我的终端中,我可以看到在表单中创建属性的补丁后,有一个错误提示:

Unpermitted parameter: profile

调查后,我发现了这些帖子中的每一个,并提出了以下解决方案:

解决方案 1:更改配置文件控制器中的强参数以包含父级的 id(在我的情况下:profile_id):

Unpermitted Parameters: profile (NestedAttributes) - RAILS 4

我尝试改变:

vision_attributes: [:id, :long_term, :immediate_challenge], 

vision_attributes: [:id, :profile_id, :long_term, :immediate_challenge], 

结果:没有区别 - 产生相同的错误。

解决方案2:改变形式

Nested attributes - Unpermitted parameters Rails 4

接受这个建议,我尝试将视觉形式更改为:

<%= f.simple_fields_for :profile_attributes do |f| %>
      <%= f.simple_fields_for :vision, @profile.vision do |ff| %>


  <div class="form-inputs">
    <%= ff.input :long_term, as: :text, :label => "What is your long term research vision?", :input_html => {:rows => 10} %>

    <%= ff.input :immediate_challenge, as: :text, :label => "What do you see as the immediate challenge to be addressed in pursuit of your long-term vision?",  :input_html => {:rows => 10} %>

  </div>

<% end %>
<% end %>

结果:没有区别——同样的错误结果。

解决方案 3:强参数在配置文件控制器中表达方式的进一步变化:

Rails 4 Nested Attributes Unpermitted Parameters

更改嵌套强参数在配置文件控制器中的表达方式:

      vision_attributes: [:id, :profile_id, :long_term, :immediate_challenge], 

      :vision_attributes[:id, :profile_id, :long_term, :immediate_challenge], 

结果:

一个新错误:
语法错误,意外',',期待=> ...ng_term,:immediate_challenge],... ^ /Users/mem/cl/cf3/app/controllers/profiles_controller.rb:95:语法错误,意外',' ,期待keyword_end /Users/mem/cl/cf3/app/controllers/profiles_controller.rb:96:语法错误,意外',',期待keyword_end /Users/mem/cl/cf3/app/controllers/profiles_controller.rb:97 : 语法错误,意外')',期待keyword_end

我陷入困境、迷失和沮丧。刚刚在 codementor.io 上投入的美元超出了我的承受能力,结果是导师不知道如何提供帮助。很想知道接下来要尝试什么。

另一种解决方案

我发现这篇文章:http://www.sitepoint.com/complex-rails-forms-with-nested-attributes/#adding-an-address

采用该教程中显示的方法,我尝试创建一个表单助手,它具有:

module FormHelper
  def setup_profile(profile)
    profile.vision ||= Vision.new
    profile
  end
end

(我不知道定义正文第二行的profile这个词是什么意思)但它与教程中针对用户/地址所采用的方法是一致的。

然后我将我的个人资料表单更改为:

<%= f.simple_fields_for (setup_profile(profile)) do |f| %>

              <%= render 'visions/form', f: f %>
            <% end %>  

并将我的愿景部分改变为:

  <div class="form-inputs">
    <%= ff.input :long_term, as: :text, :label => "What is your long term research vision?", :input_html => {:rows => 10} %>

    <%= ff.input :immediate_challenge, as: :text, :label => "What do you see as the immediate challenge to be addressed in pursuit of your long-term vision?",  :input_html => {:rows => 10} %>

  </div>

当我保存这些更改并重试时,我收到此错误:

undefined local variable or method `profile' for #<#<Class:0x007fe113fcd680>:0x007fe11f2769d0>

错误信息指向配置文件表单的这一行:

    <%= f.simple_fields_for (setup_profile(profile)) do |f| %>

我不知道这条错误消息是什么意思,但我认为这是因为 profile 应该是 '@profile' 或 ':profile' - 我不知道为什么,它只是经常这样显示。

如果我将此行更改为:

<%= f.simple_fields_for (setup_profile(@profile)) do |f| %>

我收到此错误:

undefined method `long_term' for #<Profile:0x007fe11c241c38>

我认为这个错误意味着表单正在配置文件表中查找名为“long_term”的属性,而不是愿景表。

如果我将此行更改为:

<%= f.simple_fields_for (setup_profile(@profile.vision)) do |f| %>

我在表单助手中收到此错误:

undefined method `vision' for #<Vision:0x007fe117e95278>

在我继续随机尝试之前,任何人都可以看看我尝试实施站点点文章中显示的解决方案的方式是否存在问题?

【问题讨论】:

    标签: ruby-on-rails associations polymorphic-associations


    【解决方案1】:

    首先,您的 params 方法需要修复:

    def profile_params
          params.require(:profile).permit(...
    

    为了澄清,你应该阅读strong params on github


    你写的太多了;应该是这样的:

    #app/models/profile.rb
    class Profile < ActiveRecord::Base
       has_many :qualifications
       has_one :vision
       accepts_nested_attributes_for :qualifications, :vision #-> has to match association name
    end
    

    当您创建profile 时,您需要构建关联对象(除非它们已经存在):

    #app/controllers/profiles_controller.rb
    class ProfilesController < ApplicationController
       def new
          @profile = Profile.new
          @profile.qualifications.build
          @profile.build_vision
       end
    end
    

    这将允许您使用以下表格:

    #app/views/profiles/new.html.erb
    <%= form_for @profile do |f| %>
       <%= f.fields_for :qualifications do |q| %>
          <%= q.text_field :title %>
          ... etc ...
       <% end %>
       <%= f.fields_for :vision do |v| %>
          <%= v.text_field :long_term %>
          ... etc ...
       <% end %>
       <%= f.submit %>
    <% end %>
    

    这应该根据需要创建一个新的profile 和关联的qualification / vision 对象。


    您的addressable 多态关联不应与上述内容有任何关系。

    虽然起初令人困惑,但多态关联基本上使您能够引用可在许多不同情况下使用的关联。它是多态的事实并不重要。

    IE Rails 将只使用has_many :addresses,无论是否为as: :addressable

    【讨论】:

    • 在使用 rails 脚手架时,控制器是使用该格式构建的。所有的控制器都是用这种强大的参数定义格式生成的:def vision_params params[:vision].permit(:) end。我已将其更改为您建议的格式,尽管它对问题没有影响。我很奇怪,如果这是原因,列入白名单的个人资料属性也不应该出现在个人资料显示页面上。我在配置文件控制器中的新方法已经具有每个关联模型的构建功能。无论如何,谢谢 - 这不是解决方案
    • 顺便说一句-我没有个人资料/新页面,这是一个部分表单-尽管这不应该是问题的原因
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多