在使用Rails创建对象时遇到问题(在尝试使用FactoryGirl创建实例时注意到它,返回的模型具有id=0
,即使它已正确保留并具有正确的ID在DB。其他工厂工作正常,这个似乎没有什么不同。值得注意的是,模型由DB视图支持而不是实际的表,但具有相同“条件”的其他模型正常工作。任何想法?
我的模特是:
class Property::Openhouse < ActiveRecord::Base
self.table_name = 'property_open_houses_view'
self.primary_key = 'id'
belongs_to :property, :inverse_of => :openhouses
attr_protected #allow access to all params
# [SNIP]
end
工厂:
FactoryGirl.define do
factory :open_house, class: 'Property::Openhouse' do
property
mls_system { property.mls_system }
mls_num { property.mls_num }
event_date 1.week.from_now
start_time "10:00AM"
end_time "6:00PM"
end
end
IRB(或测试)会发生什么:
development (main):0 > Property::Openhouse.count
(0.5ms) SELECT COUNT(*) FROM `property_open_houses_view`
=> 5
development (main):0 > oh = FactoryGirl.create :open_house
=> #<Property::Openhouse id: 0, property_id: 8, mls_num: "V123460", mls_system: :abcdef, event_date: "2014-04-24 19:57:27", start_time: "10:00AM", end_time: "6:00PM", remarks: nil, created_at: "2014-04-17 21:05:15", updated_at: "2014-04-17 21:05:15", open_house_type: nil, most_recent_import_id: nil, expired_at: nil>
development (main):0 > oh.persisted?
=> true
development (main):0 > oh.id
=> 0
development (main):0 > Property::Openhouse.last
Property::Openhouse Load (0.3ms) SELECT `property_open_houses_view`.* FROM `property_open_houses_view` ORDER BY `property_open_houses_view`.`id` DESC LIMIT 1
=> #<Property::Openhouse id: 6, property_id: 8, mls_num: "V123460", mls_system: "abcdef", event_date: "2014-04-24 19:57:27", start_time: "10:00AM", end_time: "6:00PM", remarks: nil, created_at: "2014-04-17 21:05:15", updated_at: "2014-04-17 21:05:15", open_house_type: nil, most_recent_import_id: nil, expired_at: nil>
development (main):0 > Property::Openhouse.count
(0.5ms) SELECT COUNT(*) FROM `property_open_houses_view`
=> 6
有什么想法吗?
UPDATE :我使用的是MySQL,视图由单个表支持
CREATE VIEW property_open_houses_view AS
SELECT
`id`,
`property_id`,
`mls_num`,
`event_date`,
`start_time`,
`end_time`,
`remarks`,
`created_at`,
`updated_at`,
`open_house_type`
FROM property_open_houses;
更新2014年4月21日
根据@Aaron K的建议,我查看了https://github.com/rails/rails/issues/5982,但我担心这可能不是我的情况,因为我的表定义没有default 0
的ID。
# db/schema.rb
create_table "property_open_houses", :force => true do |t|
t.string "mls_system", :limit => 30, :null => false
t.integer "property_id", :null => false
t.datetime "entered_at"
t.datetime "modified_at"
t.string "mls_num", :limit => 30, :null => false
t.datetime "event_date"
t.string "end_time", :limit => 30
t.string "start_time", :limit => 30
t.string "open_house_type", :limit => 30
t.text "remarks"
t.string "remote_sysid"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "most_recent_import_id"
t.datetime "expired_at"
end
我在schema.rb
以及直接在数据库中检查了两者,其中基础表中的ID是自动递增的非空主键整数。我的schema.rb
不包含视图,我们通过rake任务生成它们,该任务在db:migrate
之后自动运行,该任务会丢弃现有视图并通过运行我之前更新中显示的原始SQL重新创建它。有趣的是,如果我在MySQL上运行describe property_open_houses_view;
,ID字段将被列为默认值0.但是,对于我拥有的另一个表/视图对,即使相同的输出(ID默认为0)显示在{{ 1}},返回具有适当ID的Factory Girl模型。
行为不正确:
describe
正确行为:
mysql> describe property_open_houses_view;
+-----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | 0 | |
... SNIP ...
mysql> describe property_open_houses;
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
... SNIP ...
我注意到的一件事是,当我创建一个行为正确的模型实例(mysql> describe properties_view;
+---------------------------+----------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+----------------+------+-----+---------+-------+
| id | int(11) | NO | | 0 | |
... SNIP ...
mysql> describe properties;
+---------------------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+----------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
... SNIP ...
)时,生成的SQL Property
没有INSERT
字段,但行为不端一个(id
),有这样一个字段,它的值为0,DB会忽略它,用下一个自动增量值替换它。
Property::Openhouse
更新2014年4月21日第2部分
我刚刚意识到FactoryGirl似乎不是等式的一部分,因此更新了问题标题。使用SQL (1.1ms) INSERT INTO `property_open_houses_view` (`created_at`, `end_time`,
`event_date`, `expired_at`, `id`, `mls_num`, `mls_system`, `most_recent_import_id`,
`open_house_type`, `property_id`, `remarks`, `start_time`, `updated_at`) VALUES
('2014-04-21 15:03:25', '6:00PM', '2014-04-14 15:02:27', NULL, 0, 'V123456', 'abcdef',
NULL, NULL, 1032366, NULL, '10:00AM', '2014-04-21 15:03:25')
创建模型会引发相同的情况
create
答案 0 :(得分:0)
大多数数据库不允许您直接插入视图。有一些例外(例如视图是否由单个表支持)。例如,当您在视图上尝试INSERT
时,PostgreSQL将引发以下错误:
错误:无法插入视图“myview”
详细信息:不从单个表或视图中选择的视图不会自动更新。
提示:要启用插入视图,请提供
INSTEAD OF INSERT
触发器或无条件ON INSERT DO INSTEAD
规则。
其他数据库可能会有不同的行为,因此请查阅他们的文档。
继续使用PostgreSQL(和Rails 4.0.x)。当ActiveRecord
执行create
时,SQL如下所示:
INSERT INTO "mytable" ("created_at", "foo", "updated_at", "bar")
VALUES ($1, $2, $3, $4)
RETURNING "id"
[
["created_at", Thu, 17 Apr 2014 23:17:32 UTC +00:00],
["foo", "testing"],
["updated_at", Thu, 17 Apr 2014 23:17:32 UTC +00:00],
["bar", 4.0]
]
重要的部分是RETURNING "id"
。这里ActiveRecord被发送回创建的行的id
值。如果您的视图使用规则假装允许create
,请确保SQL具有适用于您数据库的RETURNING
语法。
似乎这可能是MySQL和Rails的已知问题。有关完整问题,请参阅https://github.com/rails/rails/issues/5982。