Как провести рефакторинг большого набора запросов, используемых 3 методами просмотра? - PullRequest
0 голосов
/ 23 декабря 2011

Рельсы 2.3.5

У меня есть отчет, созданный в 3 разных представлениях (основной, предварительный просмотр и версия HTML без простого макета для автоматической электронной почты). В отчете используется около 28 запросов, и для некоторых из них я выполняю некоторую логику перед запросом:

  sunday_this_week = (Time.now.beginning_of_week - 1.days).strftime("%Y-%m-%d")
  sunday_1_week_ago = (Time.now.beginning_of_week - 8.days).strftime("%Y-%m-%d")
  sunday_2_week_ago = (Time.now.beginning_of_week - 15.days).strftime("%Y-%m-%d")
  sunday_3_week_ago = (Time.now.beginning_of_week - 22.days).strftime("%Y-%m-%d")
  sunday_4_week_ago = (Time.now.beginning_of_week - 29.days).strftime("%Y-%m-%d")
  @sunday_dates = [sunday_this_week,sunday_1_week_ago,sunday_2_week_ago,sunday_3_week_ago,sunday_4_week_ago ]

  sql = %Q{
           SELECT * FROM report_notes
           WHERE week_of IN(?)
           ORDER BY week_of ASC, market ASC, measure ASC
          }
  @performance_metric_notes = RptNote.find_by_sql([ sql, @sunday_dates ])

Некоторые из запросов действительно велики, и, поскольку они нужны для 3 представлений, у меня есть те же запросы, перечисленные в трех разных методах контроллера. В контроллере много строк (~ 1400 строк).

Что бы вы сделали для рефакторинга чего-то подобного (возможно ли иметь один метод контроллера со всей логикой и запросами настройки запросов, которые могут вызывать 3 различных метода представления вместо каждого метода представления, имеющего копию)?

Спасибо!

Ответы [ 4 ]

2 голосов
/ 23 декабря 2011

Я бы извлек весь этот код в отдельный класс Report.
Перемещение его на другое действие контроллера все равно привело бы к огромному контроллеру.Кроме того, если для создания отчета достаточно логики, действие контроллера не является подходящим местом для него.Намного лучше, если вы можете поддерживать свои контроллеры в чистоте, просто подготавливая переменные для представлений.

Просто поместите ваш класс в / lib, и в действиях вашего контроллера вы можете вызвать что-то вроде

report = Report.new params
@performance_metric_notes = report.performance_metric_notes
@other_performances = report.other_performances
...

Вы поняли.

1 голос
/ 23 декабря 2011

как сказал @Christoph, если задействовано много логики, реализуйте это как метод в модели;Более того, вы можете реализовать это как scope :

class RptNote < ActiveRecord::Base

  def self.performance_metric_notes( past_weeks = 4 )
    # this will calculate the last sundays for this week + 
    # the nth past weeks, defaults to 4 :
    last_sundays = (0..past_weeks).map do |n|
      (Time.now.beginning_of_week - (1+n*7).days).strftime("%Y-%m-%d")
    end
    # this will return a relation. Using an array in a where clause 
    # renders a SQL IN selector.
    self
      .where( week_of: last_sundays )
      .order( :week_of, :market, :measure )
  end

end

... это позволит вам уточнить результаты, добавив другие предложения:

RptNote.performance_metric_notes.where( measure: something )

см. Railscasts # 215 для получения дополнительной информации об отношениях и запросах в рельсах 3

edit: wooops, мой плохой, только что увидел, что ваш вопрос был на рельсах 2. Логика остаетсято же самое, за исключением запроса.

Существует еще кое-что: если ваши действия контроллера используют это часто, вы можете установить before_filter на контроллере для автоматической выборки записей:

before_filter :fetch_notes

def fetch_notes
  @notes = RptNote.performance_metric_notes
end
1 голос
/ 23 декабря 2011

Почему бы не включить его в модель отчета как метод?

@performance_metric_notes = RptNote.get_my_custom_report
0 голосов
/ 23 декабря 2011

В вашей модели:

scope :by_dates, lambda { |dates|
  where("week_of IN (#{sunday_dates.join(,)})").
  order_by("week_of ASC, market ASC, measure ASC")
}

def self.sunday_dates
  sunday_this_week = (Time.now.beginning_of_week - 1.days).strftime("%Y-%m-%d")
  sunday_1_week_ago = (Time.now.beginning_of_week - 8.days).strftime("%Y-%m-%d")
  sunday_2_week_ago = (Time.now.beginning_of_week - 15.days).strftime("%Y-%m-%d")
  sunday_3_week_ago = (Time.now.beginning_of_week - 22.days).strftime("%Y-%m-%d")
  sunday_4_week_ago = (Time.now.beginning_of_week - 29.days).strftime("%Y-%m-%d")
  [sunday_this_week,sunday_1_week_ago,sunday_2_week_ago,sunday_3_week_ago,sunday_4_week_ago]
end

А в вашем контроллере:

RptNote.by_dates(RptNote.sunday_dates)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...