我有一个用户实体,具有当前的位置领域(国家和城市).抱着这个信息,我建立了一个实体,称为位置其has_many用户。

我不能完全肯定我是否应该把用户模型"has_one"或"belongs_to",但是为什么我读,如果我希望它有外交钥匙的位置我应该把"belongs_to".我也希望能够编辑的用户当前的位置编辑的用户。所以我使用嵌套的属性。但是,当我编辑的用户我最终添加一个新的位置时间而没有相关联的用户是编辑。你能帮帮我吗?

我的代码如下:

#User Model
class User < ActiveRecord::Base
  ## Relationships
  belongs_to :current_location, :class_name => 'Location'
  accepts_nested_attributes_for :current_location
end

#Location Model
class Location < ActiveRecord::Base
  #Relationship
  has_many :users
end

# part of the _form_edit.haml
- form_edit.fields_for :current_location do |location_form|
  = location_form.label :location, "Current Location"
  = location_form.text_field :location

#Application Helper
#nested attributes for user and location
def setup_user(user)
  returning(user) do |u|
    u.build_current_location if u.current_location.nil?
  end
end

#in the user controller (added after edit)
def update
    @user = @current_user
    if @user.update_attributes(params[:user])
      flash[:notice] = "Account updated!"
      redirect_to account_url
    else
      render :action => :edit
    end
  end
有帮助吗?

解决方案

确切的问题你面,正如其他人指出的是,你的控制器不接收的位置id它应。看到我的位置id正在通过了错误的参数。不幸的是,一个位置id不存在上一个新的记录,所以这是不可能的形式。

你的问题源自使用accepts_nested_attributes_for在belongs_to关系。该行为是不明确的定义。这似乎是一个有记载的错误。所以accepts_nested_attributes_for应该在一个具有一个或多边关系。

这里有一些可能的解决方案:

  1. 移动accepted_nested_attributes_for的位置模式和建立你的形式的其他方式。

    -form_for @location do |location_form|
     ...
     =location_form.fields_for @user do |user_form|
       ....
    

    不幸的是,这并不允许一合乎逻辑的方式提交的信息。并使编辑的权利的用户困难。

  2. 使用一个加入模型,并使有一个:通过关系。

    我真的不知道该如何以及accept_nested_attributes_for工作有:通过关系,但它肯定会解决你的问题与联的记录。

  3. 忽略accepts_nested_attributes_for和处理,该协会在你的控制器老式的方法。

    实际上保持accepts_nested_attributes_for.它提供了一些有用的便利方法,只是不要让它得到的update_attributes/创建的发言。

    def update 
      @user = @current_user 
      completed = false
      location_params = params[:user].delete(:current_location_attributes)
    
      User.transaction do
        @location = Location.find_or_create_by_id(location_params)
        @user.update_attributes(params[:user]) 
        @user.current_location = @location
        @user.save!
        completed = true
      end
      if completed
        flash[:notice] = "Account updated!" redirect_to account_url 
      else 
        render :action => :edit 
      end
    end
    

领域对于将填充id领域中的current_location_attributes哈希自动的,如果它不是创建一个新的位置。然而,find_or_create_by_id,需要:id项中的散列为它的工作。这将创造一个正确地自动增加id如果id不在数据库。如果你正在创建一个新的位置,你将需要增加。最简单的添加它的形式 =location_form.hidden_field :id, 0 unless current\_location.new\_record?.

然而,可能要减少重复的位置的建立和变更位置。find_or_create_by_id线的位置。find_or_create_by_location.这也将减少任何错误,从失败的独特性验证。

其他提示

您没有提供嵌套属性的id。所以导轨认为这是一个新的。

- form_edit.fields_for :current_location do |location_form|
    = location_form.label :location, "Current Location"
    = location_form.text_field :location
    = location_form.hidden_field :id unless location_form.new_record?

不知道以前的答案是真的正确。你需要的是指定用户的ID为位置,而不是位置本身。

- form_edit.fields_for :current_location do |location_form|
  = location_form.label :location, "Current Location"
  = location_form.text_field :location
  = location_form.hidden_field :user_id

默认情况下belongs_to :current_location, :class_name => 'Location'将期望Users表具有current_location_id字段。一旦你有了这个,你应该能够做这样的事情:

@user = @current_user
@user.update_attributes(params[:user])

@location = @user.current_location or @user.build_current_location
@location.update_attributes(params[:location]) 

@user.current_location.save!
@user.save!
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top