Rails의 양식 개체 패턴: YAAF를 사용하여 모든 것에 대한 서비스 생성 중지
11986 단어 railscodequalityopensourceruby
대형 컨트롤러 작업
대형 컨트롤러 방법을 얼마나 많이 접하셨습니까? 당신이 나처럼 운이 좋다면 아마도 여러 번일 것입니다.
긴 컨트롤러 리팩토링을 시작하는 가장 일반적인 방법 중 하나는 코드를 서비스로 옮기는 것입니다.
서비스는 훌륭하고 원자적인 방식으로 코딩하면 테스트하고 이해하기 쉽습니다. 그러나 문제는 서비스를 사용할 때 스위스 군용 칼을 사용하는 것과 같습니다.
-"Hey, I don't know how to properly refactor this piece of code" -"Dude, just do a new service"
하지만 아니요! 새로운 서비스를 만드는 것이 항상 최선의 선택은 아닙니다. 어떤 경우에는 바퀴를 재발명하고 있으며 이미 우리의 요구에 맞는 패턴이 있을 수 있습니다.
그래서 여기에 YAAF가 등장합니다. 우리의 하루를 구하는 또 다른 활성 형식입니다. YAAF는 Rails를 사용하여 쉽고 친숙한 방식으로 양식 개체를 만들 수 있는 보석입니다.
ActiveRecord
및 ActiveModel
기능을 사용하여 완전히 구성 가능한 상태로 유지하면서 Rails 모델처럼 작동하는 양식 개체를 제공합니다.YAAF는 언제 사용합니까?
데이터베이스에 새 게시물을 저장하는 API 엔드포인트가 있다고 가정해 보겠습니다. 게시물에는 제목, 본문, 게시자가 있으며 태그와 범주도 있을 수 있습니다.
게시자가 게시물을 보내는 즉시 태그 및 카테고리를 생성할 수 있습니다. (만약 우리의 입력이 정확한 태그나 카테고리를 찾지 못한다면, 사용자가 새로운 태그나 카테고리를 쓰도록 할 것입니다).
따라서 최악의 시나리오에서 컨트롤러는 다음과 같을 수 있습니다.
class Api::V1::PostsController < Api::V1::ApiController
def index
@posts = Post.all
end
def create
ActiveRecord::Base.transaction do
@post = Post.new(post_params)
@post.tags = params[:tags].map do |tag|
tag[:id].present? ? Tag.find(tag[:id]) : Tag.find_or_create_by(name: tag[:name])
end
if params[:category_name].present?
category = Category.create!(name: params[:category_name])
@post.category = category
end
@post.save!
end
end
def post_params
params.require(:post).permit(:title, :body, :publisher_id, :category_id)
end
end
끔찍해 보이죠? 아마도 그 코드 조각에 대한 첫 번째 생각은 게시물 생성을
PostCreationService
라는 서비스로 이동하는 리팩토링을 만드는 것입니다. 이것은 유용할 수 있으며 향후 시스템의 다른 부분에서 사용될 수 있습니다. 하지만 바퀴를 재발명하는 것에 대해 무엇을 말했습니까?YAAF를 사용할 때 게시물 생성의 모든 로직과 관련 모델을 내부에 캡슐화할 새
PostForm
클래스를 만들어야 합니다. 그리고 그것을 구현하는 것은 매우 간단합니다! 이 코드를 보세요.# app/forms/post_form.rb
class PostForm < ApplicationForm
attr_accessor :post, :category_name, :tags
validate :amount_of_tags
def initialize(args = {})
super(args)
@models = [new_post, category, post_tags].flatten.compact
end
def new_post
@new_post ||= Post.new(post).tap do |post|
post.category = category
post.tags = post_tags
end
end
def category
return [] if category_name.blank?
@category ||= Category.find_or_initialize_by(name: category_name)
end
def post_tags
return [] if tags.blank?
@post_tags ||= tags.map do |tag|
tag[:id].present? ? Tag.find(tag[:id]) : Tag.find_or_initialize_by(name: tag[:name])
end
end
private
def amount_of_tags
return if tags.size.between?(1, 3)
errors.add(:base, "You can't assign more than three tags to a post")
end
end
참고: YAAF가 양식 개체에 비즈니스 규칙을 캡슐화하는 데 도움이 되므로
amount_of_tags
라는 맞춤 유효성 검사도 추가했습니다.그런 다음 컨트롤러에는 다음이 있습니다.
class Api::V1::PostsController < Api::V1::ApiController
def index
@posts = Post.all
end
def create
form = PostForm.new(post_form_params)
form.save!
@post = form.post
end
private
def post_form_params
params.permit(:category_name, tags: %i[id name], post: %i[title body publisher_id category_id])
end
end
도움말:
ApplicationForm
에서 상속되는 YAAF::Form
를 갖는 것은 좋은 습관입니다.그게 다야, 이제 게시물/태그/카테고리의 모든 지속성 로직을 캡슐화하는
PostForm
가 있어 컨트롤러와 모델을 깔끔하게 유지하고 따르기 쉬운 코드를 제공합니다.또 다른 좋은 점은 YAAF가
ActiveModel
모델과 유사한 API를 제공하므로 서로 바꿔서 취급할 수 있다는 것입니다.서비스나 PORO가 아닌 이유는 무엇입니까?
팀으로 작업하는 경우 맞춤형 서비스 또는 PORO를 만드는 것이 무질서할 수 있습니다.
요약
여기까지 했다면 이 문서가 YAAF를 프로젝트에 통합하는 데 도움이 되길 바랍니다. 또한
FormObject
패턴을 사용하여 코드를 더욱 개선하는 데 도움이 되었기를 바랍니다. 더 많은 예를 볼 수 있습니다here. YAAF는 오픈소스이며 새로운 기여를 받을 수 있습니다.그래서 그것을 확인하고 당신의 생각을 참조하십시오!
Reference
이 문제에 관하여(Rails의 양식 개체 패턴: YAAF를 사용하여 모든 것에 대한 서비스 생성 중지), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/rootstrap/form-object-patterns-in-rails-stop-creating-services-for-everything-with-yaaf-409o텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)