简短版本:在试图处理Ruby-on-Rails中的遗留数据库时,我遇到了一些我不理解的类加载行为。
长版本:在我的工作中,我正在开发一个针对MySQL数据库运行的PHP代码库,它有时有用,但通常令人沮丧的命名约定。因此,它不适合典型的Ruby on Rails命名模式。一个例子:
create table objectOfSomeType (
OOSTid int primary key auto_increment,
OOSTatooID int,
OOSTname varchar(255) not null,
OOSTotherThing datetime,
OOSTenteredDate timestamp not null,
OOSTenteredBy varchar(32) not null,
OOSTmodifiedDate timestamp,
OOSTmodifiedBy varchar(32)
/* etc. */
);
create table another_type_of_object (
ATOOid int primary key auto_increment,
ATOOname varchar(255) not null
/* etc. */
);
值得注意的属性:
我试图建立一个ActiveRecord::Base
的子类,它有一些处理表前缀的函数。 E.g:
class ActiveRecordJob < ActiveRecord::Base
class_inheritable_accessor :table_prefix
class << self
# this class needs no table
abstract_class = true
# function to setup the prefix
def set_table_prefix(prefix)
self.table_prefix = prefix
set_primary_key "#{prefix}id"
end
# override the standard column_names to return prefix-less names
def column_names
names = super
if pfx = self.table_prefix
# obviously not a Rubist...
names = names.map { |n| n.sub(%r|^#{pfx}|, "") }
end
names
end
end
# override method_missing to set up non-prefixed versions
# if the prefixed version is found, otherwise fall back to super
def method_missing(method, *args)
if pfx = self.table_prefix
prefixed = pfx + method
if respond_to?(prefixed)
self.class.send(:define_method, method.to_sym) do
return send(prefixed, *args)
end
return send(method, *args)
end
end
super
end
end
class ObjectOfSomeType < ActiveRecordJob
set_table_name :objectOfSomeType
set_table_prefix :OOST
belongs_to :atoo, :class_name => 'AnotherTypeOfObject', :foreign_key => 'OOSTatooID'
end
class AnotherTypeOfObject < ActiveRecordJob
set_table_name :anotherTypeOfObject
set_table_prefix :ATOO
end
这适用于单个模型(ObjectOfSomeType
对象具有name
和otherProperty
属性)。但是,这些协会出了问题。举例来说,在object_of_some_type / show.html.erb模板中:
This works fine, no need for .OOSTname:
<%= h @oost.name %>
This works fine, accessing the prefixed name directly:
<%= h @oost.atoo.ATOOname %>
But this throws an exception, because the custom method_missing is not hit:
<%= h @oost.atoo.name %>
Surprisingly (to this Ruby noob), this does work.
<%= h @oost.atoo.class.find(@oost.atoo.id).name %> <!-- this line marked -->
After the above, working call, this also works:
<%= h @oost.atoo.name %>
标记的行是什么“修复”了这个问题?我可能会采用不同的方法(在这个数据库中设置一个充满RoR命名视图的数据库),但我仍然希望用我的Ruby知识填补这个空白。
答案 0 :(得分:1)
ActiveRecord在命名约定时非常自以为是。使用DataMapper可能会有更多的运气,它允许您设置一个模型,该模型使用其自己的Rails类命名约定作为其属性,但在保存或更新时,它们将被转换为数据库中的基础列名。