我有一个Rails应用程序,它将位于遗留数据库之上,其中包含一些我不得不处理的丑陋表格。一个是与feature_attributes
相关的features
表。问题是这个feature_attributes
表没有主键。我不认为这是一个问题,但显然是。我的模型名称与表名不同,但我使用set_table_name
来指定正确的名称。
class Feature < ActiveRecord::Base
has_many :feature_attributes
end
class FeatureAttribute < ActiveRecord::Base
set_table_name 'feature_attribute'
belongs_to :feature
end
我加载了一项我知道已关联feature_attributes
并在其上调用feature.feature_attributes
的功能后,即可获得nil
。事实上,即使FeatureAttribute.first
给了我nil
。 FeatureAttribute.any?
的结果返回false
。我担心ActiveRecord没有读取表中的任何数据,因为没有主键。那是怎么回事?
feature_attribute
表格包含以下列。
feature_id
attribute_name
attribute_value
created_date
modified_date
帮助!
我还会注意到,直接针对MySQL服务器运行生成的SQL实际上会获得我想要的行。
SELECT `feature_attribute`.* FROM `feature_attribute` WHERE `feature_attribute`.`feature_id` = 24;
编辑:我很抱歉。下次我将学会查看我的database.yml
。显然我是从具有相同特征表的测试数据库中读取的,但feature_attribute
表完全是空的。
答案 0 :(得分:5)
尝试也设置主键:
class FeatureAttribute < ActiveRecord::Base
set_table_name 'feature_attribute'
set_primary_key 'feature_id'
belongs_to :feature
end
<强>更新强>
我认为你的问题在于其他任何地方。我刚刚测试过,ActiveRecords可以在没有主键的情况下正常工作:
对于一个简单的表:
class CreateThings < ActiveRecord::Migration
def change
create_table :things, :id => false do |t|
t.string :name
t.timestamps
end
end
end
在控制台中:
Loading development environment (Rails 3.1.1)
irb(main):001:0> Thing.create(:name=>'A name for the thing')
(0.1ms) BEGIN
SQL (0.3ms) INSERT INTO `things` (`created_at`, `name`, `updated_at`) VALUES ('2011-11-02 16:33:48', 'A name for the thing', '2011-11-02 16:33:48')
(40.3ms) COMMIT
=> #<Thing name: "A name for the thing", created_at: "2011-11-02 16:33:48", updated_at: "2011-11-02 16:33:48">
irb(main):002:0> Thing.first
Thing Load (0.7ms) SELECT `things`.* FROM `things` LIMIT 1
=> #<Thing name: "A name for the thing", created_at: "2011-11-02 16:33:48", updated_at: "2011-11-02 16:33:48">
irb(main):003:0>
更新2 不是很好:
irb(main):003:0> Thing.create(:name=>'Another thing')
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO `things` (`created_at`, `name`, `updated_at`) VALUES ('2011-11-02 16:40:59', 'Another thing', '2011-11-02 16:40:59')
(35.4ms) COMMIT
=> #<Thing name: "Another thing", created_at: "2011-11-02 16:40:59", updated_at: "2011-11-02 16:40:59">
irb(main):004:0> Thing.first
Thing Load (0.5ms) SELECT `things`.* FROM `things` LIMIT 1
=> #<Thing name: "A name for the thing", created_at: "2011-11-02 16:33:48", updated_at: "2011-11-02 16:33:48">
irb(main):005:0> Thing.last
Thing Load (11.8ms) SELECT `things`.* FROM `things` ORDER BY `things`.`` DESC LIMIT 1
Mysql2::Error: Unknown column 'things.' in 'order clause': SELECT `things`.* FROM `things` ORDER BY `things`.`` DESC LIMIT 1
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'things.' in 'order clause': SELECT `things`.* FROM `things` ORDER BY `things`.`` DESC LIMIT 1
答案 1 :(得分:3)
如果某个功能只能出现一次某个属性,则假定attribute_name
是关键,并与feature_id
结合使用。 Rails不支持开箱即用的复合主键,但有一个名为composite_primary_keys的gem支持它。
在你的模型中,你可以写
set_primary_keys :feature_id, :attribute_name
如果某个功能可以多次出现属性名称,则feature_id
,attribute_name
和attribute_value
的组合是关键,您应该写
set_primary_keys :feature_id, :attribute_name, :attribute_value
希望这有帮助。
[edit]替代方法:
以上显然还不够,所以你也可以做到以下几点:
class Feature
has_many :feature_attributes, :finder_sql => 'select * from feature_attributes where feature_id=\'#{id}\''
end
希望这确实有用:)
答案 2 :(得分:2)
class Feature < ActiveRecord::Base
self.table_name = 'legacy_table_name'
self.primary_key = nil
end
然后使用Feature.find_by field:'value'
或其他ActiveRecord查询进行查询。
答案 3 :(得分:1)
如果无法更新表只是添加自动增量主键,那么您可以更好地手动处理它:
class Feature < ActiveRecord::Base
# get rid of has_many feature_attributes and use this instead
def feature_attributes
FeatureAttribute.find_by_sql(["select * from feature_attribute where feature_id = ?", self.id])
end
end