Rails Model, View, Controller 및 Helper : 어디로 가는가?


155

Ruby on Rails Development (또는 일반적으로 MVC)에서 로직을 어디에 두어야하는지에 대한 빠른 규칙을 따라야합니다.

긍정 답변 해주세요 - 함께 음주 여기를 넣어 ,보다는 음주 것을 거기에 넣지 .

답변:


173

MVC

컨트롤러 : 사용자가 원하는 것을 해결하고, 무엇을 줄 것인지, 로그인했는지, 특정 데이터를 볼 수 있는지 등을 결정하는 것과 관련된 코드를 여기에 넣으십시오. 결국 컨트롤러는 요청을 봅니다. 표시 할 데이터 (모델)와 렌더링 할 뷰를 계산합니다. 코드가 컨트롤러에 들어가야하는지 확실하지 않다면 아마 그렇지 않을 것입니다. 컨트롤러를 마른 상태로 유지하십시오 .

보기 :보기에는 데이터 (모델)를 표시하기위한 최소 코드 만 포함되어야하며, 많은 처리 또는 계산을 수행해서는 안되며, 모델에서 계산하거나 요약 한 데이터를 표시하거나 컨트롤러에서 생성 한 데이터를 표시해야합니다. 뷰가 실제로 모델 또는 컨트롤러로 수행 할 수없는 처리를 수행 해야하는 경우 코드를 도우미에 넣으십시오. 뷰에 많은 루비 코드가있어 페이지 마크 업을 읽기가 어렵습니다.

모델 : 모델은 데이터와 관련된 모든 코드 (사이트를 구성하는 엔티티 (예 : 사용자, 게시물, 계정, 친구 등)) 가있는 곳이어야합니다 . 코드가 엔티티와 관련된 데이터를 저장, 업데이트 또는 요약해야하는 경우 여기에 입력하십시오. 뷰와 컨트롤러에서 재사용 할 수 있습니다.


2
사람들은 뚱뚱한 모델에서 벗어나기 시작했습니다. 내 모델을 데이터 구조로 생각하고 싶습니다. 그런 다음 동작을 구현하는 일부 Ruby 객체를 작성하여 모델로 초기화합니다 (문자열 및 배열을 Rails 외부의 객체에서 데이터로 처리하는 것과 같은 방식으로 모델을 데이터로 처리 함). 다음 은이 기술의 예를 보여주는 좋은 비디오입니다.
Joshua Cheek

@AdamDonahue 나는 지방이 좋은 것으로 보일 수 있는지 잘 모르겠습니다. 책임의 톤은 서비스에 속하는 것이 좋습니다.
fatuhoku

35

pauliephonic의 답변에 추가하려면 :

도우미 :보기를보다 쉽게 ​​만들 수있는 기능입니다. 예를 들어, 가격을 표시하기 위해 항상 위젯 목록을 반복하는 경우 실제 표시의 일부와 함께 도우미에 배치하십시오. 또는보기를 어지럽히고 싶지 않은 RJS 조각이 있으면 도우미에 넣으십시오.


실제로 Helper에 sign_in 메소드도 넣지 않습니까? RoR Tutorial에서 제안한대로 >>> ruby.railstutorial.org/book/…
Ivan Wang

14

MVC 패턴은 실제로 UI에만 관련이 있습니다. 컨트롤러는 뷰를 제어하지만 로직은 제어하지 않으므로 복잡한 비즈니스 로직을 컨트롤러에 넣지 마십시오. Controller는 적절한보기를 선택하고 도메인 모델 (모델) 또는 비즈니스 계층에보다 복잡한 항목을 위임하는 데 관심을 가져야합니다.

Domain Driven Design에는 서비스 개념이 있으며, 이는 여러 종류의 객체를 오케스트레이션해야하는 로직이며, 일반적으로 Model 클래스에 속하지 않는 로직을 의미합니다.

