【发布时间】: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
然后,我的个人资料显示页面会尝试以多种方式使用其他模型的属性。当我尝试使用用户模型中的属性(配置文件属于用户)时,它可以成功运行。
当我尝试使用属于配置文件的模型的属性时,它不起作用。
我有以下使用这些属性的方法 - 没有一个有效:
- 渲染部分:
Qualifications
<div class="row">
<div class="col-md-12">
<div class="profilequalifications">
<!-- @qualification.award.profile -->
</div>
</div>
</div>
- 直接引用属性:
那么 - 我的视觉和个性的嵌套形式是这种格式:
<%= 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