Rails6.0 active decorator 설정방법

Posted by negabaro kim on Friday, May 22, 2020 Tags: rails   3 minute read

active decorator란

drapper보다 심플한 decorator decorate한 로직들은 오직 뷰에서만 보세요~ 라는 설정을 강제한게 특징이다.

decorate를 일일이 정의할 필요가 없다.

설정방법

install

gem 'active_decorator'
bundle install

generator

bundle exec rails g decorator user

추가해줄 모델을 지정해서 실행

decorator 설정

#app/decorators/user_decorator.rb
module UserDecorator
  def full_name
    last_name + first_name
  end
end

rails g decorator user커맨드로 생성된app/decorators/user_decorator.rb파일에 메소드를 추가해준다.

controller 설정

특별한 설정이 필요없다 인스턴스를 view로 넘겨주기만 하면된다

def edit
  @user = User.find(param[:id])
end

view 설정

= @user.full_name

app/decorators/user_decorator.rb에 추가해준 메소드를 그대로 써주기만 하면됨

devise사용시 문제점

devise와 같이 controller에서 인스턴스를 넘겨주지 않으면 메소드가 찾을 수 없다는 에러가 나온다 해결방법은 2가지

첫번째 방법. 컨트롤러에서 current_user를 @user에 넘겨준다

def edit
  @user = current_user
end

개인적으로는 컨트롤러를 보고 어떤 인스턴스를 뷰에 넘기는지 확실히 알 수 있기에 이방법을 선호 그러나 current_user같이 거의 모든 서비스에서 사용하는 경우 이방법이 오히려 일일히 컨트롤러에 선언해야 하므로 귀찮을 수 있다.

이렇게만 해주면 current_user.full_name이 동작함 @user.full_name만 동작할 줄 알았는데..이유는 잘모르겠다

두번째 방법.

application_controller에서 재정의

#app/controllers/application_controller.rb
def current_user
  ActiveDecorator::Decorator.instance.decorate(super) if super.present?
  super
end

해당 메소드를 오버라이드에서 직접 decorate하는 방법이다. 컨트롤러에서 매번 인스턴스 넘겨주는게 귀찮으므로 2번째 방법을 선택

메모1. (view이외에서 사용하는법)

기본 view에서만 사용가능하지만 뷰이외에서 사용하게 하는방법은 존재한다

사용예

user = ActiveDecorator::Decorator.instance.decorate(User.find(1))
user.full_name #decorate사용!!

메모2.

레이어를 나눌 수 있다면 모듈로 따로 정의해서 decorator fat되지 않게 하자

module UserDecorator
  # 공통처리하는 부분
  # PeopleDecorator모듈을 임포트
  include PeopleDecorator
end

메모3.

decorator의 테스트파일 작성방법 decorate상태의 클래스 작성을 위해 모델명.extend Decorator클래스명로 정의

# spec/decorators/user_decorator_spec.rb
require "rails_helper"

describe UserDecorator do
 # 이 부분이 포인트
  let(:user) { create(:user).extend UserDecorator }
  subject { user }
  it { should be_a User }

  describe "full_name" do
    subject { user.full_name }
    it { is_expected.to eq "#{user.first_name} #{user.last_name}" }
  end

  # link_to등Viewhelper을 사용한 테스트를 사용시 ActionView도 extend
  let(:user_w_viewhelper) do 
    create(:user).extend(UserDecorator).extend(ActionView::Helpers)
  end  
end

reference:

https://kic-yuuki.hatenablog.com/entry/2019/07/07/164550
https://qiita.com/yatmsu/items/2f05517d36267780aec2
https://github.com/amatsuda/active_decorator