2013-05-20 70 views
8

我兩個型號UserSubmission如下:first_or_create通過電子郵件,然後保存嵌套模式

class User < ActiveRecord::Base 
    # Associations 
    has_many :submissions 
    accepts_nested_attributes_for :submissions 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :email, :name, :role, :submission_ids, :quotation_ids, :submissions_attributes 

    validates :email, :presence => {:message => "Please enter a valid email address" } 
    validates :email, :uniqueness => { :case_sensitive => false } 
end 

class Submission < ActiveRecord::Base 
    belongs_to :user 
    attr_accessible :due_date, :text, :title, :word_count, :work_type, :rush, :user, :notes 

    validates :work_type, :title, :text,:presence => true 
    validates :text, :length => { :minimum => 250 } 
    validates :word_count, :numericality => { :only_integer => true } 
end 

我有收集由這兩款車型所需要的數據的形式。用戶控制器:

def index 
    @user = User.new 
    @user.submissions.build 
end 

def create 
    @user = User.where(:email => params[:user][:email]).first_or_create(params[:user]) 

    if @user 
    redirect_to :root 
    else 
    render 'pages/index' 
    end 
end 

我想要做的是首先檢查用戶是否已經通過提交的電子郵件在系統中存在。如果是這樣,那麼我想爲該用戶創建一個提交。否則同時創建用戶和提交。

我很困惑如何用first_or_create方法做到這一點。

任何幫助表示讚賞。

回答

13

first_or_createaccepts a block。所以,你可以如下做到這一點:

@user = User.where(:email => params[:user][:email]).first_or_create do |user| 
    # This block is called with a new user object with only :email set 
    # Customize this object to your will 
    user.attributes = params[:user] 
    # After this, first_or_create will call user.create, so you don't have to 
end 
+0

我應該'合併'而不是分配給它,但這是我個人的偏好。更清潔一點。 –

+0

謝謝,似乎是最乾淨的答案 – chell

+0

只有在用戶不存在於數據庫中時纔會調用create。我發現這造成了一個問題,因爲當用戶已經存在時它不會創建提交對象 – chell

-3

嘿,我想應該是類似的東西

@user = User.first_or_create(params[:user]) 

然後在用戶模式

def first_or_create(params) 
    unless user = User.where(:email => params[:email]).first # try to find user 
    user = User.create(email: params[:user]) 
    # it should create also submission because of accepts_nested_attributes_for 
    else #user exsists so we need to create submission for him 
    user.submissions.create(params[:submissions]) 
    end 
end 
+1

['first_or_create'(http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-first_or_create)在ActiveRecord的存在了。你不應該寫自己的。 – Mischa

+0

如果用戶不存在,則此代碼不會創建提交。 – davogones

1

因爲你的使用情況有點複雜,它可能不會傷害拆分此成兩個單獨的行動。如果你想讓它以原子方式出現,你可以把它扔到transaction

User.transaction do 
    # Create the user if they don't already exist 
    @user = User.where(:email => params[:user][:email]).first_or_create 

    # Update with more attributes, and create nested submissions 
    @user.update_attributes(params[:user]) 
end 
+0

爲什麼我會將此作爲交易處理?這也會創建提交對象嗎? – chell

+0

我假設你的參數看起來像'{user:...,submissions_attributes:{...}}',因爲你的模型中有'accep_nested_attributes_for:submissions_attributes'。如果嵌套提交屬性,相關模型將自動創建。該事務將確保所有內容都以原子方式創建/更新(即它全部成功或全部回滾)。 – davogones

+0

我也喜歡這個答案。我是NOOB,不確定哪個是最好的答案。我使用RDX中的一種,因爲它只使用了一種方法。 – chell