2010-05-06 38 views
0

我有下面的模仿我的问题的ActiveRecord测试用例。我有一个People表,其中一个属性是日期。我创建了该表中添加一列的观点就是一个将日期加20分:ActiveRecord/sqlite3列类型在表视图中丢失?

#!/usr/bin/env ruby 

%w|pp rubygems active_record irb active_support date|.each {|lib| require lib} 

ActiveRecord::Base.establish_connection(
:adapter => "sqlite3", 
:database => "test.db" 
) 

ActiveRecord::Schema.define do 
    create_table :people, :force => true do |t| 
    t.column :name, :string 
    t.column :born_at, :datetime 
    end 

    execute "create view clowns as select p.name, p.born_at, datetime(p.born_at, '+' || '20' || ' minutes') as twenty_after_born_at from people p;" 

end 

class Person < ActiveRecord::Base 
    validates_presence_of :name 
end 

class Clown < ActiveRecord::Base 
end 

Person.create(:name => "John", :born_at => DateTime.now) 

pp Person.all.first.born_at.class 
pp Clown.all.first.born_at.class 
pp Clown.all.first.twenty_after_born_at.class 

的问题是,输出

Time 
Time 
String 

当我想到视图的新datetime属性也是在Ruby世界中的时间或日期时间。有任何想法吗?

我也试过:

create view clowns as select p.name, p.born_at, CAST(datetime(p.born_at, '+' || '20' || ' minutes') as datetime) as twenty_after_born_at from people p; 

具有相同的结果。

回答

0

好了,更多的调查后,我发现:

MySQL的工作原理:

%w|pp rubygems active_record irb active_support date|.each {|lib| require lib} 

ActiveRecord::Base.establish_connection(
    :adapter => "mysql", 
    :username => "root", 
    :database => "test2" 
) 

ActiveRecord::Schema.define do 
    create_table :people, :force => true do |t| 
    t.column :name, :string 
    t.column :born_at, :datetime 
    end 

    execute "create view clowns as select p.name, p.born_at, (p.born_at + INTERVAL 20 MINUTE) as twenty_after_born_at from people p;" 
end 

class Person < ActiveRecord::Base 
    validates_presence_of :name 
end 

class Clown < ActiveRecord::Base 
end 

Person.create(:name => "John", :born_at => DateTime.now) 

pp Person.all.first.born_at.class 
pp Clown.all.first.born_at.class 
pp Clown.all.first.twenty_after_born_at.class 

产地:

Time 
Time 
Time 

读取sqlite3的转接器的源代码,我发现它使用PRAGMA table_info(table_name)获取类型信息,并且不返回视图类型:

sqlite> pragma table_info('people'); 
0|id|INTEGER|1||1 
1|name|varchar(255)|0||0 
2|born_at|datetime|0||0 
sqlite> pragma table_info('clowns'); 
0|name|varchar(255)|0||0 
1|born_at|datetime|0||0 
2|twenty_after_born_at||0||0 

因此,它可能是适配器的限制或只是sqlite3的视图限制。我有opened a ticket for ActiveRecord

此外,在quoting this mail源码用户:

回报率应该是使用 sqlite3_column_type()API来确定 值的类型从一个 查询返回。其他API如 sqlite3_column_decltype()和编译指示 table_info正在返回其他 信息,而不是 结果值的类型。

0

那么,基本上在SQLite中没有数据时间类型而不是MySQL。在你的例子中,你明确地定义了表格的类型,但是没有指定视图的类型。这可能是问题所在。由于我从未碰过红宝石,所以无法检查它。

+0

问题是RoR和sqlite3。第一个使用table_info PRAGMA进行视图时,它知道sqlite3不能给你一个视图的类型。它应该在结果集上使用sqlite3_column_type(但似乎ActiveRecord中的类型只能解析一次表)。 Sqlite的错误不是在视图中提供类型,它们可以映射到原始表,在这种情况下,也可以是datetime()函数的结果(MySQL至少可以)。 – duncan 2010-05-07 06:49:55