2010-10-23 45 views
2

我有一個紅寶石(on Rails的)類:爲什麼關聯對象不能保存?

class User < ActiveRecord::Base 
    # relationships 
    belongs_to :current_shipping_address, :class_name => "Address" 
    belongs_to :subscription 

    # Validators 
    validates_presence_of :subscription 
    validates_presence_of :current_shipping_address 
end 

我這樣做在一個控制器:

subscription = Subscription.new 

address_info = params[:user].delete(:address) rescue {} 
@address = Address.new(address_info.merge(:country => "US")) 

@user = User.new(params[:user].merge(:first_name => @address.first_name, :last_name => @address.last_name)) 
@user.subscription = subscription 
@user.current_shipping_address = @address 
@user.save! 

此時,不可思議的是,我有一個已經被保存在一個@user數據庫,但沒有current_shipping_address(儘管驗證)。訂閱也被保存在數據庫中。

地址不會被保存。

我在這裏錯過了什麼? 1 - 未驗證失敗,用戶如何保存? 2 - 爲什麼地址沒有保存?

我該如何修改這段代碼,以便保存地址(正如我所預期的那樣)?

我在Ruby on Rails的運行這3

謝謝!

回答

0

您不能在您的案例中保存由用戶保存的訂閱和current_shipping_address,因爲它們不是模型User中的簡單字段。您將它們定義爲通過belongs_to的關聯到用戶模式,我不知道你願意做什麼,但如果我理解正確的是使用嵌套的屬性做一個辦法:

class User < ActiveRecord::Base 
    # relationships 
    has_many :current_shipping_addresses, :class_name => "Address", :dependant => destroy 
    has_many :subscriptions, :dependant => destroy 


    # Nesting 
    accepts_nested_attributes_for :subscriptions 
    accepts_nested_attributes_for :current_shipping_addresses 

end 

之後,當,然後創建並保存一個用戶,訂閱和current_shipping_address將被保存。

更多關於關聯設定這裏:http://guides.rubyonrails.org/association_basics.html

+0

我不想讓很多......但你的鏈接幫助我出去! – phil 2010-10-24 08:45:26

0

你需要告訴它的外鍵是什麼,如果你不標準的表結構粘連。您只需要添加:

belongs_to :current_shipping_address, :class_name => "Address", :foreign_key => "address_id" 

或您正在使用的任何列將地址標識存儲到地址表。

雖然這不是推薦的嵌套屬性的方法。我會建議使用在你的形式fields_for而不是用線:

address_info = params[:user].delete(:address) rescue {} 
@address = Address.new(address_info.merge(:country => "US")) 

你可以做

<%= f.fields_for:current_shipping_address做| FF | %> #...您的地址字段... <%結束%>

那麼這將讓你只需保存的地址,當您運行@user.save!

您仍然可以

添加 :country => "US"事先
params[:user][:current_shipping_address][:country] = "US" 

然後運行保存。它真的取決於你。

+0

你的評論對於表單結構等是公平的,但是這實際上並沒有解決地址對象爲什麼沒有保存的問題(據我所知)。我正在使用formtastic,所以不幸的是你的解決方案並不直接適用於我。使用您的解決方案,您仍然可以最終保存地址。 – phil 2010-10-24 08:45:04

+0

哦,並且用戶對象上的字段是current_shipping_address_id,所以外鍵沒有問題, – phil 2010-10-24 08:53:04

0

試試這個方法!

subscription = Subscription.new 

address_info = params[:user].delete(:address) rescue {} 

@user = User.new(params[:user].merge(:first_name => @address.first_name, :last_name => @address.last_name)) 
@user.subscription = subscription 
@user.current_shipping_address << Address.new(address_info.merge(:country => "US")) 
@user.save! 
+0

這不起作用,因爲current_shipping_address不是數組 – phil 2010-10-24 08:43:31

0

似乎問題在於該地址實際上未能保存。不是因爲驗證,而是因爲'before_create'方法中的錯誤(是的,我知道我沒有給你地址對象......我當時不認爲它很重要!)。

class Address < ActiveRecord::Base 
    # relationships 

    # Validators 
    validates_presence_of :city, :state, :country, :first_name, :last_name, :address_1 

    before_create :check_state 
    before_create :check_country 

    def check_state 
    retval = true 
    state.upcase! 
    if country == "US" and !US_STATES.map{|s| s[1]}.include?(state) 
     errors.add(:state, "Must be valid") 
     retval = false 
    end 

    retval 
    end 
end 

檢查狀態失敗。但那意味着這個地址通過了'有效的'?電話,這似乎是所有積極的記錄關心。 (此方法真應了驗證)

我已轉做這個(感謝enokd的鏈接!):

@user = User.new(params[:user].merge(:first_name => @address.first_name, :last_name => @address.last_name)) 
@user.build_subscription(:subscription_plan_id => @subscription_plan.id) 
@user.build_current_shipping_address(address_info.merge(:country => "US")) 

我沒有打擾全面調查,但是,如果地址不保存它會停止整個@ user.save! 就我個人而言,我認爲這可能是一個小錯誤,當然也可能是一個意想不到的行爲,但是我知道些什麼!

+1

這可能會導致更多的問題。你應該做什麼而不是「before_create」,它應該是「驗證」。如果出現問題,這會給你的行爲(和失敗的消息)。 – jevy 2011-10-25 18:29:31

0

嘗試:

class User < ActiveRecord::Base 
    # relationships 
    has_one :current_shipping_address, :class_name => "Address", :dependant => destroy 
    has_many :subscriptions, :dependant => destroy 

    validates :current_shipping_address, :presence => true 
end 
相關問題