Найкращі практики повторного використання коду між контролерами в Ruby on Rails


82

У мене є кілька методів контролера, якими я хотів би поділитися. Яка найкраща практика робити це в рубіні на рейках? Чи слід створювати абстрактний клас, який розширюють мої контролери, чи створювати модуль та додавати його до кожного контролера? Нижче наведені методи контролера, якими я хочу поділитися:

def driving_directions
  @address_to = params[:address_to]
  @address_from = params[:address_from]
  @map_center = params[:map_center_start]

  # if we were not given a center point to start our map on
  # let's create one.
  if !@map_center && @address_to
    @map_center = GeoKit::Geocoders::MultiGeocoder.geocode(@address_to).ll
  elsif !@map_center && @address_from
    @map_center = GeoKit::Geocoders::MultiGeocoder.geocode(@address_from).ll
  end
end

def printer_friendly
  starting_point = params[:starting_point].split(',').collect{|e|e.to_f}
  ne = params[:ne].split(',').collect{|e|e.to_f}
  sw = params[:sw].split(',').collect{|e|e.to_f}
  size = params[:size].split(',').collect{|e|e.to_f}
  address = params[:address]

  @markers = retrieve_points(ne,sw,size,false)
  @map = initialize_map([[sw[0],sw[1]],[ne[0],ne[1]]],[starting_point[0],starting_point[1]],false,@markers,true)
  @address_string = address
end

1
Чи існує особлива причина, через яку в цьому випадку не використовується application.rb?
PJ.

4
Тільки те, що деякі контролери будуть використовувати код, але не всі.
Kyle Boon

Відповіді:


113

На мій погляд, застосовуються звичайні принципи проектування ОО:

  • Якщо код насправді являє собою набір утиліт, які не потребують доступу до стану об'єкта, я б розглянув можливість розміщення його в модулі, який буде викликатися окремо. Наприклад, якщо код всіх утиліти картографії, створити модуль Maps, і отримати доступ до методів , як: Maps::driving_directions.
  • Якщо код потребує стану і використовується або міг би бути використаний у кожному контролері, помістіть код у ApplicationController.
  • Якщо код потребує стану і використовується в підмножині всіх контролерів, які тісно і логічно пов'язані (тобто все про карти), тоді створіть базовий клас ( class MapController < ApplicationController) і помістіть спільний код туди.
  • Якщо код потребує стану і використовується в підмножині всіх контролерів, які не дуже тісно пов'язані, помістіть його в модуль і включіть до необхідних контролерів.

У вашому випадку методам потрібен state ( params), тому вибір залежить від логічного взаємозв'язку між контролерами, які його потребують. В додаток:

Також:

  • Використовуйте частки, коли це можливо, для повторного коду, або розмістіть їх у загальному каталозі "частинок", або включіть за певним шляхом.
  • Дотримуйтесь підходу RESTful, коли це можливо (для методів), і якщо ви виявляєте, що створюєте багато методів, які не є RESTful, розгляньте можливість вилучити їх до власного контролера.

33

Я знаю, що це питання було задано 6 років тому. Просто хочу зазначити, що в Rails 4 тепер є проблеми з контролером, які є більш нестандартним рішенням.


16

Я насправді вважаю, що модуль є найкращим способом обміну кодом між контролерами. Помічники хороші, якщо ви хочете поділитися кодом серед подань. Помічники - це в основному прославлені модулі, тому, якщо вам не потрібен доступ до рівня перегляду, я пропоную помістити модуль у вашу папку lib.

Після створення модуля вам доведеться використовувати оператор include, щоб включити його до потрібних контролерів.

http://www.rubyist.net/~slagell/ruby/modules.html


1

Я згоден з модульним підходом. Створіть окремий файл Ruby у своєму каталозі lib та помістіть модуль у новий файл.

Найбільш очевидним способом було б додати методи до вашого ApplicationController, але я впевнений, ви це вже знаєте.


1

якщо ви хочете поділитися кодами між контролером і помічниками, спробуйте створити модуль у бібліотеці. Ви також можете використовувати @template та @controller для доступу до методу в контролері та помічнику. Перевірте це, щоб отримати докладнішу інформацію http://www.shanison.com/?p=305


0

Ще одна можливість:

Якщо загальний коду потрібно стан , і ви хочете поділитися поведінкою серед контролерів, ви можете помістити його в простому старому класі рубіна в будь-якій вашій modelабо libдиректорії. Пам'ятайте, що modelкласи не повинні бути постійними, хоча всі класи ActiveRecord є постійними. Іншими словами, прийнятно мати перехідні modelкласи.


0

Я виявив, що одним із ефективних способів спільного використання однакового коду між контролерами є отримання одного контролера у спадок від іншого (там, де живе код). Я використав цей підхід, щоб поділитися однаковими методами, визначеними в моїх контролерах, з іншим набором контролерів з простором імен.


1
Використання спадщини для спільного використання коду розглядається як запах коду. Вам слід уникати цього. Див. Programmers.stackexchange.com/a/12446 . Замість цього використовуйте модулі, проблеми або навіть об’єкт послуг .
Міо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.