Rails有办法处理has_one连接表吗?

时间:2012-08-26 15:36:14

标签: ruby-on-rails ruby activerecord associations

考虑以下模型设置:

Model A
  has one B1, type: B
  has one B2, type: B

Model B
  has many A

我希望能够完成这项工作:

class Motorcycle < ActiveRecord::Base
  has_one :front_tire, class_name: "Tire"
  has_one :back_tire, class_name: "Tire"
end

class Tire < ActiveRecord::Base
  has_many :motorcycles
end

最终结果是我能够做到这一点:

m = Motorcycle.new
ft = Tire.new
bt = Tire.new
m.front_tire = ft
m.back_tire = bt
m.save
Tire.first.motorcycles #=> [...]

5 个答案:

答案 0 :(得分:1)

您不能has_manyhas_one配对,has_*需要与belongs_to配对(当然除了has_many :through)。< / p>

因此,您需要更改为motorcycle belongs_tofront_tire或创建第三个联接模型。

答案 1 :(得分:1)

我认为你正在寻找基本Single-table Inheritance,因为前轮胎和后轮胎确实不是一回事,而是特定类型的轮胎。为此,您需要在type表中添加tires字符串列,并声明Tire类的两个子类:

class Motorcycle < ActiveRecord::Base
  belongs_to :front_tire
  belongs_to :back_tire
end

class Tire < ActiveRecord::Base
end

class FrontTire < Tire
  has_many :motorcycles
end

class BackTire < Tire
  has_many :motorcycles
end

这将允许您使用Tire.first,这将返回FrontTireBackTire的实例,其中会有许多motorcycles。这符合您的Tire.first.motorcycles要求。

m = Motorcycle.new
ft = FrontTire.new # id 1
bt = BackTire.new  # id 2
m.front_tire = ft
m.back_tire = bt
m.save
Tire.first.motorcycles # returns FrontTire #1

# Or, find specifically by tire type
FrontTire.first.motorcycles # all motorcycles with this front-tire
BackTire.first.motorcycles  # all motorcycles with this back-tire

或者,您可以简单地使用通用tires关系,因为前轮胎和后轮胎是不同的类别:

class Motorcycle
  has_many :tires
end

class Tire < ActiveRecord::Base
end

class FrontTire < Tire
  has_many :motorcycles, foreign_key: :tire_id
end

class BackTire < Tire
  has_many :motorcycles, foreign_key: :tire_id
end

Npw Motorcycle.first.tires将返回两个对象的数组,一个FrontTire的实例和一个BackTire的实例。您可能希望添加验证器以防止将多个前/后轮胎分配到同一辆摩托车。

答案 2 :(得分:0)

这根本没有经过测试,但是这样的事情怎么样:

has_many :motorcycles,
         :class_name => 'Motorcycle',
         :finder_sql => proc { "select * from motorcycles
                         where front_tire_id = #{id} OR
                         back_tire_id = #{id}" }

答案 3 :(得分:0)

我认为这样的事情应该有效

class Tire < ActiveRecord::Base
  belongs_to :motorcycle
end

has_many :motercycles更改为belongs_to :motorcycle

Motorcycle有很多轮胎(通过has_oneTires属于motorcycle

或者你可以使用像

这样的东西
class Motorcycle < ActiveRecord::Base
  has_many :tires
end

class Tire < ActiveRecord::Base
  belongs_to :motorcycle
end
含有Tire的{​​{1}}的

可以包含前面或后面的值

你可以在模型中创建一些常量来维护像

这样的常量
column position

这只是另一种选择:)

答案 4 :(得分:-1)

我设法用这组代码解决了这个问题:

class Motorcycle < ActiveRecord::Base
  has_many :tire_brands
  has_one :front_tire, class_name: "Tire"
  has_one :back_tire, class_name: "Tire"
end

class Tire < ActiveRecord::Base
  belongs_to :motorcycle
  belongs_to :tire_brand
end

class TireBrand < ActiveRecord::Base
  has_many :tires
  has_many :motorcycles, through: :tires
end