0

我無法獲得我的關聯以保存在localhost:3000/controller_name/new中。我相信這是由於belongs_tofailing validation,但我不知道如何解決它(除了通過requires:false/optional: true放棄關聯,其後果我不確定)。我在這個tutorial之後創建了我的關聯,但它是用於以前版本的rails。多態關聯交易在Rails 5中失敗

我有一個多態地址表,可以屬於事件,企業,用戶等我試圖將它添加到事件。

地址遷移 - 你可以看到它引用addressable

class CreateAddresses < ActiveRecord::Migration[5.1] 
    def change 
    create_table :addresses do |t|  
     t.string :address 

     t.decimal :latitude, null: false, precision: 10, scale: 6, index: true 
     t.decimal :longitude, null: false, precision: 10, scale: 6, index: true 

     t.references :addressable, polymorphic: true, index: true 
    end 
    end 
end 

地址模式:

class Address < ApplicationRecord 
    belongs_to :addressable, polymorphic: true 
end 

事件模型:

class Event < ApplicationRecord 
    has_one :address, as: :addressable 
    accepts_nested_attributes_for :address 
end 

事件控制器:

class EventsController < ApplicationController 
    #...stuff... 

    # GET /events/new 
    def new 
    @event = Event.new 
    @event.address = @event.build_address 
    #@event.address = Address.new(addressable: @event) 
    #@event.address = @event.create_address 
    #@event.address = @addressable.User.new 
    end 

    #...stuff... 

你可以看到我嘗試了多種方法來創建事件的地址,他們主要是創建下面的項目,使用addressable導致Nil崩潰。

#<Address id: nil, address: nil, latitude: nil, longitude: nil, addressable_type: "Event", addressable_id: nil> 

事件表(使用Simple_form寶石):

<%= simple_form_for @event do |f| %> 
    <%= f.input :name %> 
    <%= f.input :description %> 

    <%= f.simple_fields_for :address do |address| %> 
    <%= render :partial => 'shared/address/form', :locals => {:f => address} %> 
    <% end %> 

    <%= f.button :submit %> 
<% end %> 

地址形式分:

<!-- Google Maps Must be loaded --> 
<% content_for :head do %> 
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCMh8-5D3mJSXspmJrhSTtt0ToGiA-JLBc&libraries=places"></script> 
<% end %> 

<div id="map"></div> 

<%= f.input :address %> 
<%= f.input :latitude %> 
<%= f.input :longitude %> 

形式呈現的罰款。當我試圖保存我得到

Started POST "/events" for 127.0.0.1 at 2017-07-01 16:06:23 -0400 
Processing by EventsController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"R0zlSs3UUNV3x8sQn5ocmE4jP12uOsFza7FezBAuhP4sw2MhF1OhixF8sAfDsLpfMEX7x5rhJ9HZfbKna8ncEA==", "event"=>{"name"=>"asd", "description" 
=>"asd", "address_attributes"=>{"address"=>"asd", "latitude"=>"1", "longitude"=>"1"}}, "commit"=>"Create Event"} 
    (0.1ms) begin transaction 
    (0.1ms) rollback transaction 

而且我保留在new頁面上。如果我插入一個byebugcreate,並打印出@event.errors它表明:

#<ActiveModel::Errors:0x007fb29c34a9a8 @base=#<Event id: nil, name: "asd", description: "asd", min_users: nil, max_users: nil, start_time: nil, recurring: nil, created_at: nil, upd 
ated_at: nil>, @messages={:"address.addressable"=>["must exist"]}, @details={:"address.addressable"=>[{:error=>:blank}]}> 

我怎樣才能創建address.addressable?根據一些SO答案的建議,關閉需要驗證的後果是什麼?

回答

0

發現的問題,並寫了一個blog post在深入討論這一點。基本上我遇到了兩個單獨的問題

1.我收到的錯誤 - "address.addressable"=>["must exist"]。 address.addressable是'父'表的元組ID。在我的情況下,它是事件ID。這個錯誤試圖告訴我,當我們試圖將它保存在控制器的create函數中時,這個外鍵在新地址中丟失了。就像我在問題中所說的那樣,您可以設置optional:true來忽略這個問題,並且在保存事件後以某種方式神奇地被填充。或者,您可以在保存之前手動將其分配到創建功能中。

def create 
    @event = Event.new(event_params) 
    @event.address.addressable = @event #<<<<<<<<<<< manually assign address.addressable 
    respond_to do |format| 
    if @event.save #Saves the event. Addressable has something to reference now, but validation does not know this in time 
     format.html { redirect_to @event, notice: 'Event was successfully created.' } 
     format.json { render :show, status: :created, location: @event } 
    else 
     #dont forget to remove the 'byebug' that was here 
     format.html { render :new } 
     format.json { render json: @event.errors, status: :unprocessable_entity } 
    end 
    end 
end 

2.事件ID是一個字符串。在我的地址遷移中,我使用的是t.references :addressable, polymorphic: true, index: true,它是整數類型的別名和addressable_id。我需要將我的遷移更改爲使用字符串ID - 因此請刪除references行並將其添加。

t.string :addressable_id, index: true 
t.string :addressable_type, index: true 

這在博客文章稍微詳細介紹。

1

運行耙分貝:模式:轉儲,然後檢查DB/schema.rb裏面的文件,請確保您有2場如下 * t.integer:addressable_id, * t.string:addressable_type 和更多這裏的細節是關於Activerecord Polymorphic Associations鏈接,如果你有問題,你的模式,那麼你可以運行遷移如下

t.references :addressable, polymorphic: true, index: true 

的事件有過態關聯許多地址,你可以使用this link創建地址 及以下示例代碼

@address = @event.addresses.build(attributes = {}, ...) 

你可以使用@address不@ event.address

+0

我還沒有能夠測試它,但我知道該地址確實有可尋址的類型,我會在裏面。我在原文中包含了使用'@ event.build_address'的輸出。我認爲問題在於這會讓Id空了嗎? –

+0

如果您已經設置了連接,例如has_one或has_many,當您使用@ event.addresses.build(rails提供的方法)時,它會自動處理id,您不必手動插入/鍵入 – widjajayd

+0

我是當我在事件控制器的'new'函數中嘗試'@address = @ event.address.build'時,得到'nil:NilClass'的'undefined method'build'。而'未定義的方法'地址'爲#<事件:0x007f3f288c0820>你的意思是?地址地址='用於'@ event.address.build'。 '@ event.build_address'工作,但傳遞給我的形式'{「id」=> nil,「地址」=>無,「緯度」=>零,「經度」=>零,「addressable_type」= = >「Event」,「addressable_id」=> nil}'。 IDK爲什麼ID不在那裏。 –