【问题标题】:ActiveRecord execute raw transaction typecasting?ActiveRecord 执行原始事务类型转换?
【发布时间】:2013-12-30 05:59:12
【问题描述】:

ActiveRecord::Base.connection.execute(sql)

结果未进行类型转换,因此它们都是字符串作为示例 ActiveRecord::Base.connection.execute(sql).entries

=> [{"id" => "1", "length" => "120", "content" => "something"},{"id" => "2", "length" => "200", "content" => "blahblah"}]

是否可以在 activerecord 中执行原始事务并返回类型转换的结果?

【问题讨论】:

  • AFAIK 没有。 AR 通常使用其对模式的了解而不是数据库告诉它有关事物类型的信息来转换事物,结果是原始 SQL 为您提供了一堆字符串,因为 AR 过于简单,无法为您提供任何其他内容。使用所需的to_ito_f、...调用自己来转换值。

标签: sql ruby-on-rails activerecord


【解决方案1】:

考虑将您的 SQL 语句显示为视图,并创建一条新记录以与视图交互。

这是一个我支持 AR 的项目: https://github.com/michaelkirk/household-account-mgmt/blob/develop/app/models/monthly_report.rb

class CreateMonthlyReports < ActiveRecord::Migration
  def up
    sql = <<-SQL
      create view monthly_reports as
        select date_part('year', created_at) as year, date_part('month', created_at) as month, sum(purchase_amount) as purchases_amount, sum(investment_amount) as investments_amount
          from (
            select * from transactions
              left join
                (select id as purchase_id, amount as purchase_amount from transactions where credit = false)
                as purchases on transactions.id = purchases.purchase_id
              left join
                (select id as investment_id, amount as investment_amount from transactions where credit = true)
                as investments on transactions.id = investments.investment_id)
              as classified_transactions
          group by year, month
          order by year, month
    SQL

    execute(sql)
  end

  def down
    sql = <<-SQL
      drop view monthly_reports
    SQL

    execute(sql)
  end

然后,由于您已将复杂性抽象到数据库视图中,就 AR 的所有意图/目的而言,它就像一个表格,您的模型和控制器看起来完全是普通的。

class MonthlyReport < ActiveRecord::Base
  MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]

  def time_period
    "#{month} #{year}"
  end

  def month
    MONTHS[self[:month] - 1]
  end

  def year
    self[:year].to_i
  end

end

然后你可以做类似的事情

class MonthlyReportsController < ApplicationController
  def index
    @monthly_reports = MonthlyReport.all
  end
end

请注意,由于这是一个 DB 视图,您将无法进行插入操作。我不确定如果你尝试会发生什么。

【讨论】:

    【解决方案2】:

    我想你指的是ORM(对象关系映射)

    首先,connection.execute 将返回一个 Mysql 适配器,您可以在其中迭代行

    你不能像这样将字符串数组(你得到的结果)转换为 ActiveRecord 对象(我猜这就是你所说的类型转换)

    您可以使用find_by_sql

    例如:

    Blog.find_by_sql("select * from blog")
    # => [#<Blog id: 1, name: "first blog", description: nil, record_status_id: 1>]
    

    使用此方法,您可以从原始 SQL 获取 ActiveRecord 对象

    【讨论】:

    • 我实际上有一个非常复杂的查询,涉及来自多个数据的数据,我希望输出是哈希。而且使用 ORM 有点麻烦。我不需要对象。但是,最好进行类型转换,否则我必须手动将输出更改为他们假定的类型。
    • 我还是听不懂你,把结果改成什么?
    • 你能用输入和输出解释你的问题吗?
    • 从 [{"id" => "1", "length" => "120", "content" => "something"},{"id" => "2", "长度" => "200", "内容" => "blahblah"}] 到 [{"id" => 1, "length" => 120, "content" => "something"},{"id" = > 2, "长度" => 200, "内容" => "blahblah"}]
    • 数据库知道 Id 和 length 都是整数,但是查询只返回字符串。我希望 AR 或其他 gem 可以执行原始查询以将其类型转换为假定的类型
    【解决方案3】:

    实际上,您可以将结果转换为 ActiveRecord 对象(参见 find_by_sql 方法 here)或原生 Ruby 类型(参见 this StackOverflow answer)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 2016-10-16
      • 2017-04-16
      相关资源
      最近更新 更多