2012-10-19 34 views
0

我有一個應用程序,其中user可以有很多people,它可以有許多projects,它可以有很多invoices如何在更遠的關聯中設置外鍵?

在我invoice控制器我有這樣的動作:

def create 
    project = current_user.projects.find(params[:invoice][:project_id])  
    @invoice = project.invoices.build(params[:invoice]) 
    if @invoice.save 
    flash[:success] = "Invoice created." 
    redirect_to invoices_path 
    else 
    render :action => "new" 
    end 
end 

的問題是,它只要沒有project_id拋出一個錯誤。

據我所知,並試圖這樣的事情,而不是...

@invoice = current_user.people.projects.invoices.build(params[:invoice]) 

...但我得到一個錯誤undefined method projects然後。

我只是想確保一個新的invoice會自動關聯正確的user,並且沒有人可以篡改它。

有沒有辦法做到這一點?

+1

你的ActiveRecord關於'people'的外觀是什麼樣子的? –

+0

如果你可以做'current_user.projects.find'你不能也''current_user.projects.build'嗎?只要做到這一點,如果沒有項目要查找。 – gregates

+0

@gregates:感謝您的幫助。我不確定我明白你的意思。你的意思是如果沒有項目存在,我應該在我的'invoice'控制器中建立一個新的'project'? – Tintin81

回答

-1

您應該使用through

class User < ActiveRecord::Base 
    has_many :projects 
    has_many :invoices, through: projects 
end 

class Invoice < ActiveRecord::Base 
    has_many :projects 
    has_one :user, through: projects 
end 

class Project < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :invoice 
end 
+0

我其實是!但據我所知,「通過」只能連接三個關聯......?我有四個... – Tintin81

+0

好的,我認爲你有點混淆了你的關係。如果發票只能有1個用戶,則應該在用戶和發票之間建立直接關係。 – tagCincy

1

下面就來完成你想要的方式。我在我的控制檯中測試了它,所以它應該可以工作。我搞砸了人/人的多元化,但你應該明白。爲了測試目的,我給模型賦予了虛擬屬性。

class User < ActiveRecord::Base 
    attr_accessible :name 
    has_many :persons 

class Person < ActiveRecord::Base 
    attr_accessible :person_name, :user_id 
    belongs_to :user 
    has_many :projects 
    has_many :people_invoices 
    has_many :invoices, through: :people_invoices 

class Project < ActiveRecord::Base 
    attr_accessible :person_id, :project_name, :user_i 
    belongs_to :person 
    has_many :invoices 

class PeopleInvoice < ActiveRecord::Base 
    attr_accessible :invoice_id, :person_id 
    belongs_to :person 
    belongs_to :invoice 

class Invoice < ActiveRecord::Base 
    attr_accessible :invoice_amount, :person_id 
    belongs_to :project 
    has_many :people_invoice 
    has_many :persons, through: :people_invoices 

我給一些虛擬屬性,每個模型,你可以在上面的attr_accessible領域看到的。

在我的控制檯,我想:

@user = User.new(name: "User") 
@person = @user.persons.create(person_name: "Employee") 
@project = @person.projects.create(project_name: "foo") 
@invoice = @project.invoices.create(invoice_amount: 25) 
@person_invoice = @person.people_invoices.create(invoice_id:1) 

與您的協會這樣,那麼你可以撥打:

@user = User.find(4) 
<User id: 4, name: "User", created_at: "2012-10-19 20:18:28", updated_at: "2012-10-19 20:18:28"> 
@user.persons 
=> [#<Person id: 5, user_id: 4, person_name: "Employee", created_at: "2012-10-19 20:19:00", updated_at: "2012-10-19 20:19:00">] 
@person.invoices 
[#<Invoice id: 1, project_id: 2, invoice_amount: 25, created_at: "2012-10-19 19:33:10", updated_at: "2012-10-19 19:33:10">] 

因爲關聯,你應該能夠找到相應的發票項目和人員,並追溯到特定用戶。由於關係是has_many,你會得到數組返回給你(注意最後兩個控制檯輸出中的括號)。然後您必須在塊中循環查看或訪問特定值。

希望這會有所幫助!

+0

嘿,非常感謝您的幫助!我只是想知道爲什麼新模型PeopleInvoice是必要的。你能向我解釋一下嗎? – Tintin81

+0

當然。我用它作爲「橋樑」。「由於您希望與發票相關的人員,但不一定通過項目,PeopleInvoices是直接發送給人員和發票的一種方式,同時還允許他們獨立操作。它基本上是一個JOIN表,它具有直接進行關聯所需的關鍵字。可能使用HABTM關係,但這比這更靈活(請參閱第2.8節:http://guides.rubyonrails.org/association_basics.html#choosing-between-has_many-through-and-has_and_belongs_to_many)。 – jflores