首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 4-多态关联

Rails 4-多态关联
EN

Stack Overflow用户
提问于 2016-01-01 08:30:11
回答 2查看 1.4K关注 0票数 1

我正在尝试用Rails4做一个应用程序。

我有一个配置文件模型和一个地址模型。

这些关联包括:

profile.rb

代码语言:javascript
复制
has_many :addresses, as: :addressable

address.rb

代码语言:javascript
复制
 belongs_to :addressable, :polymorphic => true

地址是一个多态模型。

我有一张地址表格,上面写着:

代码语言:javascript
复制
<%= 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控制台显示了以下内容:

代码语言:javascript
复制
#<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控制台创建一个新地址时,我键入:

代码语言:javascript
复制
Address.create(addressable: Address.first, profile_id: "1", country: "AU")

控制台错误是:

代码语言:javascript
复制
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):

代码语言:javascript
复制
 def new
    @profile = Profile.new
    @profile.qualifications.build
    @profile.visions.build
    @profile.personalities.build
    @profile.addresses.build

    authorize @profile
  end

我将嵌套属性添加到配置文件模型中的地址关联中:

代码语言:javascript
复制
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标记:

代码语言:javascript
复制
<div class="nested-fields">

在我的配置文件表单中,我将链接添加到表单partial:

代码语言:javascript
复制
              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

然后,当我尝试所有这些时,我得到这个错误:

代码语言:javascript
复制
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方法:

代码语言:javascript
复制
 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

另一件奇怪的事情是,当我查看在控制台中创建的最后一个地址时,它显示如下:

代码语言:javascript
复制
#<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。填充此字段是否需要其他内容?

EN

回答 2

Stack Overflow用户

发布于 2016-01-01 08:54:15

这个表单没有addressable id/type字段,所以除非您在控制器中显式地设置它们或相关对象,否则获取nil是预期的。

仅在模型中定义关系表示可以以这种方式关联对象,但不设置实际值。实际上- rails有很多神奇之处,但是它不能猜测哪个profile是哪个地址的所有者

票数 1
EN

Stack Overflow用户

发布于 2016-01-01 21:03:01

你和polymorphic associations搞混了

具有多态关联的情况下,一个模型可以属于单个关联上的多个其他模型

这意味着ActiveRecord将自动分配Address模型的addressable_type & addressableid,这取决于创建它的关联模型。

例如..。

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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或相关模型所在的任何位置。

代码语言:javascript
复制
@profile = Profile.find x
@address = @profile.addresses.new address_params ...

这将为profile模型分配addressable_idaddressable_type,允许您代表profile创建地址。

代码语言:javascript
复制
@address = current_user.addresses.new address_params

这段完全相同的代码将允许您为用户创建地址(相同的模型、相同的关联等)。

要回答您的问题,您需要围绕关联的模型来确定您的对象创建的范围:

代码语言:javascript
复制
@address = Address.create(country: "AU")

@profile = Profile.find 1
@profile.addresses << @address

您还可以执行以下操作:

代码语言:javascript
复制
@profile = Profile.find 1
@profile.addresses.create country: "AU"

--

如果您希望地址“依赖”于其他地址,则需要添加一个parent_id列,并使用acts_as_tree或另一个层次结构gem。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34552688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档