Испытывание затруднений из-за AR 2.3.5, например:
users = User.all( :select => "u.id, c.user_id", :from => "users u, connections c",
:conditions => ... )
Возвраты, например:
=> [#<User id: 1000>]
>> users.first.attributes
=> {"id"=>1000, "user_id"=>"1000"}
Обратите внимание, что AR возвращается id
из модели, искавшей как числовой, но выбранный user_id
из модели, к которой присоединяются, как a String
, хотя оба int(11)
в схеме базы данных.
Как я мог лучше сформировать этот тип запроса для выбора столбцов таблиц, поддерживающих многоуровневые модели и получающих их естественный тип, а не String
? Кажется, что AR плывет на плоскодонке на этом куда-нибудь. Как я мог принудить возвращенные типы во время загрузки AR и не иметь для прикрепления .to_i
(и т.д.). на каждый апостериорный доступ?
Почему вы используете: from => "users "внутри User.method? Следующее будет выполнять внутреннее соединение (что вы в любом случае делаете)
users = User.all(:include => :connections, :select => "users.id, connections.user_id", :conditions => {...})
Это будет очень сложный запрос для базы данных. Однако более быстрый запрос будет с внешним соединением.
Это также вернет ключи как INT, а не STRING
Гораздо более быстрая альтернатива была
Connection.all(:include => :user, :conditions => {...}).collect {|e| [e.user_id, e.id] }
Это дает вам массив массивов с идентификаторами. Если вы собираетесь выбрать только столбцы «id, user_id», то это не обязательно должно быть как объект AR. Массив может быть быстрее.
Надеюсь, я не упустил здесь какой-то момент. Предложите мне, если я.
Это, к сожалению, не произойдет очень легко. Все данные из соединения с БД поступают в rails в виде строк, преобразование типов происходит в каждом из методов динамических атрибутов, которые rails создает во время выполнения. Он знает, какие атрибуты преобразовать в какой тип по метаданным типа столбца таблицы, которые он извлекает при запуске приложения. Каждая модель имеет только метаданные столбца для своих собственных столбцов, поэтому собственные столбцы имеют правильный тип. Нет простого способа автоматического преобразования в правильные типы.
С другой стороны, вы можете создать простой метод преобразования, который будет принимать хэш и автоматически преобразовывать атрибуты.
Примерно так:
users = User.all(:select => "cl, comments.c2", ...)
users = convert_columns(users, 'c2' => :integer, 'other_column' => :date)
def convert_columns(records, columns = {})
records.each do |rec|
columns.each do |col, type|
rec[col] = case type
when :int then rec[col].to_i
when :date then ........
....
end
end
end
end
Если вам нужно быстрое решение - попробуйте использовать обратный вызов after_find и задайте там правильные типы атрибутов:
class User < ActiveRecord::Base
after_find :preset_types
private
def preset_types user
user.user_id = user.user_id.to_i
end
end