gpt4 book ai didi

ruby-on-rails - Ruby on Rails : Nested Attributes,归属关系

转载 作者:行者123 更新时间:2023-12-04 04:00:36 24 4
gpt4 key购买 nike

我有一个具有“当前位置”字段(城市和国家)的用户实体。为了保存此信息,我创建了一个名为Location的实体,它具有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

最佳答案

正如其他人指出的那样,您面临的确切问题是您的 Controller 没有收到应有的位置ID。在我看来,位置ID正在通过错误的参数传递。不幸的是,位置ID在新记录中不存在,因此这在表格中是不可能的。

您的问题源于在归属关系上使用accepts_nested_attributes_for。行为没有明确定义。这似乎是一个已记录的错误。因此,accepts_nested_attributes_for应该在一个具有一侧关系或具有多个一侧的关系上。

以下是一些可能的解决方案:

  • 将acceptd_nested_attributes_for移动到Location模型,并以其他方式构建表单。
    -form_for @location do |location_form|
    ...
    =location_form.fields_for @user do |user_form|
    ....

    不幸的是,这不允许以逻辑方式呈现信息。并且使正确的用户编辑变得困难。
  • 使用联接模型,并使其具有一个:through关系。

    老实说,我不确定accept_nested_attributes_for在:through关系中的表现如何,但是肯定可以解决链接记录的问题。
  • 忽略accepts_nested_attributes_for并以老式方式处理 Controller 中的关联。

    实际上保留accepts_nested_attributes_for。它提供了一些方便的便捷方法,只是不要让它进入update_attributes/create语句。
    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

  • 如果没有创建新位置,则for的字段将自动在current_location_attributes哈希中填充ID字段。但是,find_or_create_by_id在散列中需要一个:id条目才能起作用。如果该ID不在数据库中,它将使用正确的自动递增的ID创建。如果要创建新位置,则需要添加它。最容易使用 =location_form.hidden_field :id, 0 unless current\_location.new\_record?将其添加到表单中。

    但是,您可能希望减少重复的位置创建,并将Location.find_or_create_by_id行更改为Location.find_or_create_by_location。这还将减少因唯一性验证失败而产生的任何错误。

    关于ruby-on-rails - Ruby on Rails : Nested Attributes,归属关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1593853/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com