Papa Carlo처럼 컨트롤러를 조각하세요.
다양한 추상화 계층을 추가합니다.
쿼리 매개변수 기반 필터를 처리할 때 여전히 다음과 같이 작성해야 합니다.
class EventsController < ApplicationController
def index
events = Event.all.
page(params[:page] || 1).
order(sort_params)
events = events.where(
type: params[:type_filter]
) if params[:type_filter].in?(%w[published draft])
events = events.future if params[:time_filter] == "future"
# NOTE: `searched` is a scope or class method defined on the Event model
events = events.searched(params[:q]) if params[:q].present?
render json: events
end
def sort_params
sort_by = params[:sort_by].in?(%w[id name started_at]) ?
params[:sort_by] :
:started_at
sort_order = params[:sort].in?(%w[asc desc]) ? params[:sort] : :desc
{ sort_by => sort_order }
end
end
날씬하지 않은 컨트롤러가 있음에도 불구하고 읽기, 테스트 및 유지 관리가 어려운 코드가 있습니다.
새로운 보석interactors(러시아어로 "손 평면"을 의미)을 사용하여 이 컨트롤러(파파 카를로가 통나무에서 부라티노policies를 조각한 것처럼)를 조각할 수 있는 방법을 보여주고 싶습니다.
form objects은 해시 기반 매개변수로 구동되는 데이터 변환을 위한 범용 도구입니다.
좋아요, 이상하게 들리네요 😕
위의 예를 살펴보겠습니다. 데이터(활성 레코드 관계,
Event.all
)를 가져와서 사용자 입력(params
개체)에 따라 변환합니다.컨트롤러 외부 어딘가에서 이 변환을 추출할 수 있다면 어떨까요?
"이 추상화의 요점은 무엇입니까?"
Russian Pinocchio이 있습니다.
먼저 Rubanok을 추가할 때 위의 컨트롤러가 어떻게 보이는지 보여드리겠습니다.
class EventsController < ApplicationController
def index
events = planish Event.all
render json: events
end
end
그게 다야. 이보다 더 얇을 수는 없습니다(좋아요,
render json: planish(Event.all)
).planish
메서드 아래에 무엇이 숨겨져 있습니까?구성 원칙보다 관례를 활용하는 Rails 전용 방법(btw, Rubanok 자체는 Rails-free임)이며 다음과 같이 전개될 수 있습니다.
def index
events = EventsPlane.call(Event.all, params.to_unsafe_h)
render json: events
end
그리고
EventsPlane
클래스는 모든 마법 변환이 일어나는 곳입니다:class EventsPlane < Rubanok::Plane
TYPES = %w[draft published].freeze
SORT_FIELDS = %w[id name started_at].freeze
SORT_ORDERS = %w[asc desc].freeze
map :page, activate_always: true do |page: 1|
raw.page(page)
end
map :type_filter do |type_filter:|
next raw.none unless TYPES.include?(type_filter)
raw.where(type: type_filter)
end
match :time_filter do
having "future" do
raw.future
end
default { |_time_filter| raw.none }
end
map :sort_by, :sort do |sort_by: "started_at", sort: "desc"|
next raw unless SORT_FIELDS.include?(sort_by) &&
SORT_ORDERS.include?(sort)
raw.order(sort_by => sort)
end
map :q do |q:|
raw.searched(q)
end
end
평면 클래스는 전달된
raw
에 따라 데이터를 변환하는 방법(params
메서드를 통해 액세스 가능)을 설명합니다.map
를 사용하여 키를 추출하고 해당 값이 비어 있지 않은 경우(즉, 빈 문자열은 무시됨) 변환을 적용합니다. 여기서 Ruby 키워드 인수 기본값을 사용할 수 있습니다. 멋지죠? match
를 사용하여 변압기를 선택할 때도 값을 고려하십시오. 이제 비행기에 대한 테스트를 따로 작성할 수 있습니다.
describe EventsPlane do
let(:input) { Event.all }
# add default transformations
let(:output) { input.page(1).order(started_at: :desc) }
let(:params) { {} }
# we match the resulting SQL query and do not make real queries
# at all–our tests are fast!
subject { described_class.call(input, params).to_sql }
specify "q=?" do
params[:q] = "wood"
expect(subject).to eq(output.searched("wood").to_sql)
end
specify "type_filter=<valid>" do
params[:type_filter] = "draft"
expect(subject).to eq(output.where(type: "draft").to_sql)
end
specify "type_filter=<invalid>" do
params[:type_filter] = "unpublished"
expect(subject).to eq(output.none.to_sql)
end
# ...
end
컨트롤러/요청 테스트에서 필요한 것은 특정 평면이 사용되었는지 확인하는 것입니다.
describe EventsController do
subject { get :index }
specify do
expect { subject }.to have_planished(Event.all).
with(EventsPlane)
end
end
따라서 Rubanok은 컨트롤러를 조각하는 데 적합하지만 범용이라고 말했습니다. GraphQL 예제로 증명해 보겠습니다!
module GraphAPI
module Types
class Query < GraphQL::Schema::Object
field :profiles, Types::Profile.connection_type, null: false do
argument :city, Int, required: false
argument :home, Int, required: false
argument :tags, [ID], required: false
argument :q, String, required: false
end
def profiles(**params)
ProfilesPlane.call(Profile.all, params)
end
end
end
end
이제 막 마른 체형을 발명한 것 같습니다 🙂
자세한 내용은 Rubanok 저장소를 확인하고 자유롭게 아이디어를 제안하세요!
추신 유사한 아이디어(PORO 방식이지만)를 구현하지만 ActiveRecord에 초점을 맞추고 테스트 지원이 부족한 이전 gemseveral reasons이 있습니다.
추신 대규모 애플리케이션에서 코드를 구성하는 데 사용하는 다른 추상화가 궁금하십니까? 또는 make tests faster 과 같은 다른 게시물과 Rubanok 및
filterer
과 같은 프로젝트를 확인하십시오."Clowne: Clone Ruby models with a smile"에서 더 많은 개발 기사를 읽어보세요!
Reference
이 문제에 관하여(Papa Carlo처럼 컨트롤러를 조각하세요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/evilmartians/carve-your-controllers-like-papa-carlo-32m6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)