Ruby on Rails:使用nested_form保存连接属性使用'nil'填充数据库

时间:2016-05-31 14:32:02

标签: ruby-on-rails ruby-on-rails-4

我目前正在使用RoR 4创建WebApp,并且我在数据库之间使用has_many, though:关联。

我有3个模型用户,用户主题和主题如下:

class UsersSubject < ActiveRecord::Base
  belongs_to :users
  belongs_to :subjects
end

class Subject < ActiveRecord::Base
  has_many :users_subjects
  has_many :users, through: :users_subjects
end

class User < ActiveRecord::Base
  has_many :users_subjects, :class_name => 'UsersSubject'
  has_many :subjects, through: :users_subjects

  accepts_nested_attributes_for :subjects
end

我正在尝试使用User控制器更新User时填充UsersSubject数据库。以下是我从用户的部分形式:

<div class="control-group nested-fields">
  <div class="contols">
    <%= f.fields_for :subject do |subject| %>
      <%= subject.label "Subjects" %></br>
      <%= subject.collection_select(:subject_id, Subject.all, :id, :name) %>
    <% end %>
  </div>
</div>

这是我的控制器:

def edit
  user_id = current_user.id
  subject_id = Subject.where(:name => params[:name])
  @user_sub = UsersSubject.new(user_id: user_id, subject_id: subject_id)
  @user_sub.save
end

当我这样做时,控制器使用正确的user_id填充UsersSubject数据库,但subject_id始终为nil。已使用seed.rb文件填充Subject数据库。 有人可以帮助我理解为什么会发生这种情况并帮助我解决它吗?

提前致谢

修改

这是我的development.log

Started GET "/users/edit" for ::1 at 2016-05-31 18:27:33 +0100
Processing by Users::RegistrationsController#edit as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZGvBq1uFUi1RxcInKFz1TnUs2ZzlZsP29aW1mzQBOVBTLm/Dq3C42cQQX0ksmBv95/qHnk08bG3f5u1v9taZgw==", "user"=>{"address"=>"", "city"=>"London", "postcode"=>"", "country"=>"United Kingdom", "subject"=>{"subject_id"=>"1"}}, "commit"=>"Update"}    

将控制器代码移至update操作

def update
  user_id = current_user.id
  subject_id = params[:user][:subject][:subject_id] unless params[:user].nil?
  @user_sub = UsersSubject.new(user_id: user_id, subject_id: subject_id)
  @user_sub.save
end

application_controller.rb

中添加了主题权限
class ApplicationController < ActionController::Base

  before_filter :configure_permitted_parameters, if: :devise_controller?
  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:last_name,
      :first_name, :email, :password, :current_password, 
      subject_attributes: [:id, :subject_id]) }
  end
end

这允许update操作访问subject_attributes

user模型中的更改

class User < ActiveRecord::Base
  has_many :users_subjects, :class_name => 'UsersSubject', dependent: :destroy
  has_many :subjects, through: :users_subjects

  accepts_nested_attributes_for :subjects
end

2 个答案:

答案 0 :(得分:0)

您是否考虑过使用茧宝石?

您可能还想查看一下您传入subject_id的参数,它看起来就像是您从其名称中抓取的完整对象。打印出&#34; subject_id&#34;你现在有。

您可能希望了解此主题有一个很棒的Promise.coroutine,会员资格非常值得。

答案 1 :(得分:0)

检查rails服务器日志中的params。据我所知它应该像这样来了

"user" => {
  "name"=>"Michael Jackson",
  "subject" => {
    "subject_id"=>"1"
  }
}

但是在你的控制器方法中,你试图像params[:name]那样访问它,而你应该根据你在表单中的嵌套方式做这样的事情。

subject_id = params[:user][:subject][:subject_id]

subject_id嵌套在subject内,嵌套在user对象中。

希望这会有所帮助。 :)

  

参考代码:

     

对您的编辑操作执行此操作。

def edit
  p params #this print out the inspected params in the console log
  fail
  #this stops the code from executing further, by raising an error.
  #So we can inspect the params passed to our method in server log
  ...
end

在浏览器中转到表单,然后清除rails服务器控制台,(Command + K)表示mac,对于ubuntu,按住enter键将当前日志移到屏幕上。现在单击“提交”,然后检查服务器日志。你会注意到像

这样的东西
Started POST "/users"
Processing by UsersController#edit
Parameters: {"utf8"=>..... "user" => { "name" => "Michael Jackson", "subject" => { "subject_id" => "1" }}}

所以你想要做的是,你需要在User和Subject之间创建一个新的多对多关系。正如我所定义的那样,你从params的user_id方法中获取了设计的current_user和subject_id中的edit。你如何接受params可能与我提到的不同。

  

最终代码

def edit
  user_id = current_user.id
  subject_id = params[:user][:subject][:subject_id]
  @user_sub = UsersSubject.new(user_id: user_id, subject_id: subject_id)
  @user_sub.save
end