ActiveRecord 모델에 attr_accessor 사용하기

HyoKwangRyu·2020년 10월 28일
1

상황

class Advertise < ActiveRecord::Base
  # Associations
  # ------------
  has_many :advertise_targets

  # Scopes
  # ------
	...

  # Macros
  # ------
	...

  # Methods
  # -------
	...
end

class AdvertiseTarget < ActiveRecord::Base
  # Associations
  # ------------
  belongs_to :advertise
	...
end

AdvertiseAdvertiseTarget 은 서로 1:N 의 관계.

API 호출 마다 Advertise 의 여러 AdvertiseTarget 들 중 매칭된 타겟이 어떤 것일지 계속 변하는데, 그 당시의 타겟 정보를 응답에 포함시켜야 한다.

필요한 것

  1. DB에 저장되지 않는 일시적인 상태를 응답에 포함해야 함.
  2. 그 상태는 각 요청 마다 무작위로 변할 수 있음.
  3. 몇가지 속성을 응답에 포함시켜야 함.

이전 까지의 방식

  1. hash 를 새롭게 구성한다.
  2. 시리얼라이져에 옵션을 통해 속성을 추가한다.

이전 방식의 문제

  1. 스펙?이 없으니 hash 구성을 쉽게 변경할 수 있다. 어떤 값이 있어야 할지 모른다. 같은 리소스를 다루는 API인데, 엔드포인트마다 응답 구성이 변함.
  2. 속성을 추가하는 구간?이 시리얼라이져를 지날때 뿐임. 그러다 보니, 옵션으로 인자 넘기는게 불편함.

대안

attr_accessor와 PORO를 사용해 보자

class Advertise < ActiveRecord::Base
  # Associations
  # ------------
  has_many :advertise_targets

  attr_accessor :matching_target

  # Scopes
  # ------
	...

  # Macros
  # ------
	...

  # Methods
  # -------
	...
	def matching_target= target
    raise ArgumentError, "#{target} is not MatchingTarget Type!" if target && !target.is_a?(MatchingTarget)
    @matching_target = target
  end
end

class AdvertiseTarget < ActiveRecord::Base
  # Associations
  # ------------
  belongs_to :advertise
	...
end

class MatchingTarget
  attr_accessor :id, :type, :info

  def initialize(id, type, info)
    @id = id
    @type = type
    @info = info
  end
end

장점

코드도 간결하고. 게터 세터가 쉽게 생성 됨.

클래스의 속성들을 선언 해 놨기 떄문에, 스펙이 정해 짐.

응답 형태가 쉽고 예쁘게.

temporary state를 편하게.

단점

matching_target 속성이 추가되었으나, 항상 사용되는 것은 아니다.

...

기타

세터를 오버라이드 하여, 밸리데이션을 추가함.

MatchingTarget 클래스는 app/model/advertises 디렉토리 안에 넣음.

느낀점

이런식으로 temporary state를 다루는 방식을 구글링 해 보았으나, 자료가 딱히 없음.

이런 상황이 별로 없어서 일까. 좋은 케이스가 아니어서 일까..

→ 이렇게 해도 될지 감이 안 옴.

좀 더 나은 방식이 있다면 알려주세요.

profile
Backend Developer

0개의 댓글