我有具有before_create
钩,其生成SHA散列,并将结果存储在所述对象的属性的ActiveRecord的对象:属性可用before_type_cast但零时直接访问
before_create :store_api_id
attr_reader :api_id
def store_api_id
self.api_id = generate_api_id
end
private
def generate_api_id
Digest::SHA1.hexdigest([Time.now.nsec, rand].join).encode('UTF-8')
end
这工作,所述api_id创建属性,并存储在数据库中的文本(这是通过调用.encode('UTF-8')
用力,否则会的SQLite试图将结果保存为二进制数据
但是以下规格的失败:
it "should be available as ad.api_id" do
@ad.save!
@ad.api_id.should_not be_nil
end
it "should match the directly accessed attribute" do
@ad.save!
@ad.api_id.should == @ad.attributes['api_id']
end
通过使用ad.api_id_before_type_cast
和ad.attributes['api_id']
,我可以得到正确的散列值,但在使用ad.api_id
时不能。
Ad.find_by_api_id('string api id')
也按预期工作,但在返回的对象上调用.api_id
时仍然返回null。
我已经双重检查在数据库中的类型,如下所示:
sqlite> select typeof(api_id) from ads;
text
下面是一个例子rails console
会话上的新鲜的Rails 3.2.2 /红宝石1.9.3-P125应用程式:
Loading development environment (Rails 3.2.2)
irb(main):001:0> ex = Example.new
=> #<Example id: nil, api_id: nil, created_at: nil, updated_at: nil>
irb(main):002:0> ex.save! (0.1ms) begin transaction
SQL (7.3ms) INSERT INTO "examples" ("api_id", "created_at", "updated_at")
VALUES (?, ?, ?) [["api_id", "fc83bb94420cf8fb689b9b33195318778d771c4e"],
["created_at", Fri, 23 Mar 2012 10:17:24 UTC +00:00],
["updated_at", Fri, 23 Mar 2012 10:17:24 UTC +00:00]]
(1.0ms) commit transaction
=> true
irb(main):003:0> ex.api_id
=> nil
irb(main):004:0> ex.api_id_before_type_cast
=> "fc83bb94420cf8fb689b9b33195318778d771c4e"
irb(main):005:0> ex.attributes['api_id']
=> "fc83bb94420cf8fb689b9b33195318778d771c4e"
irb(main):006:0>
看来,使用'attr_readonly:api_id'而不是'attr_reader:api_id'按预期工作。 – 2012-03-23 14:06:54