2016-01-01 155 views
1

我試圖讓一個應用程序在Rails的4軌道4 - 多態關聯

我有一個輪廓模型和地址模式。

的關聯是:

profile.rb

has_many :addresses, as: :addressable 

address.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 %> 

我嘗試創建一個地址並保存。然後我檢查它是否在軌道控制檯中。有些事情出錯了,因爲滑軌控制檯顯示了這一點:

#<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"> 

可尋址標識和可尋址類型都爲零。

他們應該將引用返回到配置文件或相關模型的任何位置。

有沒有設立這個過程中缺少一個步驟?

此視頻(分鐘3.40)說:軌自動處理填寫多態模型的類型和ID領域。 https://gorails.com/episodes/comments-with-polymorphic-associations?autoplay=1

當我嘗試從鐵軌控制檯一個新的地址,I型:

Address.create(addressable: Address.first, profile_id: "1", country: "AU") 

控制檯錯誤是:

ActiveRecord::UnknownAttributeError: unknown attribute 'profile_id' for Address 

我的地址表有一個addressable_id鍵和我輪廓模型的has_many:地址,如:可尋址

我不明白是什麼原因導致的錯誤

另一種嘗試

所以,從我從下面的建議收集,我需要做一些事情,讓地址知道它屬於一個輪廓。

我也發現了這篇文章,其中載列的哪些需要在配置文件控制器發生把事情多態協會工作的例子: http://6ftdan.com/allyourdev/2015/02/10/rails-polymorphic-models/

我在型材控制器改變我的新行動(包括地址。建):

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"> 

在我的配置形式,我添加鏈接到窗體部分:

   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" 

個錯誤指向型材控制器更新方法:

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。是否有額外的需要填充此字段?

回答

1

此表單沒有addressable id/type字段,所以除非你明確地設置它們或控制器中的相關對象變得nil是預期的。

定義模型中的關係只表明對象可以用這種方式關聯,但不會設置實際值。其實 - 軌道有很多在它的魔力,但它不能猜出哪個profile是地址

+0

但你如何設置它們? – Mel

+0

@ user2860931只是將它們聲明爲隱藏或選擇可尋址的地址,或者如果您稍後可以將其設置爲保留,則可以跳過驗證addressable_id爲零。 –

+0

但如果地址表單屬於配置文件,並且編輯配置文件路徑導致地址表單,則不是鏈接。如果我讓用戶選擇ID,那麼如果要求用戶選擇他們自己的配置文件ID來添加地址,那麼它在表單中會顯得很奇怪。沒有一個例子顯示需要隱藏字段才能使其工作。請你可以告訴我一個這樣的例子的鏈接?非常感謝 – Mel

0

你得到與polymorphic associations混淆店主:

With polymorphic associations, a model can belong to more than one other model, on a single association

這意味着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),你可以做同樣的事情。該addressable_id & addressable_type會自動在address記錄被分配:

#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元素。

They should have the references back to profile or wherever the related model is.

@profile = Profile.find x 
@address = @profile.addresses.new address_params ... 

這將分配addressable_idaddressable_typeprofile模式,讓您代表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或其他層次寶石。

+0

我可以更新它,如果它不清楚 –

+0

嗨Rich。謝謝你。我不確定你在建議如何將地址鏈接到個人資料。我是否需要向配置文件控制器添加一些新的操作來構建profile.address?看看上面這一行,「@address = @ profile.addresses.new address_params ...」 - 我不確定在我的配置文件控制器中使用這個位置。我無法在任何資源中找到這樣的例子。 – Mel

+0

我也困惑你的評論,我很困惑哪個模型有關聯的多態元素。我想我的關聯設置正確 - 我看不出您的示例和我的代碼之間的區別 – Mel