Ruby on Rails에서 컨트롤러 간 코드 재사용을위한 모범 사례


82

공유하고 싶은 컨트롤러 메서드가 있습니다. Ruby on Rails에서 이것을 수행하는 가장 좋은 방법은 무엇입니까? 컨트롤러가 확장하는 추상 클래스를 만들어야합니까, 아니면 모듈을 만들어 각 컨트롤러에 추가해야합니까? 다음은 공유하려는 컨트롤러 방법입니다.

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

제 생각에는 일반적인 OO 디자인 원칙이 적용됩니다.

  • 코드가 실제로 개체 상태에 액세스 할 필요가없는 유틸리티 집합이라면 별도로 호출 할 모듈에 넣는 것을 고려할 것입니다. 예를 들어 코드가 모든 매핑 유틸리티 인 경우 모듈을 만들고 다음 Maps과 같은 메서드에 액세스합니다 Maps::driving_directions.
  • 코드에 상태가 필요하고 모든 컨트롤러에서 사용되거나 사용할 수있는 경우 코드를 ApplicationController에 넣습니다.
  • 코드가 상태를 필요로하고 밀접하고 논리적으로 관련된 모든 컨트롤러 (즉, 맵에 관한 모든 것)의 하위 집합에서 사용되는 경우 기본 클래스 ( class MapController < ApplicationController) 를 만들고 공유 코드를 여기에 배치합니다.
  • 코드에 상태가 필요하고 밀접하게 관련되지 않은 모든 컨트롤러의 하위 집합에서 사용되는 경우 모듈에 넣고 필요한 컨트롤러에 포함합니다.

귀하의 경우 메서드에는 상태 ( params) 가 필요 하므로 선택은이를 필요로하는 컨트롤러 간의 논리적 관계에 따라 달라집니다. 게다가:

또한:

  • 반복되는 코드에 대해 가능하면 부분을 사용하고 공통 '부분'디렉토리에 배치하거나 특정 경로를 통해 포함하십시오.
  • 가능하면 RESTful 접근 방식을 고수하고 (메서드의 경우) RESTful이 아닌 메서드를 많이 생성하는 경우 자체 컨트롤러로 추출하는 것을 고려하십시오.

33

이 질문이 6 년 전에 제기 된 것을 알고 있습니다. Rails 4에는 이제 즉시 사용 가능한 솔루션 인 Controller Concerns가 있습니다.


16

실제로 모듈은 컨트롤러간에 코드를 공유하는 가장 좋은 방법이라고 생각합니다. 뷰간에 코드를 공유하려는 경우 도우미가 좋습니다. 도우미는 기본적으로 영광스러운 모듈이므로보기 수준 액세스가 필요하지 않은 경우 lib 폴더에 모듈을 배치하는 것이 좋습니다.

모듈을 만든 후에는 include 문을 사용하여 원하는 컨트롤러에 포함시켜야합니다.

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


1

모듈 방식에 동의합니다. lib 디렉토리에 별도의 Ruby 파일을 만들고 모듈을 새 파일에 넣습니다.

가장 확실한 방법은 ApplicationController에 메서드를 추가하는 것이지만 이미 알고있을 것입니다.


1

컨트롤러와 헬퍼간에 코드를 공유하려면 라이브러리에 모듈을 생성해야합니다. 컨트롤러 및 도우미의 메서드에 액세스하기 위해 @template 및 @controller를 사용할 수도 있습니다. 자세한 내용은 http://www.shanison.com/?p=305 를 확인하십시오 .


0

또 다른 가능성 :

공통 코드에 상태가 필요하고 컨트롤러간에 동작을 공유하려는 경우 model또는 lib디렉토리 에있는 일반 오래된 루비 클래스에 넣을 수 있습니다 . 기억 model클래스가 모든 액티브 클래스가 지속에도 불구하고 지속 할 필요가 없습니다. 즉, 일시적인 model클래스 를 가질 수 있습니다.


0

컨트롤러간에 동일한 코드를 공유하는 효과적인 방법 중 하나는 하나의 컨트롤러가 다른 컨트롤러 (코드가있는 곳)에서 상속하도록하는 것입니다. 이 접근 방식을 사용하여 컨트롤러에 정의 된 동일한 메서드를 다른 네임 스페이스 컨트롤러 집합과 공유했습니다.


1
상속을 사용하여 코드를 공유하는 것은 코드 냄새로 간주됩니다. 당신은 그것을 피해야합니다. programmers.stackexchange.com/a/12446을 참조하십시오 . 대신 모듈, 관심사 또는 서비스 객체를 사용하십시오 .
Mio
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.