Rails 3.1:accepts_nested_attributes_for和has_one关联 - 不起作用?

时间:2011-10-08 00:04:22

标签: ruby-on-rails ruby-on-rails-3.1

我正在尝试在has_one关联模型上使用accepts_nested_attributes_for,并且绝对无处: - (

我有两个模型,一个用户和一个位置。用户有一个位置:

class User < ActiveRecord::Base
  # current location
  has_one :location, :dependent => :destroy
  accepts_nested_attributes_for :location
end

class Location < ActiveRecord::Base
  belongs_to :user
end

我可以使用控制台中的User.find(1).location.current_location_text = "blah"保存对模型的更改,因此我知道关联设置正确。

我在编辑用户页面上有两个表单。一个更新主要用户属性(并且工作正常并且未在下面显示)然后允许用户更新位置模型的属性,称为“current_location_text”:

<%= form_for(@user) do |f| %>  
    <%= fields_for(@user.location) do |location_fields| %>
        <%= location_fields.label :current_location_text, 'Current Location' %>
        <%= location_fields.text_field :current_location_text, :placeholder => 'Road, City or Postcode' %>
    <% end %>

    <%= f.submit "Update Current Location" %>
<% end %>

这不起作用。我有点困惑,因为表格发送的参数看起来不正确。提交表单时,这位于日志中:

Started PUT "/users/1" for 127.0.0.1 at 2011-10-08 00:28:05 +0100
  Processing by UsersController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"}
  User Load (10.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
  User Load (5.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = ? LIMIT 1  [["id", "1"]]
  SQL (4.4ms)  BEGIN
   (2.5ms)  COMMIT
Redirected to http://localhost:3000/users/1

我觉得有两件事情很奇怪:

  1. 有“COMMIT”消息,但没有先前的更新字符串,也没有错误。例如,如果您尝试提交受保护的属性,那么此时您将收到“您无法批量分配...”错误消息。

  2. 这对我来说错了。 “location”位嵌套正如我所期望的那样,但我也希望这是嵌套在“user”哈希中,如下所示:

     {"utf8"=>"✓", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "user"=>{"location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"}}
    
  3. 我不认为我在这里完全是傻瓜。我错过了一些非常明显的东西吗我已经尝试在我的表单中添加额外的隐藏字段,即用户ID,然后我获得用户哈希,但与“位置”哈希处于同一级别,而不是我期望的父级!

    如果它有帮助,这是我在UsersController中的更新:

    def更新     @user = User.find(params [:id])

    if @user.update_attributes(params[:user])
      redirect_to current_user, :notice => 'User was successfully updated.'
    else
      render :action => "edit"
    end
    

    这就是我的routes.rb中的内容(尽管我认为它不相关):

    resources :users do
      resource :location
    end
    

    任何帮助表示赞赏。如果我不解决这个问题,笔记本电脑就会出窗...... 感谢。

2 个答案:

答案 0 :(得分:11)

<%= fields_for(@user.location) do |location_fields| %>

这是你的问题。你需要在表单中实际“嵌套”fields_for,如下所示:

<% f.fields_for(@user.location) do |location_fields| -%>

答案 1 :(得分:5)

试试这个

<%= f.fields_for :location do |location_fields| %>

告诉rails你希望加载什么关联

,而不是给对象本身