Rails Mixin: ActiveRecord::Concern

HyoKwangRyu·2021년 7월 24일
1

Ruby on Rails

목록 보기
6/6

믹스인

어떤 모듈을 include 하거나 extend하는 것을 믹스인 이라고 했다. 믹스인은 다른 클래스에 추가하는 코드의 세트 이고, 모듈은 메서드와 상수의 모음이다.

dry한 코드를 만들때 보통 공통 로직을 모듈로 빼고, 필요한 클래스에서 그 모듈을 포함시켜 사용한다.

레일즈에서

Include + Extend?

모듈로 믹스인을 사용하다 보면 include와 extend 를 동시에 해야할 때가 있다.

간단한 예로 클래스 메소드와 인스턴스 메소드를 한 모듈에서 다룰 때.

module SomeThing
  def included
    "iii"
  end

  def extended
    "eee"
  end
end

class SomeClass
  include SomeThing
  extend SomeThing
end

위 코드는 문제 없이 실행 되지만, 모듈의 두 메소드가 클래스 메서드와 인스턴스 메소드로 동시에 등록? 되어버리기 때문에 원하는 바는 아니다.

이것은 모듈을 믹스인할때 호출되는 훅들을 이용하면 해결 가능한데, 이 방식을 사용하기 쉽게한게 ActiveRecord::Concern 이다

ActiveRecord::Concern

모듈에서 Concern을 extend 하면

  • included
  • class_methods

두 블록을 사용할 수 있다.

class_methods

이 블록 안에 있는 메소드는 모듈을 include한 클래스의 클래스 메소드로 extend 된다.

included

class_eval을 통해 모듈을 include한 클래스에 훅이나 association을 선언할 수 있다.

class_eval

해당 객체의 클래스에 함수를 추가 할 수 있다.

def add_scope_to(some_class)
  some_class.class_eval do
    scope :in_live, -> { where(live: true) }

    def my_method
      "my_method"
    end
  end
end

add_scope_to MyClass
Myclass.in_live
Myclass.new.my_method

정리해보자면,

module Scopable
  extend ActiveSupport::Concern
  
  included do
    scope :in_live, -> { where(live: true) }
  end
  
  class_methods do
    def some_class_method
      'Hello'
    end
  end

  def not_live?
    !live
  end
end

class Show < ApplicationRecord
  include Scopable
end

같은 식으로 모듈을 구성할 수 있고, 필요에 따라 각 클래스에서 include 해서 사용할 수 있다.

여러 클래스에서 공통으로 사용 할 수 있는 scope 등을 선언할 수도 있고,

폴리몰픽 클래스와 association 이 있을 수 있는 클래스들의 로직을 묶을 수 도 있겠다.

추가로 Concern 을 extend 모듈을 다른 모듈에서 include할때 의존성 문제도 없다.

결론

계속해서 믹스인을 이야기하고 있는데, 점점 강해지는 생각은

  • 상속보다 믹스인을 사용하여 dry한 코드를 만드는게 좋을 것 같다.
  • 상속은 모델의 데이터에 집중해야 할 것 같다.
  • 믹스인을 쓸 곳이 생각보다 많고, 젬은 이렇게 만들 것 같다?
  • 레일즈 혹은 루비코드는 생략이 많은 것 같다.. 그러다 보니 깊이 들어갈 수록 알아야 할게 많다.(다른 언어도 마찬가지 겠지만)

이번 포스팅은 깊이 생각하지 못하고 대충 썼습니다.

profile
Backend Developer

0개의 댓글