表视图中丢失了ActiveRecord / sqlite3列类型?

时间:2010-05-06 16:50:49

标签: ruby activerecord sqlite types

我有以下ActiveRecord测试用例,模仿我的问题。我有一个People表,其中一个属性是日期。我在该表上创建了一个视图,添加了一个列,即该日期加上20分钟:

#!/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世界中的Time或DateTime时。有什么想法吗?

我也尝试过:

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;

结果相同。

2 个答案:

答案 0 :(得分: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

另外,sqlite-users中的quoting this mail

  

RoR应该使用   sqlite3_column_type()确定API   从a返回的值的类型   查询。其他API如   sqlite3_column_decltype()和pragma   table_info正在返回其他   信息,而不是类型   结果值。

答案 1 :(得分:0)

嗯,基本上SQLite中没有数据时类型而不是MySQL。在您的示例中,您明确定义了表的类型,但没有为视图指定类型。这可能是问题所在。因为我从未接触到红宝石,所以无法检查。