Rails - 显示相关属性 - 未允许的参数

时间:2015-12-30 23:52:22

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

我正在尝试在Rails 4中创建一个应用程序。

我有个人资料模型,资格模型和视觉模型。

协会是:

profile.rb

has_many :qualifications  
 accepts_nested_attributes_for :qualification 

  has_one :vision
    accepts_nested_attributes_for :vision    

qualification.rb

belongs_to :profile

vision.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的模型。它是多态的。

协会是:

address.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个已保存的地址。我只有一个用户。

配置文件显示页面显示其他条件(即添加地址),即使保存了地址也是如此。

在我的个人资料显示页面上成功显示的唯一属性是配置文件表中的属性。所有关联的属性都显示为空白。那些有资格/愿景的人,不能存入数据库。

我无法弄清楚为什么这一切都搞砸了。

这个问题的另一个角度是我的资格表现在已经保存了一个条目。它显示在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>               

采取以下建议:

我在配置文件控制器中更改了我的强params定义的格式,以便它不使用rails scaffolding提供的格式,而是显示为:

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

所有相关型号仍然使用导轨脚手架格式 - 即:

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

配置文件控制器中的新方法有:

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. 渲染部分:                     &lt;%=渲染&#39;个人资料/资格&#39; %GT;                 
  2. Qualifications 
    
        <div class="row">
    
                  <div class="col-md-12">
                    <div class="profilequalifications">
                         <!-- @qualification.award.profile  -->
                    </div>  
                  </div>    
        </div>
    
    1. 直接引用属性:&lt;%= @ profile.try(:vision).try(:long_term)%&gt;
    2. 然后 - 我的视觉和个性的嵌套形式采用以下格式:

      <%= 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 %>
      

      我的资格表格略有不同,因为它使用cocoon gem添加功能以重复该表格以获得多种资格。

      进一步调查

      我找到了线索。

      在我的终端中,我可以看到在表单中创建属性的补丁之后,出现了一个错误:

      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

      更改嵌套强params在配置文件控制器中表示的方式:

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

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

      结果:

      新错误:
      语法错误,意外&#39;,&#39;,expecting =&gt; ... ng_term,:immediate_challenge],... ^ /Users/mem/cl/cf3/app/controllers/profiles_controller.rb:95:语法错误,意外&#39;,&#39;,期待keyword_end / Users /mem/cl/cf3/app/controllers/profiles_controller.rb:96:语法错误,意外&#39;,&#39;,期待keyword_end /Users/mem/cl/cf3/app/controllers/profiles_controller.rb: 97:语法错误,意外&#39;)&#39;,期待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
      

      (我不知道定义主体第二行的单词配置文件意味着什么),但它与教程中用户/地址的方法一致。

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

      <%= 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| %>
      

      我不知道此错误消息的含义,但我认为这是因为个人资料应该是&#39; @ profile&#39;或者&#39;:个人资料&#39; - 我不知道为什么,它经常出现这种情况。

      如果我将此行更改为:

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

      我收到此错误:

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

      我认为这个错误意味着表单正在寻找一个名为&#34; long_term&#34;的属性。在配置文件表中,而不是愿景表。

      如果我将此行更改为:

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

std

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

你写得太多了;这是它应该看起来的样子:

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

创建#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 %> &amp;根据需要关联profile / qualification个对象。

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

虽然最初会引起混淆,但多态关联基本上使您能够引用可在许多不同情况下使用的关联。它的多态性这一事实并不重要。

IE Rails只会使用addressable是否has_many :addresses