Как привести тип данных из Rails connection.execute
У меня есть запрос AREL, который я генерировал с большой болью. Для справки (извините):
def self.summarize_user(user)
c = Arel::Table.new(:categories)
s = Arel::Table.new(:skills)
cp = Arel::Table.new(:completions)
query = c.project(c[:id], c[:name], c[:handle])
.project(s[:id].count.as("total_skills"))
.project(cp[:id].count.as("total_completed"))
.project(cp[:verified_on].count.as("total_verified"))
.join(s).on(s[:category_id].eq c[:id])
.join(cp, Arel::Nodes::OuterJoin).on(cp[:skill_id].eq s[:id])
.where(cp[:user_id].eq(user.id).or(cp[:user_id].eq nil))
.group(c[:id], c[:name], c[:handle])
# this is the relevant bit
connection.execute(query.to_sql)
end
Это выполняет и дает мне правильные результаты из БД, которые выглядят так:
{ "id" => "13",
"name" => "Category 16",
"handle" => "category_16",
"total_skills" => "4",
"total_completed" => "0",
"total_verified" => "0"
}
Итак, учитывая, что метод уже монстр, я бы не стал пытаться .inject
через результаты, чтобы привести все числа в Fixnum. Есть ли способ, при использовании connection.execute
, чтобы привести поля к их соответствующим типам данных?
3 ответа
Решение
Вы можете воспользоваться find_by_sql и to_json
json_records = Arel::Table.find_by_sql(query.to_sql).to_json
Затем вы можете извлечь свои результаты, как
result = JSON.parse json_records
Есть несколько способов конвертировать ActiveRecord
возражает против hash
, Это всего лишь мое личное предпочтение.
Вы могли бы использовать Virtus
class Summary
include Virtus.model
attribute :id, Integer
attribute :name, String
attribute :handle, String
attribute :total_skills, Integer
attribute :total_completed, Integer
attribute :total_verified, Integer
end
summary.map { |results| Summary.new(results) }
hsh = { "id" => "13",
"name" => "Category 16",
"handle" => "category_16",
"total_skills" => "4",
"total_completed" => "0",
"total_verified" => "0"
}
s = Summary.new(hsh)
s.total_skills # => 4
Кстати, вот метод, который я предпочел бы не использовать, так как код достаточно сложен, чтобы понять, как он есть.
def self.summarize_user(user)
# ... sins against nature ...
result = connection.execute(query.to_sql)
self.map_summary(result)
end
protected
def self.map_summary(summary)
summary.map do |result|
{
id: result['id'].to_i,
name: result['name'],
handle: result['handle'],
total_skills: result['total_skills'].to_i,
total_completed: result['total_completed'].to_i,
total_verified: result['total_verified'].to_i,
}
end
end