如何从Rails connection.execute转换数据类型

时间:2014-04-28 03:05:34

标签: ruby-on-rails activerecord arel

我收到的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

这会执行并给出DB的正确结果,如下所示:

{ "id" => "13",
  "name" => "Category 16",
  "handle" => "category_16",
  "total_skills" => "4",
  "total_completed" => "0",
  "total_verified" => "0"
}

所以,鉴于该方法已经是一个怪物,我宁愿不尝试通过结果.inject将所有数字投射到Fixnum中。有没有办法在使用connection.execute时将字段转换为正确的数据类型?

3 个答案:

答案 0 :(得分:2)

您可以使用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

答案 1 :(得分:2)

您可以利用find_by_sqlto_json

json_records = Arel::Table.find_by_sql(query.to_sql).to_json

然后您可以提取结果,如

result = JSON.parse json_records

有几种方法可以将ActiveRecord个对象转换为hash。这只是我个人的偏好。

答案 2 :(得分:0)

顺便说一下,这是我不想使用的方法,因为代码很难理解,因为它是。

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