Тип столбца ActiveRecord / sqlite3 потерян в табличном представлении? - PullRequest
0 голосов
/ 06 мая 2010

У меня есть следующий тестовый сценарий ActiveRecord, который имитирует мою проблему.У меня есть таблица людей с одним атрибутом даты.Я создаю представление над этой таблицей, добавляя один столбец, который является только этой датой плюс 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

Когда я ожидаю новую дату и времяАтрибут представления также должен быть Time или 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;

С таким же результатом.

Ответы [ 2 ]

0 голосов
/ 07 мая 2010

Ну, в принципе нет типа времени данных в SQLite, в отличие от MySQL. В вашем примере вы явно определяете типы для таблицы, но не указываете типы для представления. Это может быть проблемой. Не могу проверить, так как я никогда не трогал рубин.

0 голосов
/ 07 мая 2010

Ну, после дополнительного расследования я обнаружил, что:

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. У меня открыт тикет для ActiveRecord :

Также цитирование этого письма в sqlite-users:

RoR должен использовать sqlite3_column_type () API для определения тип значений, возвращаемых из запрос. Другие API, такие как sqlite3_column_decltype () и прагма table_info возвращают другие информация, а не тип значение результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...