Ruby on rails 活动记录模型的动态表名称
我有一个有趣的活动记录问题,我不太确定是什么 最干净的解决方案是。我正在与之集成的遗留数据库 在它的模式中有一个奇怪的折痕,其中有一个逻辑表 “分区”为多个物理表。每张桌子都有相同的颜色 结构,但包含有关不同项的数据 我不擅长清楚地解释这一点(你可以看出!)。让我试试 并举例说明。假设我们有一辆车,它有 一个或多个轮子。通常我们会用一张汽车表和一个 如下所示:Ruby on rails 活动记录模型的动态表名称,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我有一个有趣的活动记录问题,我不太确定是什么 最干净的解决方案是。我正在与之集成的遗留数据库 在它的模式中有一个奇怪的折痕,其中有一个逻辑表 “分区”为多个物理表。每张桌子都有相同的颜色 结构,但包含有关不同项的数据 我不擅长清楚地解释这一点(你可以看出!)。让我试试 并举例说明。假设我们有一辆车,它有 一个或多个轮子。通常我们会用一张汽车表和一个 如下所示: CREATE TABLE cars ( `id` int(11) NOT NULL auto_increment, `name`
CREATE TABLE cars (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255),
;etc
)
CREATE TABLE wheels (
`id` int(11) NOT NULL auto_increment,
`car_id` int(11) NOT NULL,
`color` varchar(255),
;etc
)
到目前为止,一切顺利。但在我的遗产中,有一种“分裂”的策略
它看起来更像:
CREATE TABLE cars (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255),
;etc
)
CREATE TABLE car_to_wheel_table_map (
`car_id` int(11) NOT NULL,
`wheel_table` varchar(255)
)
CREATE TABLE wheels_for_fords (
`id` int(11) NOT NULL auto_increment,
`car_id` int(11) NOT NULL,
`color` varchar(255)
)
CREATE TABLE wheels_for_buicks (
`id` int(11) NOT NULL auto_increment,
`car_id` int(11) NOT NULL,
`color` varchar(255)
)
CREATE TABLE wheels_for_toyotas (
`id` int(11) NOT NULL auto_increment,
`car_id` int(11) NOT NULL,
`color` varchar(255)
)
这里我们有一套用于桌子的轮子,还有
car\u to_wheel\u table\u map table包含从car\u id到
包含特定汽车车轮的特定车轮。如果我
要想找到一套汽车的轮子,我首先要找出哪一套
车轮表使用通过汽车\u到\u车轮表\u地图表,然后查看
在car_to_wheel_table_映射中指定的车轮表中的up记录
首先,有人能告诉我是否有一个标准的名字吗
这个技巧
第二,有没有人对我如何使这项工作在
以一种非常干净的方式进行活动记录。在我看来,我可以
Wheel模型,其中可以为每个实例定义表名,或者我可以
在运行时使用正确的表名动态创建模型类
如映射表中所指定
编辑:请注意,将架构更改为更接近AR想要的内容不是一个选项。各种遗留代码库都依赖于此模式,无法实际修改。为什么不简单地将所有控制盘放在一个表中,并使用一个标准:has\u many?您可以在迁移中执行此操作:
DB表分区实际上是非常常见的做法。如果有人以前没有这样做过,我会感到惊讶。ActsAsPartitionable怎么样
另一种可能性:您的DBMS可以假装分区是一个大表吗?我认为MySQL支持这一点。我将在模型中与自定义函数进行关联:
has_one :cat_to_wheel_table_map
def wheels
Wheel.find_by_sql("SELECT * FROM #{cat_to_wheel_table_map.wheel_table} WHERE car_id == #{id}")
end
也许您可以使用与:finder\u sql的关联来实现,但我不确定如何将参数传递给它。我使用了ModelWheel,如果希望ActiveRecord映射数据,则必须定义它。可能您可以从现有的带轮子的表中创建此模型
我没有测试它;) 这里有一个方法可以做到这一点。基本(在70行代码之前)是:
- 为每种车型创建一个
- 定义一个方法“wheels”,该方法使用关联中的表名来获取正确的控制盘
#!/usr/bin/env ruby
%w|rubygems active_record irb|.each {|lib| require lib}
ActiveSupport::Inflector.inflections.singular("toyota", "toyota")
CAR_TYPES = %w|ford buick toyota|
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database => ":memory:"
)
ActiveRecord::Schema.define do
create_table :cars do |t|
t.string :name
end
create_table :car_to_wheel_table_map, :id => false do |t|
t.integer :car_id
t.string :wheel_table
end
CAR_TYPES.each do |car_type|
create_table "wheels_for_#{car_type.pluralize}" do |t|
t.integer :car_id
t.string :color
end
end
end
CAR_TYPES.each do |car_type|
eval <<-END
class #{car_type.classify}Wheel < ActiveRecord::Base
set_table_name "wheels_for_#{car_type.pluralize}"
belongs_to :car
end
END
end
class Car < ActiveRecord::Base
has_one :car_wheel_map
CAR_TYPES.each do |car_type|
has_many "#{car_type}_wheels"
end
delegate :wheel_table, :to => :car_wheel_map
def wheels
send("#{wheel_table}_wheels")
end
end
class CarWheelMap < ActiveRecord::Base
set_table_name "car_to_wheel_table_map"
belongs_to :car
end
rav4 = Car.create(:name => "Rav4")
rav4.create_car_wheel_map(:wheel_table => "toyota")
rav4.wheels.create(:color => "red")
fiesta = Car.create(:name => "Fiesta")
fiesta.create_car_wheel_map(:wheel_table => "ford")
fiesta.wheels.create(:color => "green")
IRB.start if __FILE__ == $0
#/usr/bin/env ruby
%w | rubygems active | u record irb |。每个{| lib | require lib}
ActiveSupport::拐点。拐点。单数(“toyota”、“toyota”)
汽车类型=%w |福特别克丰田|
ActiveRecord::Base.logger=logger.new(标准输出)
ActiveRecord::Base.build\u连接(
:adapter=>“sqlite3”,
:数据库=>“:内存:”
)
ActiveRecord::Schema.define do
创建表格:汽车不需要|
t、 字符串:名称
结束
创建表:汽车到车轮表映射,:id=>false do | t|
t、 整数:车号
t、 字符串:轮_表
结束
汽车类型。每个都有汽车类型|
创建表格“wheels(车轮){car#u type.pluralize}”do|t|
t、 整数:车号
t、 字符串:颜色
结束
结束
结束
汽车类型。每个都有汽车类型|
评估“Rav4”)
rav4.创建汽车车轮地图(:车轮表格=>“丰田”)
rav4.wheels.create(:color=>“red”)
嘉年华=汽车。创建(:name=>“嘉年华”)
嘉年华。创建汽车车轮地图(:车轮表格=>“福特”)
fiesta.wheels.create(:color=>“green”)
IRB.start如果文件=0美元
这个怎么样?(要点如下:)
#/usr/bin/env ruby
%w | rubygems active | u record irb |。每个{| lib | require lib}
ActiveSupport::拐点。拐点。单数(“toyota”、“toyota”)
ActiveRecord::Base.logger=logger.new(标准输出)
ActiveRecord::Base.build\u连接(
:adapter=>“sqlite3”,
:数据库=>“:内存:”
)
ActiveRecord::Schema.define do
创建表格:汽车不需要|
t、 字符串:名称
结束
创建表:汽车到车轮表映射,:id=>false do | t|
t、 整数:车号
t、 字符串:轮_表
结束
创建表格:fords do的车轮|
t、 整数:车号
t、 字符串:颜色
结束
创建表格:丰田汽车的车轮|
t、 整数:车号
t、 字符串:颜色
结束
结束
类Wheel:汽车车轮图
def车轮
@车轮| |=开始
_klass=“#{wheel_table.classify}wheel”
评估“丰田”)
嘉年华=汽车。创建(:name=>“嘉年华”)
嘉年华。创建汽车车轮地图(:车轮表格=>“福特”)
rav4.wheels.create(:color=>“red”)
fiesta.wheels.create(:color=>“green”)
#IRB.start如果文件=0美元
很遗憾,我知道你的麻烦。任何想在你的数据库中划分表的人一定是被你的老板解雇了,然后被我雇用了;-)
无论如何,解决方案(通过RailsForum):
就是使用尼克博士的魔法模型
干杯假设1:你知道你在看什么类型的车,所以你可以判断它是福特还是道奇 让我们将汽车品牌放入一个名为(所有事物中)品牌的属性中。 您应该稍后对此进行规范化,但现在让我们保持简单
CREATE TABLE cars (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255),
'make' varchar(255),
#ect
)
class Wheel < ActiveRecord::Base
def find_by_make(iMake)
select("wheels_for_#{iMake}.*").from("wheels_for_#{iMake}");
end
#...
end
创建表车(
`id`int(11)非空自动增量,
`名称`varchar(255),
“make”varchar(255),
#ect
)
类WheelCREATE TABLE cars (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255),
'make' varchar(255),
#ect
)
class Wheel < ActiveRecord::Base
def find_by_make(iMake)
select("wheels_for_#{iMake}.*").from("wheels_for_#{iMake}");
end
#...
end