我无法确定哪种类型的关联最适合我的应用程序。我有以下模型:Firm
,Client
和Case
。
公司处理许多案例。每个案例都可以分配一个或多个 客户端。因此,我最初的方法是:
class Firm < ActiveRecord::Base
has_many :cases
has_many :clients
end
class Case < ActiveRecord::Base
belongs_to :firm
has_many :clients
end
class Client < ActiveRecord::Base
belongs_to :firm
has_many :cases
end
但我认为有些事情是不对的。我在想has_many :through
协会会更好,但我不确定。
答案 0 :(得分:2)
假设案件永远不属于另一家公司:
class Firm < ActiveRecord::Base
has_many :clients
has_many :cases, through: :clients
end
class Client < ActiveRecord::Base
belongs_to :firm
has_and_belongs_to_many :cases
end
class Case < ActiveRecord::Base
has_and_belongs_to_many :clients
end
迁移联接表
rails g migration CreateJoinTableCaseClient case client
答案 1 :(得分:2)
Rails指南说“如果你需要在连接模型上进行验证,回调或额外的属性,你应该使用has_many:”。正如伟大的编码哲学家Avi Flombaum曾经躲过的那样,你怎么可能知道你的连接模型在申请过程的早期就不会有其他用途。无论您处于开发阶段,将来都无法看到您不需要扩展连接表。
解决这个问题:
# models/firm.rb
class Firm < ActiveRecord::Base
has_many :clients
has_many :cases, through: :clients
end
# models/client.rb
class Client < ActiveRecord::Base
belongs_to :firm
has_many :client_cases
has_many :cases, through: :client_cases
end
# models/case.rb
class Case < ActiveRecord::Base
has_many :client_cases
has_many :clients, through: :client_cases
end
# models/client_case.rb
class ClientCase < ActiveRecord::Base
belongs_to :client
belongs_to :case
end
你的问题必须在其他地方;我能够在终端中创建以下内容而没有任何错误。
f = Firm.create name: 'Magical Group' # => #<Firm id: 1...
b = f.clients.create name: 'Billy' # => #<Client id: 1...
m = f.clients.create name: 'Megan' # => #<Client id: 2...
c = Case.create name: 'Billy & Megan are getting married!' # => #<Case id: 1...
b.cases << c # => #<ActiveRecord::Associations::CollectionProxy
m.cases << c # => #<ActiveRecord::Associations::CollectionProxy
f.cases.count # => 2
f.cases.uniq.count # => 1
我提供了数据库架构,请确保您的类似:
ActiveRecord::Schema.define(version: 20150813173900) do
create_table "cases", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "client_cases", force: :cascade do |t|
t.integer "client_id"
t.integer "case_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "client_cases", ["case_id"], name: "index_client_cases_on_case_id"
add_index "client_cases", ["client_id"], name: "index_client_cases_on_client_id"
create_table "clients", force: :cascade do |t|
t.string "name"
t.integer "firm_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "clients", ["firm_id"], name: "index_clients_on_firm_id"
create_table "firms", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end