2014-04-28 41 views
1

我有一個AREL查詢,我生成了很多痛苦。供參考(對不起):如何從Rails中強制轉換數據類型connection.execute

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時,有沒有辦法將字段轉換爲適當的數據類型?

+0

爲什麼查詢會返回字符串而不是整數id,total_skills,total_completed和total_verified? –

+0

@JohnNaegle這就是問題,是啊:) –

回答

2

您可以採取的find_by_sqlto_json

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

優勢,然後你就可以提取您的結果一樣

result = JSON.parse json_records 

有幾種方法可將ActiveRecord對象轉換爲hash。這只是我個人的偏好。

+0

今天是2017和'Arel :: Table'沒有'#find_by_sql'方法。所以這個答案似乎是不正確的。 – 907th

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 
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