嵌套属性的未允许参数,即使它存在

时间:2014-12-30 01:50:56

标签: ruby-on-rails ruby nested-forms nested-attributes strong-parameters

我似乎无法通过控制器或可能通过视图保存/更新嵌套模型属性。我看到一个错误“未经许可的参数:(取决于我选择更新的模型在这里,例如语言)”。经过几天的研究,我感到失败;感谢您的帮助或指导。

我有一个页面,每个部分都有许多表单,一个编辑模式和一个删除按钮。 一切都在索引页面完成。

Started PATCH "/user_skills/1" for 127.0.0.1 at 2014-12-29 19:21:05 -0600
Processing by UserSkillsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ArM2OqBIlsM+Vx7YHRq8NtExBp/Z/FmxpRO8xEX8Y9w=",   "user_skill"=>{"language"=>{"title"=>"Ruby", "description"=>"A dynamic, elegant and productive object oriented programming language."}}, "button"=>"", "id"=>"1"}
UserSkill Load (0.1ms)  SELECT  "user_skills".* FROM "user_skills"  WHERE "user_skills"."id" = ? LIMIT 1  [["id", 1]]
Unpermitted parameters: language
(0.1ms)  begin transaction
(0.0ms)  commit transaction
Redirected to http://localhost:3000/user_skills.1
Completed 302 Found in 4ms (ActiveRecord: 0.3ms)

所以我有一个名为user_skill.rb的模型,它应该更新其他三个不同的模型。

# == Schema Information
#
# Table name: user_skills
#
#  id :integer          not null, primary key
#
class UserSkill < ActiveRecord::Base
  has_many :languages
  has_many :frameworks
  has_many :tools

  accepts_nested_attributes_for :languages, :frameworks, :tools, allow_destroy: true    
end

我的一个控制器

class UserSkillsController < ApplicationController

def index
    load_user
end

def update
    load_user
    build_skill
    save_skill or render 'user_skills'
end

private

def userskill_scoped
    UserSkill.all
end

def build_skill
    @skill ||= userskill_scoped.build
    @skill.attributes = skill_params
end

def load_user
    @skill ||= UserSkill.find(1)
end

def skill_params
    skill_params = params
    skill_params ? skill_params.require(:user_skill).permit(:id, languages_attributes: [:id, :title, :description, :user_skill_id, :_destroy], frameworks_attributes: [:id, :title, :description, :user_skill_id, :_destroy], tools_attributes: [:id, :title, :description, :user_skill_id, :_destroy]) : {}

end

def save_skill
  notice = @skill.new_record? ? "User skill was successfully created" : "User skills was successfully updated"
  if @skill.save
    redirect_to user_skills_path(@skill), notice: notice
  else
    render 'user_skills'
  end
end

这是我的表单,我删除了一些bootstrap div,以便它更容易阅读。工艺对象作为局部变量从集合传递到此表单;它代表记录的实际实例。 e.g

<Language id: 1, title: "Ruby", description: "A dynamic, elegant and productive object oriented ...", url: "http://www.ruby-lang.org", image: nil, created_at: "2014-12-19 02:35:10", updated_at: "2014-12-19 19:57:48", user_skill_id: 1>
irb(main):003:0>

我的表格:

<%= form_for @skill do |f| %>
  <%= f.fields_for technology do |f| %> 
  <h4>Title:</h4>
  <%= f.text_field :title, class: 'form-control', :required => true %>
  <h4>Content:</h4>
  <%= f.text_area :description, class: 'form-control content-text', :required => true %>
<% end %>

<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">Cancel</button>
<%= f.button 'Save', action: 'update', class: "btn btn-default btn-sm", data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %> 
</div>
<% end %>

*更新,添加视图*

这些是我的观点,导致部分形式。 “user_skill#指数”

    <% if notice %>
    <div class="alert alert-success" role="alert">
    <%= notice %>
    </div>  
    <% end %>

    <div>
    <h1 class="title">My Tools</h1>
    <p class="subtitle">Technologies I've worked with...</p>
    <hr>
    <h3>Programming Languages</h3>
    <br>
    <%= render partial: 'user_skills/partials/skills', locals: { a: "languages" } %> 
    <hr>
    <h3>Frameworks</h3>
    <br>
    <%= render partial: 'user_skills/partials/skills', locals: { a: "frameworks"  } %> 
    <hr>
    <h3>Other</h3>
    <br>
    <%= render partial: 'user_skills/partials/skills', locals: { a: "tools"  } %> 
    <br>
    <% ["languages","frameworks","tools"].each do |skill| %>
    <% @skill.send(skill).each do |technology| %>
    <!-- Modal -->
    <%= render 'user_skills/partials/modal', technology: technology %>
    <% end %>
    <% end %> 
    <br>
    <br>
    <br>
    <br>
    <br>
    <br>

    </div>

_skills partial

<% @skill.send(a).each do |technology| %>
<%= render 'user_skills/partials/skill_panels', :technology => technology %> 
            <!-- Modal -->
<%= render 'user_skills/partials/modal', :a => a, :technology => technology %> 
<% end %>

_skills_panel

<div class="panel panel-default">
<div class="panel-heading">
<%= technology.title %>
</div>
<div class="panel-body">
<%= technology.description %> 
</div>
<div class="panel-footer">
<div class="row">
<div class="col-xs-12">
<%= link_to technology.url, technology.url %>
<%= render 'user_skills/partials/edit_buttons', technology: technology %> 
</div>
</div>
</div>
</div>

edit_button partial

<div class="col-xs-8 pull-right">
<div class="pull-right edit_skill">
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-default btn-xs" data-toggle="modal" data-target='#edit_modal<%= "_#{technology.title.gsub(' ','').gsub('.','_')}" %>'>Edit</button>

    

<%= button_to "Delete", @skill, method: :delete, data: { confirm: "Are you sure you want to delete?"}, class: "btn btn-default btn-xs pull-right" %> 
</div>
</div>
</div>

模态部分

<div class="modal fade" id='edit_modal_<%= technology.title.gsub(' ','').gsub('.','_')%>' tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h3 class="modal-title" id="myModalLabel">Edit Skills</h3>
</div>
<div class="modal-body">
<%= render partial: 'form', locals: { technology: technology} %> 
</div>
</div>
</div>
</div>

1 个答案:

答案 0 :(得分:1)

您的输入与您的.reqire(...).permit(...)完全不匹配。

你传入的参数如下:

user_skill: { ..., languages: { ... } }

虽然你预期的参数看起来像这样:

...require(:user_skill).permit(..., languages_attributes: ...

languageslanguages_attributes之间的不匹配实际上非常重要。那些东西需要匹配或Rails抛出不匹配的参数。 _attributes的缺失或存在与匹配参数名称中的任何其他字符集一样重要。

不匹配的原因是您的表单设置不正确。我无法分辨为什么,因为您没有在HTML中添加任何内容来指示languages应该来自哪里。