Ruby on rails 使用Postgres函数作为ActiveRecord模型

Ruby on rails 使用Postgres函数作为ActiveRecord模型,ruby-on-rails,ruby-on-rails-3,postgresql,Ruby On Rails,Ruby On Rails 3,Postgresql,我已经创建了一个Postgres函数,我正在使用它来执行一个复杂的查询,它连接了许多表,所有这些表都必须通过一个动态日期字段进行过滤 该函数工作正常,允许my执行类似于“从trail\u中为日期('2014-01-01')选择*的查询”,并返回一个表 Postgres函数文档中的简化示例: CREATE FUNCTION sum_n_product_with_tab (x int) RETURNS TABLE(sum int, product int) AS $$ SELECT $1 +

我已经创建了一个Postgres函数,我正在使用它来执行一个复杂的查询,它连接了许多表,所有这些表都必须通过一个动态日期字段进行过滤

该函数工作正常,允许my执行类似于“从trail\u中为日期('2014-01-01')选择*的查询”,并返回一个表

Postgres函数文档中的简化示例:

CREATE FUNCTION sum_n_product_with_tab (x int)
RETURNS TABLE(sum int, product int) AS $$
    SELECT $1 + tab.y, $1 * tab.y FROM tab;
$$ LANGUAGE SQL;
在函数的参数是动态的情况下,如何将此返回表用作Rails/Ruby模型

类似于以下内容(显然不起作用):

class SimplifiedExample
创建一个包含所需数据的视图,然后您可以轻松创建一个ActiveRecord模型来访问它

您没有提供数据的具体细节,但作为一个简单的例子,在Postgres中创建视图以收集数据

  create or replace view data_trails as
    select t.*, td.trail_date from trails t
    join trail_dates td on (td.trail_id = t.id)
然后创建您的模型

  class DataTrail < ActiveRecord::Base
    scope :on_date, -> (date) { where(trail_date: date) }
  end

  DataTrail.on_date(Date.today)
classdatatrail(日期){其中(审判日期:日期)}
结束
DataTrail.on_日期(日期:今天)
您可以在EnterpriseRails手册中找到更多信息。现在有点过时了,但原则是合理的


创建一个与函数输出列相同的虚拟表:

CREATE TABLE report.compliance_year (
year TIMESTAMP,
compliance NUMERIC(20,2),
fund_id INT);
创建您的模型:

class Visualization::ComplianceByYear < ActiveRecord::Base
    self.table_name = 'report.compliance_year'
    def compliance_by_year(fund_id)
        Visualization::ComplianceByYear.find_by_sql(["
            SELECT year, compliance, fund_id
              FROM report.usp_compliance_year(ARRAY[?])", fund_id])
    end
end 

这是我最初的路线,但在我的查询中,我必须连接大约五个表,它们都在一个日期进行过滤,并根据该日期进行计算。。。因此,我需要能够传入某种变量或使用函数来实现这一点(我认为)。我想我可以,尽管这是一个100多行的查询,而且我必须使我的查询与数据库人员实现的数据库函数保持同步。或者你可以使用arel
Model.select(arel::Nodes::NamedFunction.new('sum_n_product_with_tab',6)).to_sql
视图不为我执行此操作,因为函数需要函数内子查询的参数。如果我放弃子查询,只在函数执行后进行过滤(如这里所建议的),那么函数将太慢,因为它必须计算表中的所有行。
class Visualization::ComplianceByYear < ActiveRecord::Base
    self.table_name = 'report.compliance_year'
    def compliance_by_year(fund_id)
        Visualization::ComplianceByYear.find_by_sql(["
            SELECT year, compliance, fund_id
              FROM report.usp_compliance_year(ARRAY[?])", fund_id])
    end
end 
def visualizations
  @compliancebyyear = Visualization::ComplianceByYear.new()
  @compliancefunds = @compliancebyyear.compliance_by_year(current_group.id)
end