【问题标题】:Optimal tables relationship for rails applicationsRails 应用程序的最佳表关系
【发布时间】:2014-08-04 08:35:33
【问题描述】:

假设,我想编写一个应用程序,允许用户根据不同的条件搜索汽车。例如,用户首先会知道哪个车型是由特定汽车制造商制造的;或者,根据汽车制造商和型号过滤汽车。

为了达到这个目的,我开始在我的 Db 中设计我需要的所有表:

  • 制造
  • 型号
  • 汽车

想法A

每个车型都与一个汽车制造商相关联,而一辆车只能与一个车型相关联。

优势 这种结构可以让我轻松识别属于特定汽车制造商的所有汽车型号或属于特定汽车型号的所有汽车。

缺点 进入汽车表没有直接指示汽车制造商(仅通过汽车型号)。

想法 B

每辆汽车都与汽车制造商和车型相关联。

优势 我现在可以访问汽车的所有信息,而无需浏览其他表格。

缺点 如果我想查找与特定型号或制造商相关的所有汽车,任务看起来很复杂。

我的问题

  1. 最佳策略是什么?有更好的解决方案吗?
  2. 从收集数据的角度来看,哪个更快?

【问题讨论】:

  • 架构中的“汽车”是什么?它是一辆实体车,已经制造出来并在某个地方的陈列室里吗?还是它仍然有点抽象?基本上,汽车和模型之间有什么区别?
  • 顺便说一句,您可能想要谈论“制造商”而不是“制造商”。 “Manufacture”是动词,“Manufacturer”是名词,意思是“制造的人”。因此,福特、保时捷等可能是您的制造商类的实例。
  • 汽车是代表物理汽车的对象。相反,模型只代表汽车的类型(如福特福克斯、嘉年华、蒙迪欧……)为了简化问题,我最小化了汽车的属性。当然,可以添加其他属性,例如发动机、燃料、颜色或马力。你是对的!我应该使用制造商而不是制造商。

标签: mysql sql ruby-on-rails database


【解决方案1】:

我会坚持使用您的版本 A,因为它更准确地反映了您正在建模的数据。每种车型都只有一家制造商生产,如果您知道汽车的型号,您可以立即推断出制造商。版本 B 没有这样的链接。

就 Rails 中的关联而言,您可以轻松地对关系建模:

class Manufacturer < ActiveRecord::Base
  has_many :models
  has_many :cars, through: :models
end

class Model < ActiveRecord::Base
  belongs_to :manufacturer
  has_many :cars
end

class Car < ActiveRecord::Base
  belongs_to :model
end

在直接访问汽车制造商方面,@car.model.manufacturer 当然可以,但您也可以使用委托方法更直接一点:

class Car < ActiveRecord::Base
  belongs_to :model
  delegate :manufacturer, to: :model
end

在搜索方面,Rails 可以让您找到需要去的地方。例如,要查找制造商名为“福特”的所有汽车:

Car.joins(:model => :manufacturer).where(manufacturers: { name: 'Ford' })

如果您需要执行任何更复杂的查询,您可以在您的joinswhere 调用中包含相关的SQL 片段。如果您超出了 ActiveRecord 的数据库调用和范围链接,您可以探索像 Squeel 这样的扩展,或直接访问 Arel - 但您描述的项目应该可以使用 AR 的本机调用,至少在开始时是这样。


就“收集数据”而言——您的方法 B 将使您能够使用 Rails 助手构建一个表单,该表单能够将两个关联转换为下拉菜单或单选按钮。但是,正如我上面所说,您会失去数据建模的准确性。考虑一下您添加/删除制造商和型号的频率——如果它们经常更新,那么与所有制造商和型号都是预定义且很少更改的情况相比,这将对您的用户界面产生很大影响。

【讨论】:

  • 我同意,A 更好。在 B 中,如果您想知道哪个制造商制造了特定型号,则需要找到该型号的汽车记录并从那里查找,这绝对是错误的。
【解决方案2】:

这样做:

#app/models/car.rb
Class Car < ActiveRecord::Base
   #fields id | manufacturer_id | name | model | other | information | created_at | updated_at
   belongs_to :manufacturer
end

#app/models/manufacturer.rb
Class Manufacturer < ActiveRecord::Base
   #fields id | name | foundation_year | etc | etc
   has_many :cars
end

#app/models/model.rb
Class Model < Car
   self.inheritance_column = :model # http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/inheritance_column
   #this uses the Car model to populate different "models". It will allow you to identify the model based on the car - using the same table for all
end

您可能不需要为Model 提供单独的表,因为我认为Car 本身就是Model?相反,我会考虑使用STI (Single Table Inheritance) 根据您定义的模型调用任何特定的汽车模型:

#app/controllers/models_controller.rb
Class ModelsController < ApplicationController
   def show
       @cars = Model.find params[:id]
   end
end

您应该真正使用具有多种型号的 STI(即,您的汽车中的每个 Model 都有一个特定的型号)。我建议反对它的原因是因为我假设您的每个 Car 对象都有自己的模型

如果不是这种情况,请使用以下建议。不过,


多个模型

处理模型/汽车的更简单方法是使用模型的简单关联:

#app/models/car.rb
Class Car < ActiveRecord::Base
   # fields id | manufacturer_id | name | other | car | details | created_at | updated_at
   has_many :models
   belongs_to :manufacturer
end

#app/models/manufacturer.rb
Class Manufacturer < ActiveRecord::Base
   has_many :cars
   #fields id | name | foundation_year | other | attributes | created_at | updated_at
end

#app/models/model.rb
Class Model < ActiveRecord::Base
   #fields id | name | wheels | engine | etc | created_at | updated_at
   belongs_to :car
end

这使您能够为每个“汽车”创建不同的模型 - IE 有一个“运动”版本等。


活动记录

你会是最好的reading up on ActiveRecord associations,以及他们在 Rails 中扮演的角色

您必须考虑 Rails 以 对象 为中心 - 这意味着您所做的一切都必须尽可能地模块化。如果你有一个表对同一个对象有多个属性,你会遇到问题

您需要考虑对象之间的关系(关联),以达到构建模型以反映如何调用它们的程度。这一点非常重要,因为目前,您正在寻找数据库设置——您需要将焦点切换到 object 设置

理想情况下,你想要这样:

@car = Car.find params[:id]
@car.models.each do |model|
   model.name
end

【讨论】:

    猜你喜欢
    • 2015-01-04
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    相关资源
    最近更新 更多