나는 일반적으로 서비스 계층을 내 응용 프로그램의 API로 생각합니다. 내 서비스 계층은 일반적으로 내가 만드는 응용 프로그램의 요구 사항과 매우 밀접하게 매핑되므로 서비스 계층은 내 앱의 하위 수준에서 발견되는 더 복잡한 상호 작용을 단순화하는 역할을합니다. 즉, 서비스 계층을 우회하는 동일한 목표를 달성 할 수 있습니다 하지만 작동하려면 더 많은 레버를 당겨야합니다.

나는 여기서 Rails에 대해 이야기하지 않고 특정 문제를 해결하는 일반적인 건축 스타일에 대해 이야기하고 있습니다.


이것은 훌륭한 답변입니다 :)
Carlos Martinez



7

인증 / 액세스 제어와 관련된 것을 컨트롤러에 넣습니다.

모델은 모든 데이터에 관한 것입니다. 검증, 관계, CRUD, 비즈니스 로직

조회수는 데이터를 표시하는 것입니다. 표시 및 입력 만.

컨트롤러는 모델에서 뷰로 이동하는 데이터와 뷰에서 모델로 이동하는 데이터를 제어하는 ​​것입니다. 컨트롤러는 모델 없이도 존재할 수 있습니다.

나는 컨트롤러를 경비원 / 수신자라고 생각합니다. 고객 (요청)을 고객에게 요청하는 적절한 카운터로 안내합니다 (보기). 그러면 텔러 (보기)는 관리자 (모델)로부터 답변을 얻습니다. 그런 다음 요청은 경비원 / 수신자 (컨트롤러)로 돌아가서 다른 텔러 (보기)에게 갈 때까지 기다립니다. 다른 텔러 (보기)는 관리자 (모델)가 다른 텔러 (보기) 질문에 대한 답변을 알려줍니다. .

마찬가지로 텔러 (보기)에게 무언가를 말하고 싶다면 두 번째 텔러가 관리자가 귀하의 정보를 수락했는지 여부를 알려주는 것을 제외하고는 거의 동일한 일이 발생합니다. 관리자에게 해당 정보를 알려줄 권한이 없기 때문에 경비원 / 수신자 (컨트롤러)가 하이킹을하도록 지시했을 수도 있습니다.

비유적이고 비현실적인 세상에서 은유를 확장하기 위해, 텔러 (조회)는 예쁘지 만 머리가 비어 있고 종종 당신이 말하는 것을 믿습니다. 가지 말고 관리자는 정말 추악하고 의미가 있지만 모든 것을 알고 무엇이 진실인지 아닌지를 말할 수 있습니다.


4

적절하게 분리하는 데 도움이되는 한 가지는 "컨트롤러에서 로컬 변수를 전달하여"반 패턴을 피하는 것입니다. 이 대신에 :

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  def show
    @foo = Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= @foo.bar %>
...

도우미 메소드로 사용 가능한 게터로 이동하십시오.

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  helper_method :foo

  def show
  end

  protected

  def foo
    @foo ||= Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= foo.bar %>
...

이렇게하면 "@foo"에 넣은 내용과 사용 방법을보다 쉽게 ​​수정할 수 있습니다. 컨트롤러와 뷰를 더 복잡하게 만들지 않고 분리합니다.


음 ... 유크. 이를 수행 할시기에 대한 몇 가지 이유 / 시나리오를 추가 할 수 있습니까? 이로 인해 KISS와 YAGNI가
깨지고

2
1) Rails는 컨트롤러의 인스턴스 변수를 뷰 인스턴스에 복사하기 위해 많은 마술을 수행합니다. 2) 제안 된 구현은 foo에 액세스 할 때만 foo를로드하므로 일부 작업을 절약 할 수 있습니다. 중요한 대답은 실제로 1)입니다.
webmat

11
한숨 이 끔찍하다. Rails 인스턴스 변수 공유는 안티 패턴이 아닌 기능입니다. 그것은 실제 문제를 거의 일으키지 않는 유비쿼터스의 저정도 오버 헤드 구문 설탕이다. 마음에 들지 않으면 괜찮지 만 바로크 비표준 구조로 코딩하면 상황이 무한히 악화됩니다. 이 경우 효과적으로 foo를 전역 (어쨌든 컨트롤러 당) 변수로 만듭니다. 범위를 극적으로 증가 시켜서 변수 범위의 남용을 감지하려는 시도는 매우 역설적입니다.
gtd

