2014-03-10 3 views
8

Я создал функцию Postgres, которую я использую, чтобы выполнить сложный запрос, который объединяет многие таблицы, которые все должны быть отфильтрованы динамическим полем даты.Использовать функцию Postgres как ActiveRecord Model

Функция работает отлично и позволяет выполнить такой запрос, как "SELECT * FROM trail_for_date('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::Base 
    self.table_name = 'sum_n_product_with_tab(:dynamic_input)' 
end 
+0

Это исходный маршрут, по которому я пошел, но в моем запросе мне нужно присоединиться к пяти таблицам, которые все фильтруют на одну дату и выполняют вычисления на основе этой даты ... Поэтому мне нужно иметь возможность передавать какие-то переменную или использовать функцию для выполнения этого (я думаю). –

+0

Я полагаю, что мог бы, хотя это был вопрос с более чем 100 строк, и мне пришлось бы синхронизировать мой запрос с функцией базы данных, которую реализовали ребята из базы данных. –

+0

Или вы можете использовать isl 'Model.select (Arel :: Nodes :: NamedFunction.new ('sum_n_product_with_tab', 6)). To_sql' –

ответ

1

Создайте представление, содержащее данные, необходимые, а затем вы можете легко создать модель 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) 

Вы можете найти более подробную информацию в книге Enterprise Rails. Сейчас он немного устарел, но принципы звучат.

http://enterpriserails.chak.org/full-text/chapter-11-view-backed-models

+0

Представления не делают этого для меня, потому что функции требуется аргумент для подзапроса внутри функция. Если я отказываюсь от подзапроса и просто фильтрую после выполнения функции (как предлагается здесь), тогда функция будет слишком медленной, так как ей придется вычислять для всех строк таблицы. –

0

создать фиктивную таблицу с теми же столбцами, как ваш выход функции:

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 

Reference это в контроллере и заполнить его с функции:

def visualizations 
    @compliancebyyear = Visualization::ComplianceByYear.new() 
    @compliancefunds = @compliancebyyear.compliance_by_year(current_group.id) 
end 
Смежные вопросы