【问题标题】:Has and belongs_to many or has_many through example with active record通过具有活动记录的示例,拥有和属于_to many 或 has_many
【发布时间】:2013-08-07 17:24:56
【问题描述】:

假设我有一个虚构的汽车租赁应用程序。

我有用户、汽车和地址。

user (id, name, email)
  has_many :addresses
  has_many :cars

car (id, name)
  belongs_to :user

address (id, name, user_id)
  belongs_to :user

每个用户都有多个地址和汽车。地址是用户可以借车的位置。

现在,使用这个模型,我想做以下事情(假设用户 #1 有 2 个地址和 3 辆车):

Settings for User #1 : 
(specify at which address each of your cars are available)
/-------------------------------------------\
|           |  Car #1  | Car #2  |  Car #3  |
|-----------+----------+---------+----------|
| Address 1 |   yes    |  yes    |    no    |
|-----------+----------+---------+----------|
| Address 2 |   no     |  no     |   yes    |
\-------------------------------------------/

我认为你可以创建一个表cars_addresses (id, car_id, address_id, available:bool)

但我不知道如何用活动记录来指定。所以我的问题是:

  • 这是正确的架构结构吗?
  • 如何通过活动记录来实现?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord database-schema


    【解决方案1】:

    您需要的是汽车和地址之间的 has_and_belongs_to_many。然而,很多 rubbyists 会说永远不应该使用这种关系(应该使用 has_many :through 代替)这是一个完美的地方,因为我想不出需要在这些模型之间存储的任何额外信息。所以它会是:

    user (id, name, email)
      has_many :addresses
      has_many :cars
    
    car (id, name)
      belongs_to :user
      has_and_belongs_to_many :addresses
    
    address (id, name, user_id)
      belongs_to :user
      has_and_belongs_to_many :cars
    

    然后您需要创建没有 id 和两个列的表addresses_cars(订单很重要,不需要模型):address_id 和car_id。而已!它会“神奇地”工作:

    user.cars.first.addresses => list of location car is available
    user.addresses.first.cars => list of cars available under address
    user.addresses.first.cars << user.cars.first => add a car to given address
    

    【讨论】:

      【解决方案2】:

      这取决于您的“汽车”型号代表什么。

      如果它是一辆不能同时出现在多个位置的实体汽车,那么另一个关系就可以了:

      car (id, name, location_id)
          belongs_to :user
          belongs_to :location
      
      location (id, name, user_id)
          belongs_to :user
          has_many :cars
      

      这将使关系发挥作用:

      #list each car and it's location
      current_user.cars.each do |car| { puts "#{car.name} is at #{car.location.name}" }  
      

      #how many cars are at each location
      current_user.locations.each do |location| { puts "#{location.cars.count} of your cars are at #{location.name}" }
      

      为汽车设置位置:

      #move car with id=5 to location with id=15
      c=Car.find(5)
      l=Location.find(15)
      c.location=l
      c.save
      

      c=Car.find(5)
      c.location_id=15
      c.save
      

      顺便说一句,我建议将您的模型命名为“位置”而不是“地址”。 Ruby 会自动生成许多带有复数名称的方法,因此使用简单的复数形式的单词会帮助您避免一些混淆。

      【讨论】:

      • 感谢您的回复。在我的模型中,一辆汽车可以同时在多个位置:它们代表汽车在哪里可用。所以我会选择 habtm。
      猜你喜欢
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多