1
나는 그것을 구입하지 않습니다, dasil003. 의 범위 foo및이 @foo동일 - 이들은 모두 <ControllerClass 요청> 쌍 범위가된다. 또한 getter 버전을 사용 Foo하여 뷰가 액세스하는 방식을 변경하지 않고 해당 객체를 찾거나 저장 / 캐시하는 방법을 변경할 수 있습니다.
James A. Rosen

1
반 패턴 "패스 인스턴스 변수"를 의미한다고 생각합니다. 인스턴스 var는 깊게 중첩 된 부분에서도 전체 렌더링에 대한 상태를 누설합니다. 귀하의 솔루션은 또한 상태를 누출하지만 재 할당을 허용하지 않기 때문에 인스턴스 var보다 약간 낫습니다. 메소드를 호출하는 것과 같이 로컬을 전달하는 것이 실제로 가장 좋습니다. 지역은 부분적으로 볼 수 없습니다. 이 답변을 참조하십시오 .
켈빈

2

글쎄, 그것은 논리가 처리해야 할 것에 달려 있습니다.

종종 더 많은 것을 모델로 밀어 넣어 컨트롤러를 작게 유지하는 것이 좋습니다. 이를 통해 모델이 나타내는 데이터에 액세스해야하는 모든 위치에서이 논리를 쉽게 사용할 수 있습니다. 뷰에는 로직이 거의 없어야합니다. 따라서 실제로는 일반적으로 반복하지 않도록 노력해야합니다.

또한 구글의 간단한 정보는 어디로 가는지 몇 가지 더 구체적인 예를 보여줍니다.

모델 : 검증 요구 사항, 데이터 관계, 메소드 작성, 메소드 업데이트, 메소드 제거, 메소드 찾기 (이 메소드의 일반 버전뿐만 아니라 빨간색을 가진 사람을 찾는 것과 같이 많은 일을하는 경우) 성을 기준으로 한 머리를 찾은 다음 find_redH_by_name ( "smith") 또는 이와 유사한 이름을 호출하기 만하면 해당 논리를 추출해야합니다.

보기 : 이것은 데이터 처리가 아니라 데이터 형식에 관한 것이어야합니다.

컨트롤러 : 데이터 처리가 진행됩니다. 인터넷에서 : "컨트롤러의 목적은 사용자가 요청한 조치에 응답하고, 사용자가 설정 한 모든 매개 변수를 취하고, 데이터를 처리하고, 모델과 상호 작용 한 다음, 요청 된 데이터를 최종 양식으로 전달하는 것입니다. 전망."

희망이 도움이됩니다.


0

간단히 말해서 일반적으로 모델 에는 테이블과 관련된 모든 코드, 단순 또는 복잡한 관계 (여러 테이블을 포함하는 SQL 쿼리로 생각), 비즈니스 논리를 사용하여 결과에 도달하기위한 데이터 / 변수 조작 .

컨트롤러 에는 요청 된 작업에 대한 관련 모델에 대한 코드 / 포인터가 있습니다.

는 사용자 입력 / 상호 작용을 승인하고 결과 응답을 표시합니다.

이것들로부터 큰 편차가 생기면 그 부분에 원치 않는 부담이 가해져 전체적인 어플리케이션 성능에 영향을 줄 수 있습니다.


-1

테스팅, 테스팅 ... 모델에 최대한 많은 로직을 넣으면 제대로 테스트 할 수 있습니다. 단위 테스트는 모델 테스트를 통해 데이터와 데이터의 구성 방식을 테스트하고 기능 테스트는 컨트롤러를 테스트하여 라우팅되거나 제어되는 방식을 테스트하므로 데이터가없는 한 데이터 무결성을 테스트 할 수 없습니다. 모델.

제이

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.