我正在尝试用Rails4做一个应用程序。
我有一个配置文件模型和一个地址模型。
这些关联包括:
profile.rb
has_many :addresses, as: :addressableaddress.rb
belongs_to :addressable, :polymorphic => true地址是一个多态模型。
我有一张地址表格,上面写着:
<%= simple_form_for(@address) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<div class="row">
<div class="col-xs-3">
<%= f.input :unit %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :street_number %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :street %>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<%= f.input :building %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :city %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :region %>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<%= f.input :zip %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :country, priority: [ "Australia", "New Zealand", "United Kingdom" ] %>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<%= f.input :main_address %>
</div>
<div class="col-xs-3 col-xs-offset-1">
<%= f.input :project_offsite %>
</div>
</div>
</div>
<div class="form-actions">
<%= f.button :submit, :class => "formsubmit" %>
</div>
<% end %>我尝试创建一个地址并保存它。然后我检查它是否在rails控制台中。有些地方出错了,因为rails控制台显示了以下内容:
#<Address id: 1, unit: "", building: "", street_number: "34", street: "f", city: "sdfasdf", region: "asdf", zip: "2000", country: "GB", main_address: nil, project_offsite: nil, time_zone: nil, latitude: nil, longitude: nil, addressable_id: nil, addressable_type: nil, created_at: "2015-12-30 00:07:00", updated_at: "2015-12-30 00:17:00"> 可寻址id和可寻址类型都为零。
它们应该将引用返回到profile或相关模型所在的任何位置。
在设置此流程时是否缺少一个步骤?
这个视频(分钟3.40)说rails会自动处理多态模型的type和id字段的填写。https://gorails.com/episodes/comments-with-polymorphic-associations?autoplay=1
当我尝试从rails控制台创建一个新地址时,我键入:
Address.create(addressable: Address.first, profile_id: "1", country: "AU")控制台错误是:
ActiveRecord::UnknownAttributeError: unknown attribute 'profile_id' for Address我的address表有一个addressable键,我的配置文件模型有has_many :addresses,as::addressable
我不明白是什么导致了这个错误
另一次尝试
因此,根据我从下面的建议中收集到的信息,我需要做一些事情来让address知道它属于一个配置文件。
我还找到了这篇文章,它列出了配置文件控制器中需要发生的事情的示例,以使事情与多态关联一起工作:http://6ftdan.com/allyourdev/2015/02/10/rails-polymorphic-models/
我将profiles控制器中的新操作更改为(包括addresses.build):
def new
@profile = Profile.new
@profile.qualifications.build
@profile.visions.build
@profile.personalities.build
@profile.addresses.build
authorize @profile
end我将嵌套属性添加到配置文件模型中的地址关联中:
has_many :addresses, as: :addressable
accepts_nested_attributes_for :addresses, reject_if: :all_blank, allow_destroy: true我更改了我的地址格式:-从form_for改为fields_for;-将其重命名为_address_fields.html.erb;-使用以下命令打开div标记:
<div class="nested-fields">在我的配置文件表单中,我将链接添加到表单partial:
Your addresss
</div>
<%= f.simple_fields_for :addresses do |f| %>
<%= render 'addresses/address_fields', f: f %>
<% end %>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_add_association 'Add an address', f, :addresses, partial: 'addresses/address_fields' %>
</div>所有这些都是在Jeiwan在这篇文章中的回答中提出的:Rails - Cocoon gem - Nested Forms
然后,当我尝试所有这些时,我得到这个错误:
ActiveRecord::RecordNotUnique in ProfilesController#update
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_addresses_on_addressable_type_and_addressable_id" DETAIL: Key (addressable_type, addressable_id)=(0, 1) already exists. : INSERT INTO "addresses" ("unit", "building", "street_number", "street", "city", "region", "zip", "country", "addressable_id", "addressable_type", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING "id"错误指向配置文件控制器中的update方法:
def update
respond_to do |format|
if @profile.update(profile_params)
format.html { redirect_to @profile }
format.json { render :show, status: :ok, location: @profile }
else我发现这篇文章描述了一位用户的类似问题,但在我更改数据库之前,我想试着了解一下发生了什么。
Rails auto-assigning id that already exists
另一件奇怪的事情是,当我查看在控制台中创建的最后一个地址时,它显示如下:
#<Address id: 6, unit: "", building: "", street_number: "34", street: "asdf", city: "asdf", region: "add", zip: "2111", country: "AU", main_address: nil, project_offsite: nil, time_zone: nil, latitude: nil, longitude: nil, addressable_id: 1, addressable_type: 0, created_at: "2016-01-01 22:01:31", updated_at: "2016-01-01 22:01:31">]> 该记录现在具有addressable_id,但没有addressable_type。填充此字段是否需要其他内容?
发布于 2016-01-01 08:54:15
这个表单没有addressable id/type字段,所以除非您在控制器中显式地设置它们或相关对象,否则获取nil是预期的。
仅在模型中定义关系表示可以以这种方式关联对象,但不设置实际值。实际上- rails有很多神奇之处,但是它不能猜测哪个profile是哪个地址的所有者
发布于 2016-01-01 21:03:01
具有多态关联的情况下,一个模型可以属于单个关联上的多个其他模型
这意味着ActiveRecord将自动分配Address模型的addressable_type & addressableid,这取决于创建它的关联模型。
例如..。
#app/models/profile.rb
class Profile < ActiveRecord::Base
has_many :addresses, as: :addressable
end
#app/models/address.rb
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
end如上所述,每次创建配置文件时,您都可以为其创建或分配地址。如果你有另一个模型(users),你也可以这样做。将在address记录上自动分配addressable_id & addressable_type:
#app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
def create
@profile = Profile.new profile_params
@profile.save
end
private
def profile_params
params.require(:profile).permit(...)
end
end--
您遇到的主要问题是,您对哪个模型具有关联的polymorphic元素感到困惑。
它们应该将引用返回到profile或相关模型所在的任何位置。
@profile = Profile.find x
@address = @profile.addresses.new address_params ...这将为profile模型分配addressable_id和addressable_type,允许您代表profile创建地址。
@address = current_user.addresses.new address_params这段完全相同的代码将允许您为用户创建地址(相同的模型、相同的关联等)。
要回答您的问题,您需要围绕关联的模型来确定您的对象创建的范围:
@address = Address.create(country: "AU")
@profile = Profile.find 1
@profile.addresses << @address您还可以执行以下操作:
@profile = Profile.find 1
@profile.addresses.create country: "AU"--
如果您希望地址“依赖”于其他地址,则需要添加一个parent_id列,并使用acts_as_tree或另一个层次结构gem。
https://stackoverflow.com/questions/34552688
复制相似问题