Skip to content

Instantly share code, notes, and snippets.

@rummelonp
Last active December 20, 2015 10:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rummelonp/6119911 to your computer and use it in GitHub Desktop.
Save rummelonp/6119911 to your computer and use it in GitHub Desktop.
ActiveRecord でバリデーションをコンテキスト毎に分けるやつ
class User < ActiveRecord::Base
include ValidationContext
with_context :first do |context|
context.validates_presence_of :name
end
with_context :second do |context|
context.validates_presence_of :email
end
end
class UsersController < ApplicationController
before_filter :require_user
def first
if @user.with_context(:first) { |u| u.update_attributes(params[:user]) }
# do something
else
# do something
end
end
def second
if @user.with_context(:second) { |u| u.update_attributes(params[:user]) }
# do something
else
# do something
end
end
private
def require_user
@user = User.find(params[:id])
end
end
module ValidationContext
extend ActiveSupport::Concern
included do
before_validation :reflect_context_to_associations
def self.with_context(*contexts, &block)
options = contexts.last.is_a?(Hash) ? contexts.last.dup : {}
options[:if] = Array.wrap(options[:if])
options[:if] << ->(o) { o.context.nil? || o.context.in?(contexts) }
with_options(options, &block)
end
end
attr_reader :context
def context=(context)
@context = context
reflect_context_to_associations
end
def reflect_context_to_associations
self.class.reflect_on_all_associations.each do |reflection|
association = self.association(reflection.name)
Array.wrap(association.target).each do |record|
if record.respond_to?(:context=)
record.context = context
end
end
end
end
def with_context(context, &block)
current_context, self.context = self.context, context
yield self
ensure
self.context = current_context
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment