Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Rails 디자인 패턴:프리젠터 및 서비스 객체

디자인 패턴이 필요한 이유는 무엇입니까?

문제는 Rails 아키텍처인 Model-View-Controller가 코드를 넣을 기본 구조를 제공한다는 것입니다.

하지만 이것으로 충분하지 않습니다.

정보를 제공하는 것이 목표일 때 보기가 커지고 논리적으로 가득 차게 됩니다.

컨트롤러에는 컨트롤러가 필수적인 작업을 수행하는 데 필요한 것 이상의 세부 정보가 들어 있습니다.

해결책은 무엇인가요?

우리는 이러한 문제를 해결하기 위해 디자인 패턴의 형태로 두 가지 솔루션을 만들었습니다.

  • 발표자 패턴
  • 서비스 객체 패턴

모든 사람이 정확히 구현하는 방법에 동의하는 것은 아니지만 나에게 맞는 버전을 알려 드리겠습니다.

이 패턴을 살펴봅시다!

Rails에서 발표자를 사용하는 방법

보기는 HTML, CSS 및 ERB(Embedded Ruby)를 의미하는 프레젠테이션용입니다.

ActiveRecord가 없어야 합니다. 조회수.

그리고 대부분의 논리는 생략되어야 합니다 가능한 한 깨끗하고 작업하기 쉬운 보기를 원하신다면.

<블록 인용>

"논리"란 if 문 및 삼항 연산자로 결정을 내리는 것을 의미합니다.

이제 질문은...

어떻게?

보기에서 논리를 처리하는 첫 번째 도구는 도우미를 사용하는 것입니다.

여러 보기에서 사용하는 전역 서식 지정 방법이 있을 때마다 도우미가 유용합니다.

예를 들어 :

Markdown 렌더링, 특정 형식의 날짜 표시, 텍스트에서 특정 단어 제거 등

좋아요 :

module DateHelper
  def date_as_month_and_year(date)
    date.strftime("%B %Y")
  end
end

app/helpers 아래에 이 코드를 저장할 수 있습니다. 폴더 및 date_helper.rb 파일.

:

항상 인수를 통해 도우미 메서드에 입력을 전달하고 인스턴스 변수에 의존하지 마십시오.

이렇게 하면 많은 수고를 덜 수 있습니다.

도우미 방법에는 제한이 있습니다. , 특히 보기에서 필요한 모든 서식에 대해 사용하는 경우

그들은 조직을 구축하고 결핍하는 경향이 있습니다.

해결책이 나옵니다!

복잡한 조건부 및 서식 지정 방법을 Presenter 개체로 바꾸기

다음과 같은 보기가 있다고 가정해 보겠습니다.

<p>
  Post title: <%= post.title.gsub("forbidden word", "") %>

  <%= link_to "Read post", post, class: "w-75 p-3 text-#{post.draft? ? "orange" : "green"} border-#{post.draft? ? "orange" : "green"}" %>
</p>

꽤 짧은 모습이죠?

그러나 이러한 삼항 연산자와 중복된 코드로 인해 매우 복잡하게 느껴집니다.

좋지 않습니다!

이를 해결하기 위해 발표자 클래스를 만들어 보겠습니다.

방법은 다음과 같습니다. :

class PostPresenter
  def initialize(post)
    @post = post
  end

  def title_without_forbidden_words
    @post.title.gsub("forbidden word", "")
  end

  def css_color
    @post.draft? ? "orange" : "green"
  end
end

app/presenters/post_presenter.rb 아래에 저장합니다. , presenters 생성 폴더가 없는 경우.

이제 보기를 변경할 수 있습니다.

좋아요 :

<% presenter = PostPresenter.new(post) %>

<p>
  Post title: <%= presenter.title_without_forbidden_words %>

  <%= link_to "Read post", post, class: "w-75 p-3 text-#{presenter.css_color} border-#{presenter.css_color}" %>
</p>

알겠습니다!

  • 보기에서 모든 논리를 제거했습니다.
  • 형식 지정 및 의사 결정 작업에 의미 있는 이름을 추가했습니다.
  • 코드를 복제하지 않고도 이 클래스를 다른 보기에서 재사용할 수 있습니다.

이것이 Rails에서 프리젠터를 사용하는 방법입니다 🙂

서비스 개체 사용 방법

컨트롤러는 수행할 작업만 다른 사람에게 알려야 하며, 트윗을 보내거나 고객에게 요금을 청구하거나 PDF 파일을 생성하는 방법에 대한 지식이 없어야 합니다.

이러한 작업은 위임되어야 합니다. 서비스 개체에.

내가 정의한 서비스 개체는 작업을 완료하기 위한 논리를 캡슐화하는 Ruby 모듈입니다.

:

module TwitterService
  def self.send_welcome_message(twitter_handle)
    client.update("@#{twitter_handle} welcome to 'Oranges & Apples', we hope you enjoy our juicy fruit!")
  end

  def self.client
    @client ||= Twitter::REST::Client.new do |config|
      config.consumer_key        = "..."
      config.consumer_secret     = "..."
      config.access_token        = "..."
      config.access_token_secret = "..."
    end
  end
end

규칙은 이것을 app/services 아래에 저장하는 것입니다. 폴더 및 twitter_service.rb와 같은 파일 .

이걸 어떻게 사용합니까?

Rails는 app/에서 모든 것을 자동 로드하기 때문에 , 이 코드는 컨트롤러에서 사용할 수 있습니다.

:

class UsersController
  def create
    # ...
    TwitterService.send_welcome_message(user.twitter_handle)
  end
end

이것이 작동하는 서비스 객체 패턴입니다.

요약

현명하게 사용할 때 프로젝트의 코드 품질을 향상시키는 데 도움이 되는 두 가지 유용한 Rails 패턴을 배웠습니다!

이제 적용할 차례입니다 🙂

읽어주셔서 감사합니다.