(몇 달 전에 이 게시물을 내 목록에 보냈습니다. 이 게시물이 마음에 들고 더 읽고 싶다면 가입해야 합니다!)
요전날 내 앱 중 하나에 이상한 상황이 발생했습니다.
Article
가 있다고 가정해 보겠습니다. 모델이며 이러한 기사는 먼저 초안으로 작성됩니다. 이러한 초안은 가벼워야 합니다. 본문이나 제목 없이 바로 만들고 편집할 수 있기를 원합니다.
하지만 게시하면 이 기사를 보려면 몇 가지 추가 유효성 검사가 필요합니다. 제목, 본문 및 기타 모든 항목이 있어야 합니다.
if
스스로 확인하는 문장. 하지만 Rails에서 얻을 수 있는 모든 멋진 폼 핸들링을 갖고 있지는 않을 것입니다. 그리고 Rails가 잘 처리하는 일에 대해 Rails를 사용하면 나중에 골치 아픈 일을 많이 줄일 수 있다는 것을 알게 되었습니다. 이에 대한 유효성 검사를 사용할 수 있는 방법이 있습니까?
if
및 unless
?
검증 지원 :if
및 :unless
매개변수가 있지만 항상 깨끗한 것은 아닙니다.
class Article < ActiveRecord::Base
# validate in draft mode
validates_presence_of :author_id
# validate only when published
validates_presence_of :body, unless: lambda { |o| o.draft? }
...
end
게다가 기사를 게시하려는 방식이 아닙니다. 기사를 액션으로 게시하는 것에 대해 생각하고 싶습니다. , 주가 아님 기사가 들어있어 속성을 설정하고 확인하는 것은 정답이 아닙니다.
잘 알려지지 않고 약간 문서화된 Rails 기능
이 문제는 Rails의 유효성 검사 컨텍스트에 완벽하게 맞습니다. 나는 먼저 DHH가 쓴 요지에서 사용자 정의 유효성 검사 컨텍스트에 대해 배웠습니다. 그러나 이것들이 무엇인지, 어떻게 사용하는지에 대한 좋은 설명을 찾기가 어려웠습니다.
사용자 정의 컨텍스트에 대한 문서는 매우 얇습니다. API 문서에서 찾을 수 있는 유일한 언급은 여기에 있습니다. 그리고 이러한 유효성 검사에 대한 API 문서에는 사용자 정의 컨텍스트가 전혀 언급되어 있지 않습니다! 이것은 특히 어렵습니다. 무언가의 이름을 모르는 경우 관련 문서를 어떻게 더 찾을 수 있습니까?
마침내 https://blog.arkency.com/2014/04/mastering-rails-validations-contexts/에서 좋은 개요를 찾았습니다. 읽을 가치가 있습니다. 우리의 예에서 어떻게 보이는지 봅시다:
class Article < ActiveRecord::Base
# validate in draft mode
validates_presence_of :author_id
# validate only when published
validates_presence_of :body, on: :publish
...
end
class ArticleController < ApplicationController
respond_to :html
def create
@article = Article.create(article_params)
respond_with @article
end
def publish
@article = Article.find(params[:id])
@article.attributes = article_params
@article.save(context: :publish)
respond_with @article
end
private
def article_params
params.
require(:article).
permit(:body, :title, :author_id)
end
end
나쁘지 않아! 유일한 이상한 점은 save
를 사용해야 한다는 것입니다. update
대신 게시 방법에서. 이는 update
때문에 발생합니다. 유효성 검사 컨텍스트를 매개변수로 사용할 수 없습니다. (그게 풀 리퀘스트의 기회가 아닐까요?)
저장 이상
사용자 지정 유효성 검사 컨텍스트는 다양한 방법으로 레코드를 저장하는 것 이상으로 유용합니다. 컨텍스트는 valid?
와 함께 작동합니다. :
@article.valid?(:publish)
따라서 “이 개체에 이 속성이 있습니까? 그렇지 않다면 그 이유는 무엇입니까?”
DHH는 -able?
로 끝나는 메소드를 생성합니다. valid?(:context)
에 위임 ). 그 모습이 정말 마음에 듭니다:
class Article
validate :has_been_published, on: :view
validate :is_not_spam, on: :view
def viewable?
valid? :view
end
private
def has_been_published
if published_at.future?
errors.add(:published_at, "is in the future")
end
end
def is_not_spam
if is_spam?(body)
errors.add(:body, "has been detected as spam")
end
end
end
이렇게 하면 확인할 때 true
보다 더 많은 정보를 얻을 수 있습니다. 또는 false
:
unless @article.viewable?
# @article.errors is now filled out
end
기사를 볼 수 있습니까? 글쎄요?
충분히 가벼움
이러한 종류의 유효성 검사 동작을 얻을 수 있는 몇 가지 다른 방법이 있습니다. 사용자 정의 ActiveModel
을 빌드할 수 있습니다. 자체 유효성 검사가 있는 서비스 개체. :if
를 사용할 수 있습니다. 또는 :unless
당신의 검증에. 그러나 Rails의 많은 항목과 마찬가지로 사용자 지정 유효성 검사 컨텍스트는 가독성과 유연성 사이에서 좋은 절충안입니다.