Created
July 25, 2012 13:15
-
-
Save nnabeyang/3176144 to your computer and use it in GitHub Desktop.
validatesの簡易版
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Class | |
| def class_attribute name | |
| class_eval <<-RUBY, __FILE__, __LINE__ + 1 | |
| def self.#{name}() nil end | |
| def self.#{name}=(val) | |
| singleton_class.class_eval { | |
| undef_method :#{name} | |
| define_method(:#{name}) { val } | |
| } | |
| val | |
| end | |
| RUBY | |
| end | |
| end | |
| module MyRails | |
| module Concern | |
| def self.extended(base) | |
| base.instance_variable_set("@dependencies", []) | |
| end | |
| def append_features(base) | |
| if base.instance_variable_defined?("@dependencies") | |
| base.instance_variable_get("@dependencies") << self | |
| else | |
| super | |
| @dependencies.each {|dep| base.send(:include, dep)} | |
| base.extend const_get("ClassMethods") if const_defined?("ClassMethods") | |
| end | |
| end | |
| end | |
| module Callbacks | |
| extend Concern | |
| class Callback | |
| @@_callback_sequence = 0 | |
| attr_reader :filter | |
| def initialize(callback_name, callback_obj, callbacks_class) | |
| @filter = "_callback_#{callback_name}_#{next_id}" | |
| callbacks_class.send(:define_method, "#{@filter}_object") { callback_obj } | |
| callbacks_class.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 | |
| def #{@filter} | |
| #{@filter}_object.#{callback_name}(self) | |
| end | |
| RUBY_EVAL | |
| end | |
| def next_id | |
| @@_callback_sequence += 1 | |
| end | |
| end | |
| def run_callbacks(callback_name) | |
| self.class.send("_#{callback_name}_callbacks").each do|callback| | |
| send(callback.filter) | |
| end | |
| end | |
| module ClassMethods | |
| def define_callback(callback_name) | |
| attr_name = "_#{callback_name}_callbacks" | |
| class_attribute attr_name | |
| send("#{attr_name}=", Array.new) | |
| end | |
| def set_callback(callback_name, callback_obj) | |
| send("_#{callback_name}_callbacks").push(Callback.new(callback_name, callback_obj, self)) | |
| end | |
| end | |
| end | |
| module Validations | |
| extend Concern | |
| include Callbacks | |
| attr_reader :errors | |
| def initialize | |
| @errors = [] | |
| end | |
| def valid? | |
| @errors.clear | |
| run_callbacks(:validate) | |
| return @errors.empty? | |
| end | |
| module ClassMethods | |
| def validates(*attributes) | |
| validations = extract_validations! attributes | |
| validations.each do|validation| | |
| validator_class = const_get "#{validation.to_s.camelize}Validator" | |
| validate_with(validator_class, attributes) | |
| end | |
| end | |
| def extract_validations! attributes | |
| attributes.pop if attributes.last.kind_of? Hash | |
| end | |
| def validate_with(validator_class, attributes) | |
| attributes.each do|attribute| | |
| set_callback(:validate, validator_class.new(attributes)) | |
| end | |
| end | |
| end | |
| class PresenceValidator | |
| def initialize attributes | |
| @attributes = attributes | |
| end | |
| def validate validations | |
| @attributes.each do|attribute| | |
| validations.errors.push("#{attribute} can't be blank") if !validations.send(attribute.to_sym) | |
| end | |
| end | |
| end | |
| end | |
| end | |
| class String | |
| def camelize | |
| "Presence" | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'myrails' | |
| require 'test/unit' | |
| require 'stringio' | |
| class C | |
| class_attribute :name | |
| end | |
| class CallbackObj | |
| def callback_method(record) | |
| record.log.push(1) | |
| end | |
| end | |
| class CallbackObj2 | |
| def callback_method(record) | |
| record.log.push(2) | |
| end | |
| end | |
| class Callbacks | |
| include MyRails::Callbacks | |
| attr_reader :log | |
| def initialize | |
| @log = [] | |
| end | |
| define_callback :callback_method | |
| set_callback(:callback_method, CallbackObj.new) | |
| set_callback(:callback_method, CallbackObj2.new) | |
| end | |
| class Validations | |
| include MyRails::Validations | |
| attr_accessor :name | |
| define_callback :validate | |
| validates :name, :presence => true | |
| end | |
| class MyRailsTests < Test::Unit::TestCase | |
| def test_validations_extract_attributes | |
| inp = [:name, :presence => true] | |
| validations = Validations.extract_validations! inp | |
| assert_equal [:name], inp | |
| assert_equal({:presence => true}, validations) | |
| end | |
| def test_string_camelize | |
| assert_equal "Presence", "presence".camelize | |
| end | |
| def test_validations_validates | |
| obj = Validations.new | |
| assert !obj.valid? | |
| assert_equal ["name can't be blank"], obj.errors | |
| obj.name = "nabeyang" | |
| assert obj.valid? | |
| end | |
| def test_class_attribute | |
| name = "nabeyang" | |
| assert_equal name, (C.name = name) | |
| assert_equal name, C.name | |
| end | |
| def test_callbacks_set_callback | |
| assert_equal 2, Callbacks._callback_method_callbacks.size | |
| end | |
| def test_callbacks_run_callback | |
| obj = Callbacks.new | |
| s = StringIO.new | |
| obj.run_callbacks(:callback_method) | |
| assert_equal [1, 2], obj.log | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment