activemodel-3.2.16/0000755000175000017500000000000012247654710013433 5ustar ondrejondrejactivemodel-3.2.16/CHANGELOG.md0000644000175000017500000000422212247654710015244 0ustar ondrejondrej## Rails 3.2.15 (Oct 16, 2013) ## * No changes. ## Rails 3.2.14 (Jul 22, 2013) ## * No changes. ## Rails 3.2.13 (Mar 18, 2013) ## * Specify type of singular association during serialization *Steve Klabnik* ## Rails 3.2.12 (Feb 11, 2013) ## * Fix issue with `attr_protected` where malformed input could circumvent protection. CVE-2013-0276 *joernchen* ## Rails 3.2.11 (Jan 8, 2013) ## * No changes. ## Rails 3.2.10 (Jan 2, 2013) ## * No changes. ## Rails 3.2.9 (Nov 12, 2012) ## * Due to a change in builder, nil values and empty strings now generates closed tags, so instead of this: It generates this: *Carlos Antonio da Silva* ## Rails 3.2.8 (Aug 9, 2012) ## * No changes. ## Rails 3.2.7 (Jul 26, 2012) ## * `validates_inclusion_of` and `validates_exclusion_of` now accept `:within` option as alias of `:in` as documented. * Fix the the backport of the object dup with the ruby 1.9.3p194. ## Rails 3.2.6 (Jun 12, 2012) ## * No changes. ## Rails 3.2.4 (May 31, 2012) ## * No changes. ## Rails 3.2.3 (March 30, 2012) ## * No changes. ## Rails 3.2.2 (March 1, 2012) ## * No changes. ## Rails 3.2.1 (January 26, 2012) ## * No changes. ## Rails 3.2.0 (January 20, 2012) ## * Deprecated `define_attr_method` in `ActiveModel::AttributeMethods`, because this only existed to support methods like `set_table_name` in Active Record, which are themselves being deprecated. *Jon Leighton* * Add ActiveModel::Errors#added? to check if a specific error has been added *Martin Svalin* * Add ability to define strict validation(with :strict => true option) that always raises exception when fails *Bogdan Gusiev* * Deprecate "Model.model_name.partial_path" in favor of "model.to_partial_path" *Grant Hutchins, Peter Jaros* * Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior *Bogdan Gusiev* Please check [3-1-stable](https://github.com/rails/rails/blob/3-1-stable/activemodel/CHANGELOG.md) for previous changes. activemodel-3.2.16/README.rdoc0000644000175000017500000001240012247654710015236 0ustar ondrejondrej= Active Model -- model interfaces for Rails Active Model provides a known set of interfaces for usage in model classes. They allow for Action Pack helpers to interact with non-ActiveRecord models, for example. Active Model also helps building custom ORMs for use outside of the Rails framework. Prior to Rails 3.0, if a plugin or gem developer wanted to have an object interact with Action Pack helpers, it was required to either copy chunks of code from Rails, or monkey patch entire helpers to make them handle objects that did not exactly conform to the Active Record interface. This would result in code duplication and fragile applications that broke on upgrades. Active Model solves this. You can include functionality from the following modules: * Add attribute magic to objects class Person include ActiveModel::AttributeMethods attribute_method_prefix 'clear_' define_attribute_methods [:name, :age] attr_accessor :name, :age def clear_attribute(attr) send("#{attr}=", nil) end end person.clear_name person.clear_age {Learn more}[link:classes/ActiveModel/AttributeMethods.html] * Callbacks for certain operations class Person extend ActiveModel::Callbacks define_model_callbacks :create def create run_callbacks :create do # Your create action methods here end end end This generates +before_create+, +around_create+ and +after_create+ class methods that wrap your create method. {Learn more}[link:classes/ActiveModel/Callbacks.html] * Tracking value changes The ActiveModel::Dirty module allows for tracking attribute changes: person = Person.new person.name # => nil person.changed? # => false person.name = 'bob' person.changed? # => true person.changed # => ['name'] person.changes # => { 'name' => [nil, 'bob'] } person.name = 'robert' person.save person.previous_changes # => {'name' => ['bob, 'robert']} {Learn more}[link:classes/ActiveModel/Dirty.html] * Adding +errors+ interface to objects Exposing error messages allows objects to interact with Action Pack helpers seamlessly. class Person def initialize @errors = ActiveModel::Errors.new(self) end attr_accessor :name attr_reader :errors def validate! errors.add(:name, "can not be nil") if name.nil? end def ErrorsPerson.human_attribute_name(attr, options = {}) "Name" end end person.errors.full_messages # => ["Name can not be nil"] person.errors.full_messages # => ["Name can not be nil"] {Learn more}[link:classes/ActiveModel/Errors.html] * Model name introspection class NamedPerson extend ActiveModel::Naming end NamedPerson.model_name # => "NamedPerson" NamedPerson.model_name.human # => "Named person" {Learn more}[link:classes/ActiveModel/Naming.html] * Observer support ActiveModel::Observers allows your object to implement the Observer pattern in a Rails App and take advantage of all the standard observer functions. {Learn more}[link:classes/ActiveModel/Observer.html] * Making objects serializable ActiveModel::Serialization provides a standard interface for your object to provide +to_json+ or +to_xml+ serialization. s = SerialPerson.new s.serializable_hash # => {"name"=>nil} s.to_json # => "{\"name\":null}" s.to_xml # => "\n "My attribute" {Learn more}[link:classes/ActiveModel/Translation.html] * Validation support class Person include ActiveModel::Validations attr_accessor :first_name, :last_name validates_each :first_name, :last_name do |record, attr, value| record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z end end person = Person.new person.first_name = 'zoolander' person.valid? # => false {Learn more}[link:classes/ActiveModel/Validations.html] * Custom validators class Person include ActiveModel::Validations validates_with HasNameValidator attr_accessor :name end class HasNameValidator < ActiveModel::Validator def validate(record) record.errors[:name] = "must exist" if record.name.blank? end end p = ValidatorPerson.new p.valid? # => false p.errors.full_messages # => ["Name must exist"] p.name = "Bob" p.valid? # => true {Learn more}[link:classes/ActiveModel/Validator.html] == Download and installation The latest version of Active Model can be installed with RubyGems: % [sudo] gem install activemodel Source code can be downloaded as part of the Rails project on GitHub * https://github.com/rails/rails/tree/3-2-stable/activemodel == License Active Model is released under the MIT license. == Support API documentation is at * http://api.rubyonrails.org Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here: * https://github.com/rails/rails/issues activemodel-3.2.16/checksums.yaml.gz0000444000175000017500000000041312247654710016717 0ustar ondrejondrej#Re;R0 "c˒%R08=%Zvy{YK{jd-԰XהVat_a_"Z0kٞkkaO+MAIͷRn0#c322eoB.&[:w2N!I0r2MVf=0DyZT'VmO }}ЈFzvն4:0kHP?^#B.?activemodel-3.2.16/lib/0000755000175000017500000000000012247654710014201 5ustar ondrejondrejactivemodel-3.2.16/lib/active_model/0000755000175000017500000000000012247654710016634 5ustar ondrejondrejactivemodel-3.2.16/lib/active_model/validations.rb0000644000175000017500000001743712247654710021512 0ustar ondrejondrejrequire 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/hash/except' require 'active_model/errors' require 'active_model/validations/callbacks' require 'active_model/validator' module ActiveModel # == Active Model Validations # # Provides a full validation framework to your objects. # # A minimal implementation could be: # # class Person # include ActiveModel::Validations # # attr_accessor :first_name, :last_name # # validates_each :first_name, :last_name do |record, attr, value| # record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z # end # end # # Which provides you with the full standard validation stack that you # know from Active Record: # # person = Person.new # person.valid? # => true # person.invalid? # => false # # person.first_name = 'zoolander' # person.valid? # => false # person.invalid? # => true # person.errors # => #["starts with z."]}> # # Note that ActiveModel::Validations automatically adds an +errors+ method # to your instances initialized with a new ActiveModel::Errors object, so # there is no need for you to do this manually. # module Validations extend ActiveSupport::Concern include ActiveSupport::Callbacks included do extend ActiveModel::Translation extend HelperMethods include HelperMethods attr_accessor :validation_context define_callbacks :validate, :scope => :name class_attribute :_validators self._validators = Hash.new { |h,k| h[k] = [] } end module ClassMethods # Validates each attribute against a block. # # class Person # include ActiveModel::Validations # # attr_accessor :first_name, :last_name # # validates_each :first_name, :last_name do |record, attr, value| # record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z # end # end # # Options: # * :on - Specifies the context where this validation is active # (e.g. :on => :create or :on => :custom_validation_context) # * :allow_nil - Skip validation if attribute is +nil+. # * :allow_blank - Skip validation if attribute is blank. # * :if - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. :if => :allow_validation, # or :if => Proc.new { |user| user.signup_step > 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or # :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. def validates_each(*attr_names, &block) options = attr_names.extract_options!.symbolize_keys validates_with BlockValidator, options.merge(:attributes => attr_names.flatten), &block end # Adds a validation method or block to the class. This is useful when # overriding the +validate+ instance method becomes too unwieldy and # you're looking for more descriptive declaration of your validations. # # This can be done with a symbol pointing to a method: # # class Comment # include ActiveModel::Validations # # validate :must_be_friends # # def must_be_friends # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) # end # end # # With a block which is passed with the current record to be validated: # # class Comment # include ActiveModel::Validations # # validate do |comment| # comment.must_be_friends # end # # def must_be_friends # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) # end # end # # Or with a block where self points to the current record to be validated: # # class Comment # include ActiveModel::Validations # # validate do # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) # end # end # def validate(*args, &block) options = args.extract_options! if options.key?(:on) options = options.dup options[:if] = Array.wrap(options[:if]) options[:if].unshift("validation_context == :#{options[:on]}") end args << options set_callback(:validate, *args, &block) end # List all validators that are being used to validate the model using # +validates_with+ method. def validators _validators.values.flatten.uniq end # List all validators that being used to validate a specific attribute. def validators_on(*attributes) attributes.map do |attribute| _validators[attribute.to_sym] end.flatten end # Check if method is an attribute method or not. def attribute_method?(attribute) method_defined?(attribute) end # Copy validators on inheritance. def inherited(base) dup = _validators.dup base._validators = dup.each { |k, v| dup[k] = v.dup } super end end # Clean the +Errors+ object if instance is duped def initialize_dup(other) # :nodoc: @errors = nil super if defined?(super) end # Backport dup from 1.9 so that #initialize_dup gets called unless Object.respond_to?(:initialize_dup, true) def dup # :nodoc: copy = super copy.initialize_dup(self) copy end end # Returns the +Errors+ object that holds all information about attribute error messages. def errors @errors ||= Errors.new(self) end # Runs all the specified validations and returns true if no errors were added # otherwise false. Context can optionally be supplied to define which callbacks # to test against (the context is defined on the validations using :on). def valid?(context = nil) current_context, self.validation_context = validation_context, context errors.clear run_validations! ensure self.validation_context = current_context end # Performs the opposite of valid?. Returns true if errors were added, # false otherwise. def invalid?(context = nil) !valid?(context) end # Hook method defining how an attribute value should be retrieved. By default # this is assumed to be an instance named after the attribute. Override this # method in subclasses should you need to retrieve the value for a given # attribute differently: # # class MyClass # include ActiveModel::Validations # # def initialize(data = {}) # @data = data # end # # def read_attribute_for_validation(key) # @data[key] # end # end # alias :read_attribute_for_validation :send protected def run_validations! run_callbacks :validate errors.empty? end end end Dir[File.dirname(__FILE__) + "/validations/*.rb"].sort.each do |path| filename = File.basename(path) require "active_model/validations/#{filename}" end activemodel-3.2.16/lib/active_model/mass_assignment_security.rb0000644000175000017500000002102012247654710024276 0ustar ondrejondrejrequire 'active_support/core_ext/class/attribute' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/array/wrap' require 'active_model/mass_assignment_security/permission_set' require 'active_model/mass_assignment_security/sanitizer' module ActiveModel # = Active Model Mass-Assignment Security module MassAssignmentSecurity extend ActiveSupport::Concern included do class_attribute :_accessible_attributes class_attribute :_protected_attributes class_attribute :_active_authorizer class_attribute :_mass_assignment_sanitizer self.mass_assignment_sanitizer = :logger end # Mass assignment security provides an interface for protecting attributes # from end-user assignment. For more complex permissions, mass assignment security # may be handled outside the model by extending a non-ActiveRecord class, # such as a controller, with this behavior. # # For example, a logged in user may need to assign additional attributes depending # on their role: # # class AccountsController < ApplicationController # include ActiveModel::MassAssignmentSecurity # # attr_accessible :first_name, :last_name # attr_accessible :first_name, :last_name, :plan_id, :as => :admin # # def update # ... # @account.update_attributes(account_params) # ... # end # # protected # # def account_params # role = admin ? :admin : :default # sanitize_for_mass_assignment(params[:account], role) # end # # end # # = Configuration options # # * mass_assignment_sanitizer - Defines sanitize method. Possible values are: # * :logger (default) - writes filtered attributes to logger # * :strict - raise ActiveModel::MassAssignmentSecurity::Error on any protected attribute update # # You can specify your own sanitizer object eg. MySanitizer.new. # See ActiveModel::MassAssignmentSecurity::LoggerSanitizer for example implementation. # # module ClassMethods # Attributes named in this macro are protected from mass-assignment # whenever attributes are sanitized before assignment. A role for the # attributes is optional, if no role is provided then :default is used. # A role can be defined by using the :as option. # # Mass-assignment to these attributes will simply be ignored, to assign # to them you can use direct writer methods. This is meant to protect # sensitive attributes from being overwritten by malicious users # tampering with URLs or forms. Example: # # class Customer # include ActiveModel::MassAssignmentSecurity # # attr_accessor :name, :credit_rating # # attr_protected :credit_rating, :last_login # attr_protected :last_login, :as => :admin # # def assign_attributes(values, options = {}) # sanitize_for_mass_assignment(values, options[:as]).each do |k, v| # send("#{k}=", v) # end # end # end # # When using the :default role: # # customer = Customer.new # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default) # customer.name # => "David" # customer.credit_rating # => nil # customer.last_login # => nil # # customer.credit_rating = "Average" # customer.credit_rating # => "Average" # # And using the :admin role: # # customer = Customer.new # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin) # customer.name # => "David" # customer.credit_rating # => "Excellent" # customer.last_login # => nil # # To start from an all-closed default and enable attributes as needed, # have a look at +attr_accessible+. # # Note that using Hash#except or Hash#slice in place of # +attr_protected+ to sanitize attributes provides basically the same # functionality, but it makes a bit tricky to deal with nested attributes. def attr_protected(*args) options = args.extract_options! role = options[:as] || :default self._protected_attributes = protected_attributes_configs.dup Array.wrap(role).each do |name| self._protected_attributes[name] = self.protected_attributes(name) + args end self._active_authorizer = self._protected_attributes end # Specifies a white list of model attributes that can be set via # mass-assignment. # # Like +attr_protected+, a role for the attributes is optional, # if no role is provided then :default is used. A role can be defined by # using the :as option. # # This is the opposite of the +attr_protected+ macro: Mass-assignment # will only set attributes in this list, to assign to the rest of # attributes you can use direct writer methods. This is meant to protect # sensitive attributes from being overwritten by malicious users # tampering with URLs or forms. If you'd rather start from an all-open # default and restrict attributes as needed, have a look at # +attr_protected+. # # class Customer # include ActiveModel::MassAssignmentSecurity # # attr_accessor :name, :credit_rating # # attr_accessible :name # attr_accessible :name, :credit_rating, :as => :admin # # def assign_attributes(values, options = {}) # sanitize_for_mass_assignment(values, options[:as]).each do |k, v| # send("#{k}=", v) # end # end # end # # When using the :default role: # # customer = Customer.new # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default) # customer.name # => "David" # customer.credit_rating # => nil # # customer.credit_rating = "Average" # customer.credit_rating # => "Average" # # And using the :admin role: # # customer = Customer.new # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin) # customer.name # => "David" # customer.credit_rating # => "Excellent" # # Note that using Hash#except or Hash#slice in place of # +attr_accessible+ to sanitize attributes provides basically the same # functionality, but it makes a bit tricky to deal with nested attributes. def attr_accessible(*args) options = args.extract_options! role = options[:as] || :default self._accessible_attributes = accessible_attributes_configs.dup Array.wrap(role).each do |name| self._accessible_attributes[name] = self.accessible_attributes(name) + args end self._active_authorizer = self._accessible_attributes end def protected_attributes(role = :default) protected_attributes_configs[role] end def accessible_attributes(role = :default) accessible_attributes_configs[role] end def active_authorizers self._active_authorizer ||= protected_attributes_configs end alias active_authorizer active_authorizers def attributes_protected_by_default [] end def mass_assignment_sanitizer=(value) self._mass_assignment_sanitizer = if value.is_a?(Symbol) const_get(:"#{value.to_s.camelize}Sanitizer").new(self) else value end end private def protected_attributes_configs self._protected_attributes ||= begin Hash.new { |h,k| h[k] = BlackList.new(attributes_protected_by_default) } end end def accessible_attributes_configs self._accessible_attributes ||= begin Hash.new { |h,k| h[k] = WhiteList.new } end end end protected def sanitize_for_mass_assignment(attributes, role = nil) _mass_assignment_sanitizer.sanitize(attributes, mass_assignment_authorizer(role)) end def mass_assignment_authorizer(role) self.class.active_authorizer[role || :default] end end end activemodel-3.2.16/lib/active_model/railtie.rb0000644000175000017500000000004612247654710020612 0ustar ondrejondrejrequire "active_model" require "rails"activemodel-3.2.16/lib/active_model/observer_array.rb0000644000175000017500000001024112247654710022204 0ustar ondrejondrejrequire 'set' module ActiveModel # Stores the enabled/disabled state of individual observers for # a particular model class. class ObserverArray < Array attr_reader :model_class def initialize(model_class, *args) @model_class = model_class super(*args) end # Returns true if the given observer is disabled for the model class. def disabled_for?(observer) disabled_observers.include?(observer.class) end # Disables one or more observers. This supports multiple forms: # # ORM.observers.disable :user_observer # # => disables the UserObserver # # User.observers.disable AuditTrail # # => disables the AuditTrail observer for User notifications. # # Other models will still notify the AuditTrail observer. # # ORM.observers.disable :observer_1, :observer_2 # # => disables Observer1 and Observer2 for all models. # # ORM.observers.disable :all # # => disables all observers for all models. # # User.observers.disable :all do # # all user observers are disabled for # # just the duration of the block # end def disable(*observers, &block) set_enablement(false, observers, &block) end # Enables one or more observers. This supports multiple forms: # # ORM.observers.enable :user_observer # # => enables the UserObserver # # User.observers.enable AuditTrail # # => enables the AuditTrail observer for User notifications. # # Other models will not be affected (i.e. they will not # # trigger notifications to AuditTrail if previously disabled) # # ORM.observers.enable :observer_1, :observer_2 # # => enables Observer1 and Observer2 for all models. # # ORM.observers.enable :all # # => enables all observers for all models. # # User.observers.enable :all do # # all user observers are enabled for # # just the duration of the block # end # # Note: all observers are enabled by default. This method is only # useful when you have previously disabled one or more observers. def enable(*observers, &block) set_enablement(true, observers, &block) end protected def disabled_observers @disabled_observers ||= Set.new end def observer_class_for(observer) return observer if observer.is_a?(Class) if observer.respond_to?(:to_sym) # string/symbol observer.to_s.camelize.constantize else raise ArgumentError, "#{observer} was not a class or a " + "lowercase, underscored class name as expected." end end def start_transaction disabled_observer_stack.push(disabled_observers.dup) each_subclass_array do |array| array.start_transaction end end def disabled_observer_stack @disabled_observer_stack ||= [] end def end_transaction @disabled_observers = disabled_observer_stack.pop each_subclass_array do |array| array.end_transaction end end def transaction start_transaction begin yield ensure end_transaction end end def each_subclass_array model_class.descendants.each do |subclass| yield subclass.observers end end def set_enablement(enabled, observers) if block_given? transaction do set_enablement(enabled, observers) yield end else observers = ActiveModel::Observer.descendants if observers == [:all] observers.each do |obs| klass = observer_class_for(obs) unless klass < ActiveModel::Observer raise ArgumentError.new("#{obs} does not refer to a valid observer") end if enabled disabled_observers.delete(klass) else disabled_observers << klass end end each_subclass_array do |array| array.set_enablement(enabled, observers) end end end end end activemodel-3.2.16/lib/active_model/validations/0000755000175000017500000000000012247654710021151 5ustar ondrejondrejactivemodel-3.2.16/lib/active_model/validations/exclusion.rb0000644000175000017500000000774112247654710023520 0ustar ondrejondrejrequire 'active_support/core_ext/range' module ActiveModel # == Active Model Exclusion Validator module Validations class ExclusionValidator < EachValidator ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " << "and must be supplied as the :in (or :within) option of the configuration hash" def check_validity! unless [:include?, :call].any? { |method| delimiter.respond_to?(method) } raise ArgumentError, ERROR_MESSAGE end end def validate_each(record, attribute, value) exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter if exclusions.send(inclusion_method(exclusions), value) record.errors.add(attribute, :exclusion, options.except(:in, :within).merge!(:value => value)) end end private def delimiter @delimiter ||= options[:in] || options[:within] end # In Ruby 1.9 Range#include? on non-numeric ranges checks all possible # values in the range for equality, so it may be slow for large ranges. The new # Range#cover? uses the previous logic of comparing a value with the # range endpoints. def inclusion_method(enumerable) enumerable.is_a?(Range) ? :cover? : :include? end end module HelperMethods # Validates that the value of the specified attribute is not in a particular # enumerable object. # # class Person < ActiveRecord::Base # validates_exclusion_of :username, :in => %w( admin superuser ), :message => "You don't belong here" # validates_exclusion_of :age, :in => 30..60, :message => "This site is only for under 30 and over 60" # validates_exclusion_of :format, :in => %w( mov avi ), :message => "extension %{value} is not allowed" # validates_exclusion_of :password, :in => lambda { |p| [p.username, p.first_name] }, # :message => "should not be the same as your username or first name" # end # # Configuration options: # * :in - An enumerable object of items that the value shouldn't be # part of. This can be supplied as a proc or lambda which returns an enumerable. # If the enumerable is a range the test is performed with Range#cover? # (backported in Active Support for 1.8), otherwise with include?. # * :within - A synonym(or alias) for :in # * :message - Specifies a custom error message (default is: "is reserved"). # * :allow_nil - If set to true, skips this validation if the attribute # is +nil+ (default is +false+). # * :allow_blank - If set to true, skips this validation if the # attribute is blank (default is +false+). # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :if - Specifies a method, proc or string to call to determine if the # validation should occur (e.g. :if => :allow_validation, or # :if => Proc.new { |user| user.signup_step > 2 }). The method, proc # or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine if # the validation should not occur (e.g. :unless => :skip_validation, # or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. def validates_exclusion_of(*attr_names) validates_with ExclusionValidator, _merge_attributes(attr_names) end end end end activemodel-3.2.16/lib/active_model/validations/with.rb0000644000175000017500000001144312247654710022454 0ustar ondrejondrejmodule ActiveModel module Validations module HelperMethods private def _merge_attributes(attr_names) options = attr_names.extract_options! options.merge(:attributes => attr_names.flatten) end end class WithValidator < EachValidator def validate_each(record, attr, val) method_name = options[:with] if record.method(method_name).arity == 0 record.send method_name else record.send method_name, attr end end end module ClassMethods # Passes the record off to the class or classes specified and allows them # to add errors based on more complex conditions. # # class Person # include ActiveModel::Validations # validates_with MyValidator # end # # class MyValidator < ActiveModel::Validator # def validate(record) # if some_complex_logic # record.errors.add :base, "This record is invalid" # end # end # # private # def some_complex_logic # # ... # end # end # # You may also pass it multiple classes, like so: # # class Person # include ActiveModel::Validations # validates_with MyValidator, MyOtherValidator, :on => :create # end # # Configuration options: # * :on - Specifies when this validation is active # (:create or :update # * :if - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. :if => :allow_validation, # or :if => Proc.new { |user| user.signup_step > 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine # if the validation should not occur (e.g. :unless => :skip_validation, # or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. # If you pass any additional configuration options, they will be passed # to the class and available as options: # # class Person # include ActiveModel::Validations # validates_with MyValidator, :my_custom_key => "my custom value" # end # # class MyValidator < ActiveModel::Validator # def validate(record) # options[:my_custom_key] # => "my custom value" # end # end def validates_with(*args, &block) options = args.extract_options! args.each do |klass| validator = klass.new(options, &block) validator.setup(self) if validator.respond_to?(:setup) if validator.respond_to?(:attributes) && !validator.attributes.empty? validator.attributes.each do |attribute| _validators[attribute.to_sym] << validator end else _validators[nil] << validator end validate(validator, options) end end end # Passes the record off to the class or classes specified and allows them # to add errors based on more complex conditions. # # class Person # include ActiveModel::Validations # # validate :instance_validations # # def instance_validations # validates_with MyValidator # end # end # # Please consult the class method documentation for more information on # creating your own validator. # # You may also pass it multiple classes, like so: # # class Person # include ActiveModel::Validations # # validate :instance_validations, :on => :create # # def instance_validations # validates_with MyValidator, MyOtherValidator # end # end # # Standard configuration options (:on, :if and :unless), which are # available on the class version of validates_with, should instead be # placed on the validates method as these are applied and tested # in the callback. # # If you pass any additional configuration options, they will be passed # to the class and available as options, please refer to the # class version of this method for more information. def validates_with(*args, &block) options = args.extract_options! args.each do |klass| validator = klass.new(options, &block) validator.validate(self) end end end end activemodel-3.2.16/lib/active_model/validations/format.rb0000644000175000017500000001155712247654710022777 0ustar ondrejondrejmodule ActiveModel # == Active Model Format Validator module Validations class FormatValidator < EachValidator def validate_each(record, attribute, value) if options[:with] regexp = option_call(record, :with) record_error(record, attribute, :with, value) if value.to_s !~ regexp elsif options[:without] regexp = option_call(record, :without) record_error(record, attribute, :without, value) if value.to_s =~ regexp end end def check_validity! unless options.include?(:with) ^ options.include?(:without) # ^ == xor, or "exclusive or" raise ArgumentError, "Either :with or :without must be supplied (but not both)" end check_options_validity(options, :with) check_options_validity(options, :without) end private def option_call(record, name) option = options[name] option.respond_to?(:call) ? option.call(record) : option end def record_error(record, attribute, name, value) record.errors.add(attribute, :invalid, options.except(name).merge!(:value => value)) end def check_options_validity(options, name) option = options[name] if option && !option.is_a?(Regexp) && !option.respond_to?(:call) raise ArgumentError, "A regular expression or a proc or lambda must be supplied as :#{name}" end end end module HelperMethods # Validates whether the value of the specified attribute is of the correct form, # going by the regular expression provided. You can require that the attribute # matches the regular expression: # # class Person < ActiveRecord::Base # validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create # end # # Alternatively, you can require that the specified attribute does _not_ match # the regular expression: # # class Person < ActiveRecord::Base # validates_format_of :email, :without => /NOSPAM/ # end # # You can also provide a proc or lambda which will determine the regular # expression that will be used to validate the attribute. # # class Person < ActiveRecord::Base # # Admin can have number as a first letter in their screen name # validates_format_of :screen_name, # :with => lambda{ |person| person.admin? ? /\A[a-z0-9][a-z0-9_\-]*\Z/i : /\A[a-z][a-z0-9_\-]*\Z/i } # end # # Note: use \A and \Z to match the start and end of the string, # ^ and $ match the start/end of a line. # # You must pass either :with or :without as an option. In # addition, both must be a regular expression or a proc or lambda, or else an # exception will be raised. # # Configuration options: # * :message - A custom error message (default is: "is invalid"). # * :allow_nil - If set to true, skips this validation if the attribute # is +nil+ (default is +false+). # * :allow_blank - If set to true, skips this validation if the # attribute is blank (default is +false+). # * :with - Regular expression that if the attribute matches will # result in a successful validation. This can be provided as a proc or lambda # returning regular expression which will be called at runtime. # * :without - Regular expression that if the attribute does not match # will result in a successful validation. This can be provided as a proc or # lambda returning regular expression which will be called at runtime. # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :if - Specifies a method, proc or string to call to determine if the # validation should occur (e.g. :if => :allow_validation, or # :if => Proc.new { |user| user.signup_step > 2 }). The method, proc # or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine if # the validation should not occur (e.g. :unless => :skip_validation, # or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. def validates_format_of(*attr_names) validates_with FormatValidator, _merge_attributes(attr_names) end end end end activemodel-3.2.16/lib/active_model/validations/length.rb0000644000175000017500000001367712247654710022775 0ustar ondrejondrejrequire "active_support/core_ext/string/encoding" module ActiveModel # == Active Model Length Validator module Validations class LengthValidator < EachValidator MESSAGES = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }.freeze CHECKS = { :is => :==, :minimum => :>=, :maximum => :<= }.freeze RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :tokenizer, :too_short, :too_long] def initialize(options) if range = (options.delete(:in) || options.delete(:within)) raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range) options[:minimum], options[:maximum] = range.begin, range.end options[:maximum] -= 1 if range.exclude_end? end super end def check_validity! keys = CHECKS.keys & options.keys if keys.empty? raise ArgumentError, 'Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option.' end keys.each do |key| value = options[key] unless value.is_a?(Integer) && value >= 0 raise ArgumentError, ":#{key} must be a nonnegative Integer" end end end def validate_each(record, attribute, value) value = tokenize(value) value_length = value.respond_to?(:length) ? value.length : value.to_s.length CHECKS.each do |key, validity_check| next unless check_value = options[key] next if value_length.send(validity_check, check_value) errors_options = options.except(*RESERVED_OPTIONS) errors_options[:count] = check_value default_message = options[MESSAGES[key]] errors_options[:message] ||= default_message if default_message record.errors.add(attribute, MESSAGES[key], errors_options) end end private def tokenize(value) if value.kind_of?(String) if options[:tokenizer] options[:tokenizer].call(value) elsif !value.encoding_aware? value.mb_chars end end || value end end module HelperMethods # Validates that the specified attribute matches the length restrictions supplied. # Only one option can be used at a time: # # class Person < ActiveRecord::Base # validates_length_of :first_name, :maximum => 30 # validates_length_of :last_name, :maximum => 30, :message => "less than 30 if you don't mind" # validates_length_of :fax, :in => 7..32, :allow_nil => true # validates_length_of :phone, :in => 7..32, :allow_blank => true # validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name" # validates_length_of :zip_code, :minimum => 5, :too_short => "please enter at least 5 characters" # validates_length_of :smurf_leader, :is => 4, :message => "papa is spelled with 4 characters... don't play me." # validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least 100 words.", # :tokenizer => lambda { |str| str.scan(/\w+/) } # end # # Configuration options: # * :minimum - The minimum size of the attribute. # * :maximum - The maximum size of the attribute. # * :is - The exact size of the attribute. # * :within - A range specifying the minimum and maximum size of the # attribute. # * :in - A synonym(or alias) for :within. # * :allow_nil - Attribute may be +nil+; skip validation. # * :allow_blank - Attribute may be blank; skip validation. # * :too_long - The error message if the attribute goes over the # maximum (default is: "is too long (maximum is %{count} characters)"). # * :too_short - The error message if the attribute goes under the # minimum (default is: "is too short (min is %{count} characters)"). # * :wrong_length - The error message if using the :is method # and the attribute is the wrong size (default is: "is the wrong length # should be %{count} characters)"). # * :message - The error message to use for a :minimum, # :maximum, or :is violation. An alias of the appropriate # too_long/too_short/wrong_length message. # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :if - Specifies a method, proc or string to call to determine if # the validation should occur (e.g. :if => :allow_validation, or # :if => Proc.new { |user| user.signup_step > 2 }). The method, proc # or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine # if the validation should not occur (e.g. :unless => :skip_validation, # or :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. # * :tokenizer - Specifies how to split up the attribute string. # (e.g. :tokenizer => lambda {|str| str.scan(/\w+/)} to count words # as in above example). Defaults to lambda{ |value| value.split(//) } which counts individual characters. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. def validates_length_of(*attr_names) validates_with LengthValidator, _merge_attributes(attr_names) end alias_method :validates_size_of, :validates_length_of end end end activemodel-3.2.16/lib/active_model/validations/confirmation.rb0000644000175000017500000000601512247654710024170 0ustar ondrejondrejmodule ActiveModel # == Active Model Confirmation Validator module Validations class ConfirmationValidator < EachValidator def validate_each(record, attribute, value) if (confirmed = record.send("#{attribute}_confirmation")) && (value != confirmed) record.errors.add(attribute, :confirmation, options) end end def setup(klass) klass.send(:attr_accessor, *attributes.map do |attribute| :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation") end.compact) end end module HelperMethods # Encapsulates the pattern of wanting to validate a password or email # address field with a confirmation. For example: # # Model: # class Person < ActiveRecord::Base # validates_confirmation_of :user_name, :password # validates_confirmation_of :email_address, # :message => "should match confirmation" # end # # View: # <%= password_field "person", "password" %> # <%= password_field "person", "password_confirmation" %> # # The added +password_confirmation+ attribute is virtual; it exists only # as an in-memory attribute for validating the password. To achieve this, # the validation adds accessors to the model for the confirmation # attribute. # # NOTE: This check is performed only if +password_confirmation+ is not # +nil+, and by default only on save. To require confirmation, make sure # to add a presence check for the confirmation attribute: # # validates_presence_of :password_confirmation, :if => :password_changed? # # Configuration options: # * :message - A custom error message (default is: "doesn't match # confirmation"). # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :if - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. :if => :allow_validation, # or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false # value. # * :unless - Specifies a method, proc or string to call to # determine if the validation should not occur (e.g. # :unless => :skip_validation, or # :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. def validates_confirmation_of(*attr_names) validates_with ConfirmationValidator, _merge_attributes(attr_names) end end end end activemodel-3.2.16/lib/active_model/validations/numericality.rb0000644000175000017500000001340612247654710024207 0ustar ondrejondrejmodule ActiveModel # == Active Model Numericality Validator module Validations class NumericalityValidator < EachValidator CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=, :equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=, :odd => :odd?, :even => :even? }.freeze RESERVED_OPTIONS = CHECKS.keys + [:only_integer] def check_validity! keys = CHECKS.keys - [:odd, :even] options.slice(*keys).each do |option, value| next if value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol) raise ArgumentError, ":#{option} must be a number, a symbol or a proc" end end def validate_each(record, attr_name, value) before_type_cast = "#{attr_name}_before_type_cast" raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast.to_sym) raw_value ||= value return if options[:allow_nil] && raw_value.nil? unless value = parse_raw_value_as_a_number(raw_value) record.errors.add(attr_name, :not_a_number, filtered_options(raw_value)) return end if options[:only_integer] unless value = parse_raw_value_as_an_integer(raw_value) record.errors.add(attr_name, :not_an_integer, filtered_options(raw_value)) return end end options.slice(*CHECKS.keys).each do |option, option_value| case option when :odd, :even unless value.to_i.send(CHECKS[option]) record.errors.add(attr_name, option, filtered_options(value)) end else option_value = option_value.call(record) if option_value.is_a?(Proc) option_value = record.send(option_value) if option_value.is_a?(Symbol) unless value.send(CHECKS[option], option_value) record.errors.add(attr_name, option, filtered_options(value).merge(:count => option_value)) end end end end protected def parse_raw_value_as_a_number(raw_value) case raw_value when /\A0[xX]/ nil else begin Kernel.Float(raw_value) rescue ArgumentError, TypeError nil end end end def parse_raw_value_as_an_integer(raw_value) raw_value.to_i if raw_value.to_s =~ /\A[+-]?\d+\Z/ end def filtered_options(value) options.except(*RESERVED_OPTIONS).merge!(:value => value) end end module HelperMethods # Validates whether the value of the specified attribute is numeric by trying to convert it to # a float with Kernel.Float (if only_integer is false) or applying it to the regular expression # /\A[\+\-]?\d+\Z/ (if only_integer is set to true). # # class Person < ActiveRecord::Base # validates_numericality_of :value, :on => :create # end # # Configuration options: # * :message - A custom error message (default is: "is not a number"). # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :only_integer - Specifies whether the value has to be an integer, e.g. an integral value (default is +false+). # * :allow_nil - Skip validation if attribute is +nil+ (default is # +false+). Notice that for fixnum and float columns empty strings are # converted to +nil+. # * :greater_than - Specifies the value must be greater than the # supplied value. # * :greater_than_or_equal_to - Specifies the value must be greater # than or equal the supplied value. # * :equal_to - Specifies the value must be equal to the supplied value. # * :less_than - Specifies the value must be less than the supplied # value. # * :less_than_or_equal_to - Specifies the value must be less than # or equal the supplied value. # * :odd - Specifies the value must be an odd number. # * :even - Specifies the value must be an even number. # * :if - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. :if => :allow_validation, # or :if => Proc.new { |user| user.signup_step > 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine # if the validation should not occur (e.g. :unless => :skip_validation, # or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. # # The following checks can also be supplied with a proc or a symbol which corresponds to a method: # * :greater_than # * :greater_than_or_equal_to # * :equal_to # * :less_than # * :less_than_or_equal_to # # For example: # # class Person < ActiveRecord::Base # validates_numericality_of :width, :less_than => Proc.new { |person| person.height } # validates_numericality_of :width, :greater_than => :minimum_weight # end def validates_numericality_of(*attr_names) validates_with NumericalityValidator, _merge_attributes(attr_names) end end end end activemodel-3.2.16/lib/active_model/validations/callbacks.rb0000644000175000017500000000352012247654710023415 0ustar ondrejondrejrequire 'active_support/callbacks' module ActiveModel module Validations module Callbacks # == Active Model Validation callbacks # # Provides an interface for any class to have before_validation and # after_validation callbacks. # # First, extend ActiveModel::Callbacks from the class you are creating: # # class MyModel # include ActiveModel::Validations::Callbacks # # before_validation :do_stuff_before_validation # after_validation :do_stuff_after_validation # end # # Like other before_* callbacks if before_validation returns false # then valid? will not be called. extend ActiveSupport::Concern included do include ActiveSupport::Callbacks define_callbacks :validation, :terminator => "result == false", :scope => [:kind, :name] end module ClassMethods def before_validation(*args, &block) options = args.last if options.is_a?(Hash) && options[:on] options[:if] = Array.wrap(options[:if]) options[:if].unshift("self.validation_context == :#{options[:on]}") end set_callback(:validation, :before, *args, &block) end def after_validation(*args, &block) options = args.extract_options! options[:prepend] = true options[:if] = Array.wrap(options[:if]) options[:if] << "!halted" options[:if].unshift("self.validation_context == :#{options[:on]}") if options[:on] set_callback(:validation, :after, *(args << options), &block) end end protected # Overwrite run validations to include callbacks. def run_validations! run_callbacks(:validation) { super } end end end end activemodel-3.2.16/lib/active_model/validations/presence.rb0000644000175000017500000000432312247654710023304 0ustar ondrejondrejrequire 'active_support/core_ext/object/blank' module ActiveModel # == Active Model Presence Validator module Validations class PresenceValidator < EachValidator def validate(record) record.errors.add_on_blank(attributes, options) end end module HelperMethods # Validates that the specified attributes are not blank (as defined by # Object#blank?). Happens by default on save. Example: # # class Person < ActiveRecord::Base # validates_presence_of :first_name # end # # The first_name attribute must be in the object and it cannot be blank. # # If you want to validate the presence of a boolean field (where the real values # are true and false), you will want to use validates_inclusion_of :field_name, # :in => [true, false]. # # This is due to the way Object#blank? handles boolean values: # false.blank? # => true. # # Configuration options: # * :message - A custom error message (default is: "can't be blank"). # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :if - Specifies a method, proc or string to call to determine if # the validation should occur (e.g. :if => :allow_validation, or # :if => Proc.new { |user| user.signup_step > 2 }). The method, proc # or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine # if the validation should not occur (e.g. :unless => :skip_validation, # or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. def validates_presence_of(*attr_names) validates_with PresenceValidator, _merge_attributes(attr_names) end end end end activemodel-3.2.16/lib/active_model/validations/validates.rb0000644000175000017500000001252312247654710023455 0ustar ondrejondrejrequire 'active_support/core_ext/hash/slice' module ActiveModel # == Active Model validates method module Validations module ClassMethods # This method is a shortcut to all default validators and any custom # validator classes ending in 'Validator'. Note that Rails default # validators can be overridden inside specific classes by creating # custom validator classes in their place such as PresenceValidator. # # Examples of using the default rails validators: # # validates :terms, :acceptance => true # validates :password, :confirmation => true # validates :username, :exclusion => { :in => %w(admin superuser) } # validates :email, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create } # validates :age, :inclusion => { :in => 0..9 } # validates :first_name, :length => { :maximum => 30 } # validates :age, :numericality => true # validates :username, :presence => true # validates :username, :uniqueness => true # # The power of the +validates+ method comes when using custom validators # and default validators in one call for a given attribute e.g. # # class EmailValidator < ActiveModel::EachValidator # def validate_each(record, attribute, value) # record.errors.add attribute, (options[:message] || "is not an email") unless # value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i # end # end # # class Person # include ActiveModel::Validations # attr_accessor :name, :email # # validates :name, :presence => true, :uniqueness => true, :length => { :maximum => 100 } # validates :email, :presence => true, :email => true # end # # Validator classes may also exist within the class being validated # allowing custom modules of validators to be included as needed e.g. # # class Film # include ActiveModel::Validations # # class TitleValidator < ActiveModel::EachValidator # def validate_each(record, attribute, value) # record.errors.add attribute, "must start with 'the'" unless value =~ /\Athe/i # end # end # # validates :name, :title => true # end # # Additionally validator classes may be in another namespace and still used within any class. # # validates :name, :'film/title' => true # # The validators hash can also handle regular expressions, ranges, # arrays and strings in shortcut form, e.g. # # validates :email, :format => /@/ # validates :gender, :inclusion => %w(male female) # validates :password, :length => 6..20 # # When using shortcut form, ranges and arrays are passed to your # validator's initializer as +options[:in]+ while other types including # regular expressions and strings are passed as +options[:with]+ # # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+ and +:strict+ # can be given to one specific validator, as a hash: # # validates :password, :presence => { :if => :password_required? }, :confirmation => true # # Or to all at the same time: # # validates :password, :presence => true, :confirmation => true, :if => :password_required? # def validates(*attributes) defaults = attributes.extract_options! validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults.merge!(:attributes => attributes) validations.each do |key, options| key = "#{key.to_s.camelize}Validator" begin validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end validates_with(validator, defaults.merge(_parse_validates_options(options))) end end # This method is used to define validation that cannot be corrected by end # user and is considered exceptional. So each validator defined with bang # or :strict option set to true will always raise # ActiveModel::StrictValidationFailed instead of adding error # when validation fails. # See validates for more information about validation itself. def validates!(*attributes) options = attributes.extract_options! options[:strict] = true validates(*(attributes << options)) end protected # When creating custom validators, it might be useful to be able to specify # additional default keys. This can be done by overwriting this method. def _validates_default_keys [:if, :unless, :on, :allow_blank, :allow_nil , :strict] end def _parse_validates_options(options) #:nodoc: case options when TrueClass {} when Hash options when Range, Array { :in => options } else { :with => options } end end end end end activemodel-3.2.16/lib/active_model/validations/inclusion.rb0000644000175000017500000000744612247654710023514 0ustar ondrejondrejrequire 'active_support/core_ext/range' module ActiveModel # == Active Model Inclusion Validator module Validations class InclusionValidator < EachValidator ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " << "and must be supplied as the :in (or :within) option of the configuration hash" def check_validity! unless [:include?, :call].any?{ |method| delimiter.respond_to?(method) } raise ArgumentError, ERROR_MESSAGE end end def validate_each(record, attribute, value) exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter unless exclusions.send(inclusion_method(exclusions), value) record.errors.add(attribute, :inclusion, options.except(:in, :within).merge!(:value => value)) end end private def delimiter @delimiter ||= options[:in] || options[:within] end # In Ruby 1.9 Range#include? on non-numeric ranges checks all possible # values in the range for equality, so it may be slow for large ranges. The new # Range#cover? uses the previous logic of comparing a value with the # range endpoints. def inclusion_method(enumerable) enumerable.is_a?(Range) ? :cover? : :include? end end module HelperMethods # Validates whether the value of the specified attribute is available in a # particular enumerable object. # # class Person < ActiveRecord::Base # validates_inclusion_of :gender, :in => %w( m f ) # validates_inclusion_of :age, :in => 0..99 # validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %{value} is not included in the list" # validates_inclusion_of :states, :in => lambda{ |person| STATES[person.country] } # end # # Configuration options: # * :in - An enumerable object of available items. This can be # supplied as a proc or lambda which returns an enumerable. If the enumerable # is a range the test is performed with Range#cover? # (backported in Active Support for 1.8), otherwise with include?. # * :within - A synonym(or alias) for :in # * :message - Specifies a custom error message (default is: "is not # included in the list"). # * :allow_nil - If set to true, skips this validation if the attribute # is +nil+ (default is +false+). # * :allow_blank - If set to true, skips this validation if the # attribute is blank (default is +false+). # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :if - Specifies a method, proc or string to call to determine if # the validation should occur (e.g. :if => :allow_validation, or # :if => Proc.new { |user| user.signup_step > 2 }). The method, proc # or string should return or evaluate to a true or false value. # * :unless - Specifies a method, proc or string to call to determine # if the validation should not occur (e.g. :unless => :skip_validation, # or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, # proc or string should return or evaluate to a true or false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. def validates_inclusion_of(*attr_names) validates_with InclusionValidator, _merge_attributes(attr_names) end end end end activemodel-3.2.16/lib/active_model/validations/acceptance.rb0000644000175000017500000000603712247654710023572 0ustar ondrejondrejmodule ActiveModel # == Active Model Acceptance Validator module Validations class AcceptanceValidator < EachValidator def initialize(options) super(options.reverse_merge(:allow_nil => true, :accept => "1")) end def validate_each(record, attribute, value) unless value == options[:accept] record.errors.add(attribute, :accepted, options.except(:accept, :allow_nil)) end end def setup(klass) attr_readers = attributes.reject { |name| klass.attribute_method?(name) } attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") } klass.send(:attr_reader, *attr_readers) klass.send(:attr_writer, *attr_writers) end end module HelperMethods # Encapsulates the pattern of wanting to validate the acceptance of a # terms of service check box (or similar agreement). Example: # # class Person < ActiveRecord::Base # validates_acceptance_of :terms_of_service # validates_acceptance_of :eula, :message => "must be abided" # end # # If the database column does not exist, the +terms_of_service+ attribute # is entirely virtual. This check is performed only if +terms_of_service+ # is not +nil+ and by default on save. # # Configuration options: # * :message - A custom error message (default is: "must be # accepted"). # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. # * :allow_nil - Skip validation if attribute is +nil+ (default # is true). # * :accept - Specifies value that is considered accepted. # The default value is a string "1", which makes it easy to relate to # an HTML checkbox. This should be set to +true+ if you are validating # a database column, since the attribute is typecast from "1" to +true+ # before validation. # * :if - Specifies a method, proc or string to call to determine # if the validation should occur (e.g. :if => :allow_validation, # or :if => Proc.new { |user| user.signup_step > 2 }). The # method, proc or string should return or evaluate to a true or false # value. # * :unless - Specifies a method, proc or string to call to # determine if the validation should not occur (for example, # :unless => :skip_validation, or # :unless => Proc.new { |user| user.signup_step <= 2 }). # The method, proc or string should return or evaluate to a true or # false value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. def validates_acceptance_of(*attr_names) validates_with AcceptanceValidator, _merge_attributes(attr_names) end end end end activemodel-3.2.16/lib/active_model/serializers/0000755000175000017500000000000012247654710021170 5ustar ondrejondrejactivemodel-3.2.16/lib/active_model/serializers/json.rb0000644000175000017500000001032212247654710022464 0ustar ondrejondrejrequire 'active_support/json' require 'active_support/core_ext/class/attribute' module ActiveModel module Serializers # == Active Model JSON Serializer module JSON extend ActiveSupport::Concern include ActiveModel::Serialization included do extend ActiveModel::Naming class_attribute :include_root_in_json self.include_root_in_json = true end # Returns a hash representing the model. Some configuration can be # passed through +options+. # # The option include_root_in_json controls the top-level behavior # of +as_json+. If true (the default) +as_json+ will emit a single root # node named after the object's type. For example: # # user = User.find(1) # user.as_json # # => { "user": {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true} } # # ActiveRecord::Base.include_root_in_json = false # user.as_json # # => {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true} # # This behavior can also be achieved by setting the :root option to +false+ as in: # # user = User.find(1) # user.as_json(root: false) # # => {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true} # # The remainder of the examples in this section assume include_root_in_json is set to # false. # # Without any +options+, the returned Hash will include all the model's # attributes. For example: # # user = User.find(1) # user.as_json # # => {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true} # # The :only and :except options can be used to limit the attributes # included, and work similar to the +attributes+ method. For example: # # user.as_json(:only => [ :id, :name ]) # # => {"id": 1, "name": "Konata Izumi"} # # user.as_json(:except => [ :id, :created_at, :age ]) # # => {"name": "Konata Izumi", "awesome": true} # # To include the result of some method calls on the model use :methods: # # user.as_json(:methods => :permalink) # # => {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true, # "permalink": "1-konata-izumi"} # # To include associations use :include: # # user.as_json(:include => :posts) # # => {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true, # "posts": [{"id": 1, "author_id": 1, "title": "Welcome to the weblog"}, # {"id": 2, author_id: 1, "title": "So I was thinking"}]} # # Second level and higher order associations work as well: # # user.as_json(:include => { :posts => { # :include => { :comments => { # :only => :body } }, # :only => :title } }) # # => {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true, # "posts": [{"comments": [{"body": "1st post!"}, {"body": "Second!"}], # "title": "Welcome to the weblog"}, # {"comments": [{"body": "Don't think too hard"}], # "title": "So I was thinking"}]} def as_json(options = nil) root = include_root_in_json root = options[:root] if options.try(:key?, :root) if root root = self.class.model_name.element if root == true { root => serializable_hash(options) } else serializable_hash(options) end end def from_json(json, include_root=include_root_in_json) hash = ActiveSupport::JSON.decode(json) hash = hash.values.first if include_root self.attributes = hash self end end end end activemodel-3.2.16/lib/active_model/serializers/xml.rb0000644000175000017500000001470212247654710022321 0ustar ondrejondrejrequire 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/hash/conversions' require 'active_support/core_ext/hash/slice' module ActiveModel module Serializers # == Active Model XML Serializer module Xml extend ActiveSupport::Concern include ActiveModel::Serialization included do extend ActiveModel::Naming end class Serializer #:nodoc: class Attribute #:nodoc: attr_reader :name, :value, :type def initialize(name, serializable, value) @name, @serializable = name, serializable value = value.in_time_zone if value.respond_to?(:in_time_zone) @value = value @type = compute_type end def decorations decorations = {} decorations[:encoding] = 'base64' if type == :binary decorations[:type] = (type == :string) ? nil : type decorations[:nil] = true if value.nil? decorations end protected def compute_type return if value.nil? type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name] type ||= :string if value.respond_to?(:to_str) type ||= :yaml type end end class MethodAttribute < Attribute #:nodoc: end attr_reader :options def initialize(serializable, options = nil) @serializable = serializable @options = options ? options.dup : {} end def serializable_hash @serializable.serializable_hash(@options.except(:include)) end def serializable_collection methods = Array.wrap(options[:methods]).map(&:to_s) serializable_hash.map do |name, value| name = name.to_s if methods.include?(name) self.class::MethodAttribute.new(name, @serializable, value) else self.class::Attribute.new(name, @serializable, value) end end end def serialize require 'builder' unless defined? ::Builder options[:indent] ||= 2 options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent]) @builder = options[:builder] @builder.instruct! unless options[:skip_instruct] root = (options[:root] || @serializable.class.model_name.element).to_s root = ActiveSupport::XmlMini.rename_key(root, options) args = [root] args << {:xmlns => options[:namespace]} if options[:namespace] args << {:type => options[:type]} if options[:type] && !options[:skip_types] @builder.tag!(*args) do add_attributes_and_methods add_includes add_extra_behavior add_procs yield @builder if block_given? end end private def add_extra_behavior end def add_attributes_and_methods serializable_collection.each do |attribute| key = ActiveSupport::XmlMini.rename_key(attribute.name, options) ActiveSupport::XmlMini.to_tag(key, attribute.value, options.merge(attribute.decorations)) end end def add_includes @serializable.send(:serializable_add_includes, options) do |association, records, opts| add_associations(association, records, opts) end end # TODO This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well. def add_associations(association, records, opts) merged_options = opts.merge(options.slice(:builder, :indent)) merged_options[:skip_instruct] = true if records.is_a?(Enumerable) tag = ActiveSupport::XmlMini.rename_key(association.to_s, options) type = options[:skip_types] ? { } : {:type => "array"} association_name = association.to_s.singularize merged_options[:root] = association_name if records.empty? @builder.tag!(tag, type) else @builder.tag!(tag, type) do records.each do |record| if options[:skip_types] record_type = {} else record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name record_type = {:type => record_class} end record.to_xml merged_options.merge(record_type) end end end else merged_options[:root] = association.to_s unless records.class.to_s.underscore == association.to_s merged_options[:type] = records.class.name end records.to_xml merged_options end end def add_procs if procs = options.delete(:procs) Array.wrap(procs).each do |proc| if proc.arity == 1 proc.call(options) else proc.call(options, @serializable) end end end end end # Returns XML representing the model. Configuration can be # passed through +options+. # # Without any +options+, the returned XML string will include all the model's # attributes. For example: # # user = User.find(1) # user.to_xml # # # # 1 # David # 16 # 2011-01-30T22:29:23Z # # # The :only and :except options can be used to limit the attributes # included, and work similar to the +attributes+ method. # # To include the result of some method calls on the model use :methods. # # To include associations use :include. # # For further documentation see activerecord/lib/active_record/serializers/xml_serializer.xml. def to_xml(options = {}, &block) Serializer.new(self, options).serialize(&block) end def from_xml(xml) self.attributes = Hash.from_xml(xml).values.first self end end end end activemodel-3.2.16/lib/active_model/test_case.rb0000644000175000017500000000047712247654710021143 0ustar ondrejondrejmodule ActiveModel #:nodoc: class TestCase < ActiveSupport::TestCase #:nodoc: def with_kcode(kcode) if RUBY_VERSION < '1.9' orig_kcode, $KCODE = $KCODE, kcode begin yield ensure $KCODE = orig_kcode end else yield end end end end activemodel-3.2.16/lib/active_model/observing.rb0000644000175000017500000001774312247654710021173 0ustar ondrejondrejrequire 'singleton' require 'active_model/observer_array' require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/module/remove_method' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/enumerable' require 'active_support/descendants_tracker' module ActiveModel module Observing extend ActiveSupport::Concern included do extend ActiveSupport::DescendantsTracker end module ClassMethods # == Active Model Observers Activation # # Activates the observers assigned. Examples: # # class ORM # include ActiveModel::Observing # end # # # Calls PersonObserver.instance # ORM.observers = :person_observer # # # Calls Cacher.instance and GarbageCollector.instance # ORM.observers = :cacher, :garbage_collector # # # Same as above, just using explicit class references # ORM.observers = Cacher, GarbageCollector # # Note: Setting this does not instantiate the observers yet. # +instantiate_observers+ is called during startup, and before # each development request. def observers=(*values) observers.replace(values.flatten) end # Gets an array of observers observing this model. # The array also provides +enable+ and +disable+ methods # that allow you to selectively enable and disable observers. # (see ActiveModel::ObserverArray.enable and # ActiveModel::ObserverArray.disable for more on this) def observers @observers ||= ObserverArray.new(self) end # Gets the current observer instances. def observer_instances @observer_instances ||= [] end # Instantiate the global observers. def instantiate_observers observers.each { |o| instantiate_observer(o) } end # Add a new observer to the pool. # The new observer needs to respond to 'update', otherwise it # raises an +ArgumentError+ exception. def add_observer(observer) unless observer.respond_to? :update raise ArgumentError, "observer needs to respond to `update'" end observer_instances << observer end # Notify list of observers of a change. def notify_observers(*arg) observer_instances.each { |observer| observer.update(*arg) } end # Total number of observers. def count_observers observer_instances.size end protected def instantiate_observer(observer) #:nodoc: # string/symbol if observer.respond_to?(:to_sym) observer.to_s.camelize.constantize.instance elsif observer.respond_to?(:instance) observer.instance else raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an " + "instance of the class itself) responding to the instance " + "method. Example: Person.observers = :big_brother # calls " + "BigBrother.instance" end end # Notify observers when the observed class is subclassed. def inherited(subclass) super notify_observers :observed_class_inherited, subclass end end private # Fires notifications to model's observers # # def save # notify_observers(:before_save) # ... # notify_observers(:after_save) # end def notify_observers(method) self.class.notify_observers(method, self) end end # == Active Model Observers # # Observer classes respond to life cycle callbacks to implement trigger-like # behavior outside the original class. This is a great way to reduce the # clutter that normally comes when the model class is burdened with # functionality that doesn't pertain to the core responsibility of the # class. Example: # # class CommentObserver < ActiveModel::Observer # def after_save(comment) # Notifications.comment("admin@do.com", "New comment was posted", comment).deliver # end # end # # This Observer sends an email when a Comment#save is finished. # # class ContactObserver < ActiveModel::Observer # def after_create(contact) # contact.logger.info('New contact added!') # end # # def after_destroy(contact) # contact.logger.warn("Contact with an id of #{contact.id} was destroyed!") # end # end # # This Observer uses logger to log when specific callbacks are triggered. # # == Observing a class that can't be inferred # # Observers will by default be mapped to the class with which they share a # name. So CommentObserver will be tied to observing Comment, ProductManagerObserver # to ProductManager, and so on. If you want to name your observer differently than # the class you're interested in observing, you can use the Observer.observe # class method which takes either the concrete class (Product) or a symbol for that # class (:product): # # class AuditObserver < ActiveModel::Observer # observe :account # # def after_update(account) # AuditTrail.new(account, "UPDATED") # end # end # # If the audit observer needs to watch more than one kind of object, this can be # specified with multiple arguments: # # class AuditObserver < ActiveModel::Observer # observe :account, :balance # # def after_update(record) # AuditTrail.new(record, "UPDATED") # end # end # # The AuditObserver will now act on both updates to Account and Balance by treating # them both as records. # # If you're using an Observer in a Rails application with Active Record, be sure to # read about the necessary configuration in the documentation for # ActiveRecord::Observer. # class Observer include Singleton extend ActiveSupport::DescendantsTracker class << self # Attaches the observer to the supplied model classes. def observe(*models) models.flatten! models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model } redefine_method(:observed_classes) { models } end # Returns an array of Classes to observe. # # You can override this instead of using the +observe+ helper. # # class AuditObserver < ActiveModel::Observer # def self.observed_classes # [Account, Balance] # end # end def observed_classes Array.wrap(observed_class) end # The class observed by default is inferred from the observer's class name: # assert_equal Person, PersonObserver.observed_class def observed_class if observed_class_name = name[/(.*)Observer/, 1] observed_class_name.constantize else nil end end end # Start observing the declared classes and their subclasses. def initialize observed_classes.each { |klass| add_observer!(klass) } end def observed_classes #:nodoc: self.class.observed_classes end # Send observed_method(object) if the method exists and # the observer is enabled for the given object's class. def update(observed_method, object, &block) #:nodoc: return unless respond_to?(observed_method) return if disabled_for?(object) send(observed_method, object, &block) end # Special method sent by the observed class when it is inherited. # Passes the new subclass. def observed_class_inherited(subclass) #:nodoc: self.class.observe(observed_classes + [subclass]) add_observer!(subclass) end protected def add_observer!(klass) #:nodoc: klass.add_observer(self) end def disabled_for?(object) klass = object.class return false unless klass.respond_to?(:observers) klass.observers.disabled_for?(self) end end end activemodel-3.2.16/lib/active_model/serialization.rb0000644000175000017500000001032012247654710022032 0ustar ondrejondrejrequire 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/array/wrap' module ActiveModel # == Active Model Serialization # # Provides a basic serialization to a serializable_hash for your object. # # A minimal implementation could be: # # class Person # # include ActiveModel::Serialization # # attr_accessor :name # # def attributes # {'name' => name} # end # # end # # Which would provide you with: # # person = Person.new # person.serializable_hash # => {"name"=>nil} # person.name = "Bob" # person.serializable_hash # => {"name"=>"Bob"} # # You need to declare some sort of attributes hash which contains the attributes # you want to serialize and their current value. # # Most of the time though, you will want to include the JSON or XML # serializations. Both of these modules automatically include the # ActiveModel::Serialization module, so there is no need to explicitly # include it. # # So a minimal implementation including XML and JSON would be: # # class Person # # include ActiveModel::Serializers::JSON # include ActiveModel::Serializers::Xml # # attr_accessor :name # # def attributes # {'name' => name} # end # # end # # Which would provide you with: # # person = Person.new # person.serializable_hash # => {"name"=>nil} # person.as_json # => {"name"=>nil} # person.to_json # => "{\"name\":null}" # person.to_xml # => "\n {"name"=>"Bob"} # person.as_json # => {"name"=>"Bob"} # person.to_json # => "{\"name\":\"Bob\"}" # person.to_xml # => "\n:only, :except and :methods . module Serialization def serializable_hash(options = nil) options ||= {} attribute_names = attributes.keys.sort if only = options[:only] attribute_names &= Array.wrap(only).map(&:to_s) elsif except = options[:except] attribute_names -= Array.wrap(except).map(&:to_s) end hash = {} attribute_names.each { |n| hash[n] = read_attribute_for_serialization(n) } method_names = Array.wrap(options[:methods]).select { |n| respond_to?(n) } method_names.each { |n| hash[n] = send(n) } serializable_add_includes(options) do |association, records, opts| hash[association] = if records.is_a?(Enumerable) records.map { |a| a.serializable_hash(opts) } else records.serializable_hash(opts) end end hash end private # Hook method defining how an attribute value should be retrieved for # serialization. By default this is assumed to be an instance named after # the attribute. Override this method in subclasses should you need to # retrieve the value for a given attribute differently: # # class MyClass # include ActiveModel::Validations # # def initialize(data = {}) # @data = data # end # # def read_attribute_for_serialization(key) # @data[key] # end # end # alias :read_attribute_for_serialization :send # Add associations specified via the :include option. # # Expects a block that takes as arguments: # +association+ - name of the association # +records+ - the association record(s) to be serialized # +opts+ - options for the association records def serializable_add_includes(options = {}) #:nodoc: return unless include = options[:include] unless include.is_a?(Hash) include = Hash[Array.wrap(include).map { |n| n.is_a?(Hash) ? n.to_a.first : [n, {}] }] end include.each do |association, opts| if records = send(association) yield association, records, opts end end end end end activemodel-3.2.16/lib/active_model/conversion.rb0000644000175000017500000000444212247654710021352 0ustar ondrejondrejrequire 'active_support/concern' require 'active_support/inflector' module ActiveModel # == Active Model Conversions # # Handles default conversions: to_model, to_key, to_param, and to_partial_path. # # Let's take for example this non-persisted object. # # class ContactMessage # include ActiveModel::Conversion # # # ContactMessage are never persisted in the DB # def persisted? # false # end # end # # cm = ContactMessage.new # cm.to_model == self # => true # cm.to_key # => nil # cm.to_param # => nil # cm.to_path # => "contact_messages/contact_message" # module Conversion extend ActiveSupport::Concern # If your object is already designed to implement all of the Active Model # you can use the default :to_model implementation, which simply # returns self. # # If your model does not act like an Active Model object, then you should # define :to_model yourself returning a proxy object that wraps # your object with Active Model compliant methods. def to_model self end # Returns an Enumerable of all key attributes if any is set, regardless # if the object is persisted or not. # # Note the default implementation uses persisted? just because all objects # in Ruby 1.8.x responds to :id. def to_key persisted? ? [id] : nil end # Returns a string representing the object's key suitable for use in URLs, # or nil if persisted? is false. def to_param persisted? ? to_key.join('-') : nil end # Returns a string identifying the path associated with the object. # ActionPack uses this to find a suitable partial to represent the object. def to_partial_path self.class._to_partial_path end module ClassMethods #:nodoc: # Provide a class level cache for the to_path. This is an # internal method and should not be accessed directly. def _to_partial_path #:nodoc: @_to_partial_path ||= begin element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)) collection = ActiveSupport::Inflector.tableize(self) "#{collection}/#{element}".freeze end end end end end activemodel-3.2.16/lib/active_model/errors.rb0000644000175000017500000002747512247654710020514 0ustar ondrejondrej# -*- coding: utf-8 -*- require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/reverse_merge' require 'active_support/ordered_hash' module ActiveModel # == Active Model Errors # # Provides a modified +OrderedHash+ that you can include in your object # for handling error messages and interacting with Action Pack helpers. # # A minimal implementation could be: # # class Person # # # Required dependency for ActiveModel::Errors # extend ActiveModel::Naming # # def initialize # @errors = ActiveModel::Errors.new(self) # end # # attr_accessor :name # attr_reader :errors # # def validate! # errors.add(:name, "can not be nil") if name == nil # end # # # The following methods are needed to be minimally implemented # # def read_attribute_for_validation(attr) # send(attr) # end # # def Person.human_attribute_name(attr, options = {}) # attr # end # # def Person.lookup_ancestors # [self] # end # # end # # The last three methods are required in your object for Errors to be # able to generate error messages correctly and also handle multiple # languages. Of course, if you extend your object with ActiveModel::Translation # you will not need to implement the last two. Likewise, using # ActiveModel::Validations will handle the validation related methods # for you. # # The above allows you to do: # # p = Person.new # p.validate! # => ["can not be nil"] # p.errors.full_messages # => ["name can not be nil"] # # etc.. class Errors include Enumerable CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank, :strict] attr_reader :messages # Pass in the instance of the object that is using the errors object. # # class Person # def initialize # @errors = ActiveModel::Errors.new(self) # end # end def initialize(base) @base = base @messages = ActiveSupport::OrderedHash.new end def initialize_dup(other) @messages = other.messages.dup end # Backport dup from 1.9 so that #initialize_dup gets called unless Object.respond_to?(:initialize_dup, true) def dup # :nodoc: copy = super copy.initialize_dup(self) copy end end # Clear the messages def clear messages.clear end # Do the error messages include an error with key +error+? def include?(error) (v = messages[error]) && v.any? end alias :has_key? :include? # Get messages for +key+ def get(key) messages[key] end # Set messages for +key+ to +value+ def set(key, value) messages[key] = value end # Delete messages for +key+ def delete(key) messages.delete(key) end # When passed a symbol or a name of a method, returns an array of errors # for the method. # # p.errors[:name] # => ["can not be nil"] # p.errors['name'] # => ["can not be nil"] def [](attribute) get(attribute.to_sym) || set(attribute.to_sym, []) end # Adds to the supplied attribute the supplied error message. # # p.errors[:name] = "must be set" # p.errors[:name] # => ['must be set'] def []=(attribute, error) self[attribute] << error end # Iterates through each error key, value pair in the error messages hash. # Yields the attribute and the error for that attribute. If the attribute # has more than one error message, yields once for each error message. # # p.errors.add(:name, "can't be blank") # p.errors.each do |attribute, errors_array| # # Will yield :name and "can't be blank" # end # # p.errors.add(:name, "must be specified") # p.errors.each do |attribute, errors_array| # # Will yield :name and "can't be blank" # # then yield :name and "must be specified" # end def each messages.each_key do |attribute| self[attribute].each { |error| yield attribute, error } end end # Returns the number of error messages. # # p.errors.add(:name, "can't be blank") # p.errors.size # => 1 # p.errors.add(:name, "must be specified") # p.errors.size # => 2 def size values.flatten.size end # Returns all message values def values messages.values end # Returns all message keys def keys messages.keys end # Returns an array of error messages, with the attribute name included # # p.errors.add(:name, "can't be blank") # p.errors.add(:name, "must be specified") # p.errors.to_a # => ["name can't be blank", "name must be specified"] def to_a full_messages end # Returns the number of error messages. # p.errors.add(:name, "can't be blank") # p.errors.count # => 1 # p.errors.add(:name, "must be specified") # p.errors.count # => 2 def count to_a.size end # Returns true if no errors are found, false otherwise. # If the error message is a string it can be empty. def empty? all? { |k, v| v && v.empty? && !v.is_a?(String) } end alias_method :blank?, :empty? # Returns an xml formatted representation of the Errors hash. # # p.errors.add(:name, "can't be blank") # p.errors.add(:name, "must be specified") # p.errors.to_xml # # => # # # # # # name can't be blank # # name must be specified # # def to_xml(options={}) to_a.to_xml options.reverse_merge(:root => "errors", :skip_types => true) end # Returns an ActiveSupport::OrderedHash that can be used as the JSON representation for this object. def as_json(options=nil) to_hash end def to_hash messages.dup end # Adds +message+ to the error messages on +attribute+. More than one error can be added to the same # +attribute+. # If no +message+ is supplied, :invalid is assumed. # # If +message+ is a symbol, it will be translated using the appropriate scope (see +translate_error+). # If +message+ is a proc, it will be called, allowing for things like Time.now to be used within an error. def add(attribute, message = nil, options = {}) message = normalize_message(attribute, message, options) if options[:strict] raise ActiveModel::StrictValidationFailed, full_message(attribute, message) end self[attribute] << message end # Will add an error message to each of the attributes in +attributes+ that is empty. def add_on_empty(attributes, options = {}) [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) is_empty = value.respond_to?(:empty?) ? value.empty? : false add(attribute, :empty, options) if value.nil? || is_empty end end # Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?). def add_on_blank(attributes, options = {}) [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) add(attribute, :blank, options) if value.blank? end end # Returns true if an error on the attribute with the given message is present, false otherwise. # +message+ is treated the same as for +add+. # p.errors.add :name, :blank # p.errors.added? :name, :blank # => true def added?(attribute, message = nil, options = {}) message = normalize_message(attribute, message, options) self[attribute].include? message end # Returns all the full error messages in an array. # # class Company # validates_presence_of :name, :address, :email # validates_length_of :name, :in => 5..30 # end # # company = Company.create(:address => '123 First St.') # company.errors.full_messages # => # ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"] def full_messages map { |attribute, message| full_message(attribute, message) } end # Returns a full message for a given attribute. # # company.errors.full_message(:name, "is invalid") # => # "Name is invalid" def full_message(attribute, message) return message if attribute == :base attr_name = attribute.to_s.gsub('.', '_').humanize attr_name = @base.class.human_attribute_name(attribute, :default => attr_name) I18n.t(:"errors.format", { :default => "%{attribute} %{message}", :attribute => attr_name, :message => message }) end # Translates an error message in its default scope # (activemodel.errors.messages). # # Error messages are first looked up in models.MODEL.attributes.ATTRIBUTE.MESSAGE, # if it's not there, it's looked up in models.MODEL.MESSAGE and if that is not # there also, it returns the translation of the default message # (e.g. activemodel.errors.messages.MESSAGE). The translated model name, # translated attribute name and the value are available for interpolation. # # When using inheritance in your models, it will check all the inherited # models too, but only if the model itself hasn't been found. Say you have # class Admin < User; end and you wanted the translation for # the :blank error message for the title attribute, # it looks for these translations: # # * activemodel.errors.models.admin.attributes.title.blank # * activemodel.errors.models.admin.blank # * activemodel.errors.models.user.attributes.title.blank # * activemodel.errors.models.user.blank # * any default you provided through the +options+ hash (in the activemodel.errors scope) # * activemodel.errors.messages.blank # * errors.attributes.title.blank # * errors.messages.blank # def generate_message(attribute, type = :invalid, options = {}) type = options.delete(:message) if options[:message].is_a?(Symbol) if @base.class.respond_to?(:i18n_scope) defaults = @base.class.lookup_ancestors.map do |klass| [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}", :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}" ] end else defaults = [] end defaults << options.delete(:message) defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}" if @base.class.respond_to?(:i18n_scope) defaults << :"errors.attributes.#{attribute}.#{type}" defaults << :"errors.messages.#{type}" defaults.compact! defaults.flatten! key = defaults.shift value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil) options = { :default => defaults, :model => @base.class.model_name.human, :attribute => @base.class.human_attribute_name(attribute), :value => value }.merge(options) I18n.translate(key, options) end private def normalize_message(attribute, message, options) message ||= :invalid if message.is_a?(Symbol) generate_message(attribute, message, options.except(*CALLBACKS_OPTIONS)) elsif message.is_a?(Proc) message.call else message end end end class StrictValidationFailed < StandardError end end activemodel-3.2.16/lib/active_model/callbacks.rb0000644000175000017500000001071412247654710021103 0ustar ondrejondrejrequire 'active_support/core_ext/array/wrap' require 'active_support/callbacks' module ActiveModel # == Active Model Callbacks # # Provides an interface for any class to have Active Record like callbacks. # # Like the Active Record methods, the callback chain is aborted as soon as # one of the methods in the chain returns false. # # First, extend ActiveModel::Callbacks from the class you are creating: # # class MyModel # extend ActiveModel::Callbacks # end # # Then define a list of methods that you want callbacks attached to: # # define_model_callbacks :create, :update # # This will provide all three standard callbacks (before, around and after) for # both the :create and :update methods. To implement, you need to wrap the methods # you want callbacks on in a block so that the callbacks get a chance to fire: # # def create # run_callbacks :create do # # Your create action methods here # end # end # # Then in your class, you can use the +before_create+, +after_create+ and +around_create+ # methods, just as you would in an Active Record module. # # before_create :action_before_create # # def action_before_create # # Your code here # end # # You can choose not to have all three callbacks by passing a hash to the # define_model_callbacks method. # # define_model_callbacks :create, :only => [:after, :before] # # Would only create the after_create and before_create callback methods in your # class. module Callbacks def self.extended(base) base.class_eval do include ActiveSupport::Callbacks end end # define_model_callbacks accepts the same options define_callbacks does, in case # you want to overwrite a default. Besides that, it also accepts an :only option, # where you can choose if you want all types (before, around or after) or just some. # # define_model_callbacks :initializer, :only => :after # # Note, the :only => hash will apply to all callbacks defined on # that method call. To get around this you can call the define_model_callbacks # method as many times as you need. # # define_model_callbacks :create, :only => :after # define_model_callbacks :update, :only => :before # define_model_callbacks :destroy, :only => :around # # Would create +after_create+, +before_update+ and +around_destroy+ methods only. # # You can pass in a class to before_, after_ and around_, in which # case the callback will call that class's _ method passing the object # that the callback is being called on. # # class MyModel # extend ActiveModel::Callbacks # define_model_callbacks :create # # before_create AnotherClass # end # # class AnotherClass # def self.before_create( obj ) # # obj is the MyModel instance that the callback is being called on # end # end # def define_model_callbacks(*callbacks) options = callbacks.extract_options! options = { :terminator => "result == false", :scope => [:kind, :name], :only => [:before, :around, :after] }.merge(options) types = Array.wrap(options.delete(:only)) callbacks.each do |callback| define_callbacks(callback, options) types.each do |type| send("_define_#{type}_model_callback", self, callback) end end end def _define_before_model_callback(klass, callback) #:nodoc: klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1 def self.before_#{callback}(*args, &block) set_callback(:#{callback}, :before, *args, &block) end CALLBACK end def _define_around_model_callback(klass, callback) #:nodoc: klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1 def self.around_#{callback}(*args, &block) set_callback(:#{callback}, :around, *args, &block) end CALLBACK end def _define_after_model_callback(klass, callback) #:nodoc: klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1 def self.after_#{callback}(*args, &block) options = args.extract_options! options[:prepend] = true options[:if] = Array.wrap(options[:if]) << "!halted && value != false" set_callback(:#{callback}, :after, *(args << options), &block) end CALLBACK end end end activemodel-3.2.16/lib/active_model/attribute_methods.rb0000644000175000017500000004030012247654710022704 0ustar ondrejondrejrequire 'active_support/core_ext/hash/keys' require 'active_support/core_ext/class/attribute' require 'active_support/deprecation' module ActiveModel class MissingAttributeError < NoMethodError end # == Active Model Attribute Methods # # ActiveModel::AttributeMethods provides a way to add prefixes and suffixes # to your methods as well as handling the creation of Active Record like class methods # such as +table_name+. # # The requirements to implement ActiveModel::AttributeMethods are to: # # * include ActiveModel::AttributeMethods in your object # * Call each Attribute Method module method you want to add, such as # attribute_method_suffix or attribute_method_prefix # * Call define_attribute_methods after the other methods are # called. # * Define the various generic +_attribute+ methods that you have declared # # A minimal implementation could be: # # class Person # include ActiveModel::AttributeMethods # # attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!' # attribute_method_suffix '_contrived?' # attribute_method_prefix 'clear_' # define_attribute_methods ['name'] # # attr_accessor :name # # private # # def attribute_contrived?(attr) # true # end # # def clear_attribute(attr) # send("#{attr}=", nil) # end # # def reset_attribute_to_default!(attr) # send("#{attr}=", "Default Name") # end # end # # Note that whenever you include ActiveModel::AttributeMethods in your class, # it requires you to implement an attributes method which returns a hash # with each attribute name in your model as hash key and the attribute value as # hash value. # # Hash keys must be strings. # module AttributeMethods extend ActiveSupport::Concern NAME_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?=]?\z/ CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/ included do class_attribute :attribute_method_matchers, :instance_writer => false self.attribute_method_matchers = [ClassMethods::AttributeMethodMatcher.new] end module ClassMethods def define_attr_method(name, value=nil, deprecation_warning = true, &block) #:nodoc: # This deprecation_warning param is for internal use so that we can silence # the warning from Active Record, because we are implementing more specific # messages there instead. # # It doesn't apply to the original_#{name} method as we want to warn if # people are calling that regardless. if deprecation_warning ActiveSupport::Deprecation.warn("define_attr_method is deprecated and will be removed without replacement.") end sing = singleton_class sing.class_eval <<-eorb, __FILE__, __LINE__ + 1 remove_possible_method :'original_#{name}' remove_possible_method :'_original_#{name}' alias_method :'_original_#{name}', :'#{name}' define_method :'original_#{name}' do ActiveSupport::Deprecation.warn( "This method is generated by ActiveModel::AttributeMethods::ClassMethods#define_attr_method, " \ "which is deprecated and will be removed." ) send(:'_original_#{name}') end eorb if block_given? sing.send :define_method, name, &block else # If we can compile the method name, do it. Otherwise use define_method. # This is an important *optimization*, please don't change it. define_method # has slower dispatch and consumes more memory. if name =~ NAME_COMPILABLE_REGEXP sing.class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{name}; #{value.nil? ? 'nil' : value.to_s.inspect}; end RUBY else value = value.to_s if value sing.send(:define_method, name) { value } end end end # Declares a method available for all attributes with the given prefix. # Uses +method_missing+ and respond_to? to rewrite the method. # # #{prefix}#{attr}(*args, &block) # # to # # #{prefix}attribute(#{attr}, *args, &block) # # An instance method #{prefix}attribute must exist and accept # at least the +attr+ argument. # # For example: # # class Person # # include ActiveModel::AttributeMethods # attr_accessor :name # attribute_method_prefix 'clear_' # define_attribute_methods [:name] # # private # # def clear_attribute(attr) # send("#{attr}=", nil) # end # end # # person = Person.new # person.name = "Bob" # person.name # => "Bob" # person.clear_name # person.name # => nil def attribute_method_prefix(*prefixes) self.attribute_method_matchers += prefixes.map { |prefix| AttributeMethodMatcher.new :prefix => prefix } undefine_attribute_methods end # Declares a method available for all attributes with the given suffix. # Uses +method_missing+ and respond_to? to rewrite the method. # # #{attr}#{suffix}(*args, &block) # # to # # attribute#{suffix}(#{attr}, *args, &block) # # An attribute#{suffix} instance method must exist and accept at least # the +attr+ argument. # # For example: # # class Person # # include ActiveModel::AttributeMethods # attr_accessor :name # attribute_method_suffix '_short?' # define_attribute_methods [:name] # # private # # def attribute_short?(attr) # send(attr).length < 5 # end # end # # person = Person.new # person.name = "Bob" # person.name # => "Bob" # person.name_short? # => true def attribute_method_suffix(*suffixes) self.attribute_method_matchers += suffixes.map { |suffix| AttributeMethodMatcher.new :suffix => suffix } undefine_attribute_methods end # Declares a method available for all attributes with the given prefix # and suffix. Uses +method_missing+ and respond_to? to rewrite # the method. # # #{prefix}#{attr}#{suffix}(*args, &block) # # to # # #{prefix}attribute#{suffix}(#{attr}, *args, &block) # # An #{prefix}attribute#{suffix} instance method must exist and # accept at least the +attr+ argument. # # For example: # # class Person # # include ActiveModel::AttributeMethods # attr_accessor :name # attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!' # define_attribute_methods [:name] # # private # # def reset_attribute_to_default!(attr) # ... # end # end # # person = Person.new # person.name # => 'Gem' # person.reset_name_to_default! # person.name # => 'Gemma' def attribute_method_affix(*affixes) self.attribute_method_matchers += affixes.map { |affix| AttributeMethodMatcher.new :prefix => affix[:prefix], :suffix => affix[:suffix] } undefine_attribute_methods end def alias_attribute(new_name, old_name) attribute_method_matchers.each do |matcher| matcher_new = matcher.method_name(new_name).to_s matcher_old = matcher.method_name(old_name).to_s define_optimized_call self, matcher_new, matcher_old end end # Declares the attributes that should be prefixed and suffixed by # ActiveModel::AttributeMethods. # # To use, pass in an array of attribute names (as strings or symbols), # be sure to declare +define_attribute_methods+ after you define any # prefix, suffix or affix methods, or they will not hook in. # # class Person # # include ActiveModel::AttributeMethods # attr_accessor :name, :age, :address # attribute_method_prefix 'clear_' # # # Call to define_attribute_methods must appear after the # # attribute_method_prefix, attribute_method_suffix or # # attribute_method_affix declares. # define_attribute_methods [:name, :age, :address] # # private # # def clear_attribute(attr) # ... # end # end def define_attribute_methods(attr_names) attr_names.each { |attr_name| define_attribute_method(attr_name) } end def define_attribute_method(attr_name) attribute_method_matchers.each do |matcher| method_name = matcher.method_name(attr_name) unless instance_method_already_implemented?(method_name) generate_method = "define_method_#{matcher.method_missing_target}" if respond_to?(generate_method, true) send(generate_method, attr_name) else define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s end end end attribute_method_matchers_cache.clear end # Removes all the previously dynamically defined methods from the class def undefine_attribute_methods generated_attribute_methods.module_eval do instance_methods.each { |m| undef_method(m) } end attribute_method_matchers_cache.clear end # Returns true if the attribute methods defined have been generated. def generated_attribute_methods #:nodoc: @generated_attribute_methods ||= begin mod = Module.new include mod mod end end protected def instance_method_already_implemented?(method_name) generated_attribute_methods.method_defined?(method_name) end private # The methods +method_missing+ and +respond_to?+ of this module are # invoked often in a typical rails, both of which invoke the method # +match_attribute_method?+. The latter method iterates through an # array doing regular expression matches, which results in a lot of # object creations. Most of the times it returns a +nil+ match. As the # match result is always the same given a +method_name+, this cache is # used to alleviate the GC, which ultimately also speeds up the app # significantly (in our case our test suite finishes 10% faster with # this cache). def attribute_method_matchers_cache #:nodoc: @attribute_method_matchers_cache ||= {} end def attribute_method_matcher(method_name) #:nodoc: if attribute_method_matchers_cache.key?(method_name) attribute_method_matchers_cache[method_name] else # Must try to match prefixes/suffixes first, or else the matcher with no prefix/suffix # will match every time. matchers = attribute_method_matchers.partition(&:plain?).reverse.flatten(1) match = nil matchers.detect { |method| match = method.match(method_name) } attribute_method_matchers_cache[method_name] = match end end # Define a method `name` in `mod` that dispatches to `send` # using the given `extra` args. This fallbacks `define_method` # and `send` if the given names cannot be compiled. def define_optimized_call(mod, name, send, *extra) #:nodoc: if name =~ NAME_COMPILABLE_REGEXP defn = "def #{name}(*args)" else defn = "define_method(:'#{name}') do |*args|" end extra = (extra.map(&:inspect) << "*args").join(", ") if send =~ CALL_COMPILABLE_REGEXP target = "#{send}(#{extra})" else target = "send(:'#{send}', #{extra})" end mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 #{defn} #{target} end RUBY end class AttributeMethodMatcher attr_reader :prefix, :suffix, :method_missing_target AttributeMethodMatch = Struct.new(:target, :attr_name, :method_name) def initialize(options = {}) options.symbolize_keys! if options[:prefix] == '' || options[:suffix] == '' ActiveSupport::Deprecation.warn( "Specifying an empty prefix/suffix for an attribute method is no longer " \ "necessary. If the un-prefixed/suffixed version of the method has not been " \ "defined when `define_attribute_methods` is called, it will be defined " \ "automatically." ) end @prefix, @suffix = options[:prefix] || '', options[:suffix] || '' @regex = /\A(#{Regexp.escape(@prefix)})(.+?)(#{Regexp.escape(@suffix)})\z/ @method_missing_target = "#{@prefix}attribute#{@suffix}" @method_name = "#{prefix}%s#{suffix}" end def match(method_name) if @regex =~ method_name AttributeMethodMatch.new(method_missing_target, $2, method_name) else nil end end def method_name(attr_name) @method_name % attr_name end def plain? prefix.empty? && suffix.empty? end end end # Allows access to the object attributes, which are held in the # @attributes hash, as though they were first-class methods. So a # Person class with a name attribute can use Person#name and Person#name= # and never directly use the attributes hash -- except for multiple assigns # with ActiveRecord#attributes=. A Milestone class can also ask # Milestone#completed? to test that the completed attribute is not +nil+ # or 0. # # It's also possible to instantiate related objects, so a Client class # belonging to the clients table with a +master_id+ foreign key can # instantiate master through Client#master. def method_missing(method, *args, &block) if respond_to_without_attributes?(method, true) super else match = match_attribute_method?(method.to_s) match ? attribute_missing(match, *args, &block) : super end end # attribute_missing is like method_missing, but for attributes. When method_missing is # called we check to see if there is a matching attribute method. If so, we call # attribute_missing to dispatch the attribute. This method can be overloaded to # customise the behaviour. def attribute_missing(match, *args, &block) __send__(match.target, match.attr_name, *args, &block) end # A Person object with a name attribute can ask person.respond_to?(:name), # person.respond_to?(:name=), and person.respond_to?(:name?) # which will all return +true+. alias :respond_to_without_attributes? :respond_to? def respond_to?(method, include_private_methods = false) if super true elsif !include_private_methods && super(method, true) # If we're here then we haven't found among non-private methods # but found among all methods. Which means that the given method is private. false else !match_attribute_method?(method.to_s).nil? end end protected def attribute_method?(attr_name) respond_to_without_attributes?(:attributes) && attributes.include?(attr_name) end private # Returns a struct representing the matching attribute method. # The struct's attributes are prefix, base and suffix. def match_attribute_method?(method_name) match = self.class.send(:attribute_method_matcher, method_name) match && attribute_method?(match.attr_name) ? match : nil end def missing_attribute(attr_name, stack) raise ActiveModel::MissingAttributeError, "missing attribute: #{attr_name}", stack end end end activemodel-3.2.16/lib/active_model/dirty.rb0000644000175000017500000001141712247654710020320 0ustar ondrejondrejrequire 'active_model/attribute_methods' require 'active_support/hash_with_indifferent_access' require 'active_support/core_ext/object/duplicable' module ActiveModel # == Active Model Dirty # # Provides a way to track changes in your object in the same way as # Active Record does. # # The requirements for implementing ActiveModel::Dirty are: # # * include ActiveModel::Dirty in your object # * Call define_attribute_methods passing each method you want to # track # * Call attr_name_will_change! before each change to the tracked # attribute # # If you wish to also track previous changes on save or update, you need to # add # # @previously_changed = changes # # inside of your save or update method. # # A minimal implementation could be: # # class Person # # include ActiveModel::Dirty # # define_attribute_methods [:name] # # def name # @name # end # # def name=(val) # name_will_change! unless val == @name # @name = val # end # # def save # @previously_changed = changes # @changed_attributes.clear # end # # end # # == Examples: # # A newly instantiated object is unchanged: # person = Person.find_by_name('Uncle Bob') # person.changed? # => false # # Change the name: # person.name = 'Bob' # person.changed? # => true # person.name_changed? # => true # person.name_was # => 'Uncle Bob' # person.name_change # => ['Uncle Bob', 'Bob'] # person.name = 'Bill' # person.name_change # => ['Uncle Bob', 'Bill'] # # Save the changes: # person.save # person.changed? # => false # person.name_changed? # => false # # Assigning the same value leaves the attribute unchanged: # person.name = 'Bill' # person.name_changed? # => false # person.name_change # => nil # # Which attributes have changed? # person.name = 'Bob' # person.changed # => ['name'] # person.changes # => { 'name' => ['Bill', 'Bob'] } # # If an attribute is modified in-place then make use of [attribute_name]_will_change! # to mark that the attribute is changing. Otherwise ActiveModel can't track changes to # in-place attributes. # # person.name_will_change! # person.name << 'y' # person.name_change # => ['Bill', 'Billy'] module Dirty extend ActiveSupport::Concern include ActiveModel::AttributeMethods included do attribute_method_suffix '_changed?', '_change', '_will_change!', '_was' attribute_method_affix :prefix => 'reset_', :suffix => '!' end # Returns true if any attribute have unsaved changes, false otherwise. # person.changed? # => false # person.name = 'bob' # person.changed? # => true def changed? changed_attributes.any? end # List of attributes with unsaved changes. # person.changed # => [] # person.name = 'bob' # person.changed # => ['name'] def changed changed_attributes.keys end # Map of changed attrs => [original value, new value]. # person.changes # => {} # person.name = 'bob' # person.changes # => { 'name' => ['bill', 'bob'] } def changes HashWithIndifferentAccess[changed.map { |attr| [attr, attribute_change(attr)] }] end # Map of attributes that were changed when the model was saved. # person.name # => 'bob' # person.name = 'robert' # person.save # person.previous_changes # => {'name' => ['bob, 'robert']} def previous_changes @previously_changed end # Map of change attr => original value. def changed_attributes @changed_attributes ||= {} end private # Handle *_changed? for +method_missing+. def attribute_changed?(attr) changed_attributes.include?(attr) end # Handle *_change for +method_missing+. def attribute_change(attr) [changed_attributes[attr], __send__(attr)] if attribute_changed?(attr) end # Handle *_was for +method_missing+. def attribute_was(attr) attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr) end # Handle *_will_change! for +method_missing+. def attribute_will_change!(attr) begin value = __send__(attr) value = value.duplicable? ? value.clone : value rescue TypeError, NoMethodError end changed_attributes[attr] = value unless changed_attributes.include?(attr) end # Handle reset_*! for +method_missing+. def reset_attribute!(attr) __send__("#{attr}=", changed_attributes[attr]) if attribute_changed?(attr) end end end activemodel-3.2.16/lib/active_model/validator.rb0000644000175000017500000001412312247654710021147 0ustar ondrejondrejrequire 'active_support/core_ext/array/wrap' require "active_support/core_ext/module/anonymous" require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/inclusion' module ActiveModel #:nodoc: # == Active Model Validator # # A simple base class that can be used along with # ActiveModel::Validations::ClassMethods.validates_with # # class Person # include ActiveModel::Validations # validates_with MyValidator # end # # class MyValidator < ActiveModel::Validator # def validate(record) # if some_complex_logic # record.errors[:base] = "This record is invalid" # end # end # # private # def some_complex_logic # # ... # end # end # # Any class that inherits from ActiveModel::Validator must implement a method # called validate which accepts a record. # # class Person # include ActiveModel::Validations # validates_with MyValidator # end # # class MyValidator < ActiveModel::Validator # def validate(record) # record # => The person instance being validated # options # => Any non-standard options passed to validates_with # end # end # # To cause a validation error, you must add to the record's errors directly # from within the validators message # # class MyValidator < ActiveModel::Validator # def validate(record) # record.errors.add :base, "This is some custom error message" # record.errors.add :first_name, "This is some complex validation" # # etc... # end # end # # To add behavior to the initialize method, use the following signature: # # class MyValidator < ActiveModel::Validator # def initialize(options) # super # @my_custom_field = options[:field_name] || :first_name # end # end # # The easiest way to add custom validators for validating individual attributes # is with the convenient ActiveModel::EachValidator. For example: # # class TitleValidator < ActiveModel::EachValidator # def validate_each(record, attribute, value) # record.errors.add attribute, 'must be Mr. Mrs. or Dr.' unless value.in?(['Mr.', 'Mrs.', 'Dr.']) # end # end # # This can now be used in combination with the +validates+ method # (see ActiveModel::Validations::ClassMethods.validates for more on this) # # class Person # include ActiveModel::Validations # attr_accessor :title # # validates :title, :presence => true # end # # Validator may also define a +setup+ instance method which will get called # with the class that using that validator as its argument. This can be # useful when there are prerequisites such as an +attr_accessor+ being present # for example: # # class MyValidator < ActiveModel::Validator # def setup(klass) # klass.send :attr_accessor, :custom_attribute # end # end # # This setup method is only called when used with validation macros or the # class level validates_with method. # class Validator attr_reader :options # Returns the kind of the validator. Examples: # # PresenceValidator.kind # => :presence # UniquenessValidator.kind # => :uniqueness # def self.kind @kind ||= name.split('::').last.underscore.sub(/_validator$/, '').to_sym unless anonymous? end # Accepts options that will be made available through the +options+ reader. def initialize(options) @options = options.freeze end # Return the kind for this validator. def kind self.class.kind end # Override this method in subclasses with validation logic, adding errors # to the records +errors+ array where necessary. def validate(record) raise NotImplementedError, "Subclasses must implement a validate(record) method." end end # +EachValidator+ is a validator which iterates through the attributes given # in the options hash invoking the validate_each method passing in the # record, attribute and value. # # All Active Model validations are built on top of this validator. class EachValidator < Validator attr_reader :attributes # Returns a new validator instance. All options will be available via the # +options+ reader, however the :attributes option will be removed # and instead be made available through the +attributes+ reader. def initialize(options) @attributes = Array.wrap(options.delete(:attributes)) raise ":attributes cannot be blank" if @attributes.empty? super check_validity! end # Performs validation on the supplied record. By default this will call # +validates_each+ to determine validity therefore subclasses should # override +validates_each+ with validation logic. def validate(record) attributes.each do |attribute| value = record.read_attribute_for_validation(attribute) next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank]) validate_each(record, attribute, value) end end # Override this method in subclasses with the validation logic, adding # errors to the records +errors+ array where necessary. def validate_each(record, attribute, value) raise NotImplementedError, "Subclasses must implement a validate_each(record, attribute, value) method" end # Hook method that gets called by the initializer allowing verification # that the arguments supplied are valid. You could for example raise an # +ArgumentError+ when invalid options are supplied. def check_validity! end end # +BlockValidator+ is a special +EachValidator+ which receives a block on initialization # and call this block for each attribute being validated. +validates_each+ uses this validator. class BlockValidator < EachValidator def initialize(options, &block) @block = block super end private def validate_each(record, attribute, value) @block.call(record, attribute, value) end end end activemodel-3.2.16/lib/active_model/mass_assignment_security/0000755000175000017500000000000012247654710023756 5ustar ondrejondrejactivemodel-3.2.16/lib/active_model/mass_assignment_security/permission_set.rb0000644000175000017500000000123212247654710027344 0ustar ondrejondrejrequire 'set' module ActiveModel module MassAssignmentSecurity class PermissionSet < Set def +(values) super(values.map(&:to_s)) end def include?(key) super(remove_multiparameter_id(key)) end def deny?(key) raise NotImplementedError, "#deny?(key) suppose to be overwritten" end protected def remove_multiparameter_id(key) key.to_s.gsub(/\(.+/m, '') end end class WhiteList < PermissionSet def deny?(key) !include?(key) end end class BlackList < PermissionSet def deny?(key) include?(key) end end end end activemodel-3.2.16/lib/active_model/mass_assignment_security/sanitizer.rb0000644000175000017500000000321212247654710026311 0ustar ondrejondrejrequire 'active_support/core_ext/module/delegation' module ActiveModel module MassAssignmentSecurity class Sanitizer def initialize(target=nil) end # Returns all attributes not denied by the authorizer. def sanitize(attributes, authorizer) sanitized_attributes = attributes.reject { |key, value| authorizer.deny?(key) } debug_protected_attribute_removal(attributes, sanitized_attributes) sanitized_attributes end protected def debug_protected_attribute_removal(attributes, sanitized_attributes) removed_keys = attributes.keys - sanitized_attributes.keys process_removed_attributes(removed_keys) if removed_keys.any? end def process_removed_attributes(attrs) raise NotImplementedError, "#process_removed_attributes(attrs) suppose to be overwritten" end end class LoggerSanitizer < Sanitizer delegate :logger, :to => :@target def initialize(target) @target = target super end def logger? @target.respond_to?(:logger) && @target.logger end def process_removed_attributes(attrs) logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger? end end class StrictSanitizer < Sanitizer def process_removed_attributes(attrs) return if (attrs - insensitive_attributes).empty? raise ActiveModel::MassAssignmentSecurity::Error, "Can't mass-assign protected attributes: #{attrs.join(', ')}" end def insensitive_attributes ['id'] end end class Error < StandardError end end end activemodel-3.2.16/lib/active_model/secure_password.rb0000644000175000017500000000557312247654710022403 0ustar ondrejondrejmodule ActiveModel module SecurePassword extend ActiveSupport::Concern module ClassMethods # Adds methods to set and authenticate against a BCrypt password. # This mechanism requires you to have a password_digest attribute. # # Validations for presence of password, confirmation of password (using # a "password_confirmation" attribute) are automatically added. # You can add more validations by hand if need be. # # You need to add bcrypt-ruby (~> 3.0.0) to Gemfile to use has_secure_password: # # gem 'bcrypt-ruby', '~> 3.0.0' # # Example using Active Record (which automatically includes ActiveModel::SecurePassword): # # # Schema: User(name:string, password_digest:string) # class User < ActiveRecord::Base # has_secure_password # end # # user = User.new(:name => "david", :password => "", :password_confirmation => "nomatch") # user.save # => false, password required # user.password = "mUc3m00RsqyRe" # user.save # => false, confirmation doesn't match # user.password_confirmation = "mUc3m00RsqyRe" # user.save # => true # user.authenticate("notright") # => false # user.authenticate("mUc3m00RsqyRe") # => user # User.find_by_name("david").try(:authenticate, "notright") # => nil # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user def has_secure_password # Load bcrypt-ruby only when has_secure_password is used. # This is to avoid ActiveModel (and by extension the entire framework) being dependent on a binary library. gem 'bcrypt-ruby', '~> 3.0.0' require 'bcrypt' attr_reader :password validates_confirmation_of :password validates_presence_of :password_digest include InstanceMethodsOnActivation if respond_to?(:attributes_protected_by_default) def self.attributes_protected_by_default super + ['password_digest'] end end end end module InstanceMethodsOnActivation # Returns self if the password is correct, otherwise false. def authenticate(unencrypted_password) if BCrypt::Password.new(password_digest) == unencrypted_password self else false end end # Encrypts the password into the password_digest attribute. def password=(unencrypted_password) @password = unencrypted_password unless unencrypted_password.blank? self.password_digest = BCrypt::Password.create(unencrypted_password) end end end end end activemodel-3.2.16/lib/active_model/locale/0000755000175000017500000000000012247654710020073 5ustar ondrejondrejactivemodel-3.2.16/lib/active_model/locale/en.yml0000644000175000017500000000221612247654710021221 0ustar ondrejondrejen: errors: # The default format to use in full error messages. format: "%{attribute} %{message}" # The values :model, :attribute and :value are always available for interpolation # The value :count is available when applicable. Can be used for pluralization. messages: inclusion: "is not included in the list" exclusion: "is reserved" invalid: "is invalid" confirmation: "doesn't match confirmation" accepted: "must be accepted" empty: "can't be empty" blank: "can't be blank" too_long: "is too long (maximum is %{count} characters)" too_short: "is too short (minimum is %{count} characters)" wrong_length: "is the wrong length (should be %{count} characters)" not_a_number: "is not a number" not_an_integer: "must be an integer" greater_than: "must be greater than %{count}" greater_than_or_equal_to: "must be greater than or equal to %{count}" equal_to: "must be equal to %{count}" less_than: "must be less than %{count}" less_than_or_equal_to: "must be less than or equal to %{count}" odd: "must be odd" even: "must be even" activemodel-3.2.16/lib/active_model/naming.rb0000644000175000017500000001451612247654710020441 0ustar ondrejondrejrequire 'active_support/inflector' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/module/introspection' require 'active_support/deprecation' module ActiveModel class Name < String attr_reader :singular, :plural, :element, :collection, :partial_path, :singular_route_key, :route_key, :param_key, :i18n_key alias_method :cache_key, :collection deprecate :partial_path => "ActiveModel::Name#partial_path is deprecated. Call #to_partial_path on model instances directly instead." def initialize(klass, namespace = nil, name = nil) name ||= klass.name raise ArgumentError, "Class name cannot be blank. You need to supply a name argument when anonymous class given" if name.blank? super(name) @unnamespaced = self.sub(/^#{namespace.name}::/, '') if namespace @klass = klass @singular = _singularize(self).freeze @plural = ActiveSupport::Inflector.pluralize(@singular).freeze @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze @human = ActiveSupport::Inflector.humanize(@element).freeze @collection = ActiveSupport::Inflector.tableize(self).freeze @partial_path = "#{@collection}/#{@element}".freeze @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze @i18n_key = self.underscore.to_sym @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural.dup) @singular_route_key = ActiveSupport::Inflector.singularize(@route_key).freeze @route_key << "_index" if @plural == @singular @route_key.freeze end # Transform the model name into a more humane format, using I18n. By default, # it will underscore then humanize the class name # # BlogPost.model_name.human # => "Blog post" # # Specify +options+ with additional translating options. def human(options={}) return @human unless @klass.respond_to?(:lookup_ancestors) && @klass.respond_to?(:i18n_scope) defaults = @klass.lookup_ancestors.map do |klass| klass.model_name.i18n_key end defaults << options[:default] if options[:default] defaults << @human options = {:scope => [@klass.i18n_scope, :models], :count => 1, :default => defaults}.merge(options.except(:default)) I18n.translate(defaults.shift, options) end private def _singularize(string, replacement='_') ActiveSupport::Inflector.underscore(string).tr('/', replacement) end end # == Active Model Naming # # Creates a +model_name+ method on your object. # # To implement, just extend ActiveModel::Naming in your object: # # class BookCover # extend ActiveModel::Naming # end # # BookCover.model_name # => "BookCover" # BookCover.model_name.human # => "Book cover" # # BookCover.model_name.i18n_key # => :book_cover # BookModule::BookCover.model_name.i18n_key # => :"book_module/book_cover" # # Providing the functionality that ActiveModel::Naming provides in your object # is required to pass the Active Model Lint test. So either extending the provided # method below, or rolling your own is required. module Naming # Returns an ActiveModel::Name object for module. It can be # used to retrieve all kinds of naming-related information. def model_name @_model_name ||= begin namespace = self.parents.detect do |n| n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming? end ActiveModel::Name.new(self, namespace) end end # Returns the plural class name of a record or class. Examples: # # ActiveModel::Naming.plural(post) # => "posts" # ActiveModel::Naming.plural(Highrise::Person) # => "highrise_people" def self.plural(record_or_class) model_name_from_record_or_class(record_or_class).plural end # Returns the singular class name of a record or class. Examples: # # ActiveModel::Naming.singular(post) # => "post" # ActiveModel::Naming.singular(Highrise::Person) # => "highrise_person" def self.singular(record_or_class) model_name_from_record_or_class(record_or_class).singular end # Identifies whether the class name of a record or class is uncountable. Examples: # # ActiveModel::Naming.uncountable?(Sheep) # => true # ActiveModel::Naming.uncountable?(Post) => false def self.uncountable?(record_or_class) plural(record_or_class) == singular(record_or_class) end # Returns string to use while generating route names. It differs for # namespaced models regarding whether it's inside isolated engine. # # For isolated engine: # ActiveModel::Naming.route_key(Blog::Post) #=> post # # For shared engine: # ActiveModel::Naming.route_key(Blog::Post) #=> blog_post def self.singular_route_key(record_or_class) model_name_from_record_or_class(record_or_class).singular_route_key end # Returns string to use while generating route names. It differs for # namespaced models regarding whether it's inside isolated engine. # # For isolated engine: # ActiveModel::Naming.route_key(Blog::Post) #=> posts # # For shared engine: # ActiveModel::Naming.route_key(Blog::Post) #=> blog_posts # # The route key also considers if the noun is uncountable and, in # such cases, automatically appends _index. def self.route_key(record_or_class) model_name_from_record_or_class(record_or_class).route_key end # Returns string to use for params names. It differs for # namespaced models regarding whether it's inside isolated engine. # # For isolated engine: # ActiveModel::Naming.param_key(Blog::Post) #=> post # # For shared engine: # ActiveModel::Naming.param_key(Blog::Post) #=> blog_post def self.param_key(record_or_class) model_name_from_record_or_class(record_or_class).param_key end private def self.model_name_from_record_or_class(record_or_class) (record_or_class.is_a?(Class) ? record_or_class : convert_to_model(record_or_class).class).model_name end def self.convert_to_model(object) object.respond_to?(:to_model) ? object.to_model : object end end end activemodel-3.2.16/lib/active_model/translation.rb0000644000175000017500000000444312247654710021524 0ustar ondrejondrejrequire 'active_support/core_ext/hash/reverse_merge' module ActiveModel # == Active Model Translation # # Provides integration between your object and the Rails internationalization # (i18n) framework. # # A minimal implementation could be: # # class TranslatedPerson # extend ActiveModel::Translation # end # # TranslatedPerson.human_attribute_name('my_attribute') # # => "My attribute" # # This also provides the required class methods for hooking into the # Rails internationalization API, including being able to define a # class based +i18n_scope+ and +lookup_ancestors+ to find translations in # parent classes. module Translation include ActiveModel::Naming # Returns the +i18n_scope+ for the class. Overwrite if you want custom lookup. def i18n_scope :activemodel end # When localizing a string, it goes through the lookup returned by this # method, which is used in ActiveModel::Name#human, # ActiveModel::Errors#full_messages and # ActiveModel::Translation#human_attribute_name. def lookup_ancestors self.ancestors.select { |x| x.respond_to?(:model_name) } end # Transforms attribute names into a more human format, such as "First name" # instead of "first_name". # # Person.human_attribute_name("first_name") # => "First name" # # Specify +options+ with additional translating options. def human_attribute_name(attribute, options = {}) defaults = [] parts = attribute.to_s.split(".") attribute = parts.pop namespace = parts.join("/") unless parts.empty? if namespace lookup_ancestors.each do |klass| defaults << :"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}/#{namespace}.#{attribute}" end defaults << :"#{self.i18n_scope}.attributes.#{namespace}.#{attribute}" else lookup_ancestors.each do |klass| defaults << :"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}" end end defaults << :"attributes.#{attribute}" defaults << options.delete(:default) if options[:default] defaults << attribute.humanize options.reverse_merge! :count => 1, :default => defaults I18n.translate(defaults.shift, options) end end end activemodel-3.2.16/lib/active_model/version.rb0000644000175000017500000000025412247654710020647 0ustar ondrejondrejmodule ActiveModel module VERSION #:nodoc: MAJOR = 3 MINOR = 2 TINY = 16 PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') end end activemodel-3.2.16/lib/active_model/lint.rb0000644000175000017500000001221312247654710020126 0ustar ondrejondrejmodule ActiveModel module Lint # == Active Model Lint Tests # # You can test whether an object is compliant with the Active Model API by # including ActiveModel::Lint::Tests in your TestCase. It will include # tests that tell you whether your object is fully compliant, or if not, # which aspects of the API are not implemented. # # These tests do not attempt to determine the semantic correctness of the # returned values. For instance, you could implement valid? to always # return true, and the tests would pass. It is up to you to ensure that # the values are semantically meaningful. # # Objects you pass in are expected to return a compliant object from a # call to to_model. It is perfectly fine for to_model to return self. module Tests # == Responds to to_key # # Returns an Enumerable of all (primary) key attributes # or nil if model.persisted? is false def test_to_key assert model.respond_to?(:to_key), "The model should respond to to_key" def model.persisted?() false end assert model.to_key.nil?, "to_key should return nil when `persisted?` returns false" end # == Responds to to_param # # Returns a string representing the object's key suitable for use in URLs # or nil if model.persisted? is false. # # Implementers can decide to either raise an exception or provide a default # in case the record uses a composite primary key. There are no tests for this # behavior in lint because it doesn't make sense to force any of the possible # implementation strategies on the implementer. However, if the resource is # not persisted?, then to_param should always return nil. def test_to_param assert model.respond_to?(:to_param), "The model should respond to to_param" def model.to_key() [1] end def model.persisted?() false end assert model.to_param.nil?, "to_param should return nil when `persisted?` returns false" end # == Responds to to_partial_path # # Returns a string giving a relative path. This is used for looking up # partials. For example, a BlogPost model might return "blog_posts/blog_post" # def test_to_partial_path assert model.respond_to?(:to_partial_path), "The model should respond to to_partial_path" assert_kind_of String, model.to_partial_path end # == Responds to valid? # # Returns a boolean that specifies whether the object is in a valid or invalid # state. def test_valid? assert model.respond_to?(:valid?), "The model should respond to valid?" assert_boolean model.valid?, "valid?" end # == Responds to persisted? # # Returns a boolean that specifies whether the object has been persisted yet. # This is used when calculating the URL for an object. If the object is # not persisted, a form for that object, for instance, will be POSTed to the # collection. If it is persisted, a form for the object will be PUT to the # URL for the object. def test_persisted? assert model.respond_to?(:persisted?), "The model should respond to persisted?" assert_boolean model.persisted?, "persisted?" end # == Naming # # Model.model_name must return a string with some convenience methods: # :human, :singular, and :plural. Check ActiveModel::Naming for more information. # def test_model_naming assert model.class.respond_to?(:model_name), "The model should respond to model_name" model_name = model.class.model_name assert_kind_of String, model_name assert_kind_of String, model_name.human assert_kind_of String, model_name.singular assert_kind_of String, model_name.plural end # == Errors Testing # # Returns an object that has :[] and :full_messages defined on it. See below # for more details. # # Returns an Array of Strings that are the errors for the attribute in # question. If localization is used, the Strings should be localized # for the current locale. If no error is present, this method should # return an empty Array. def test_errors_aref assert model.respond_to?(:errors), "The model should respond to errors" assert model.errors[:hello].is_a?(Array), "errors#[] should return an Array" end # Returns an Array of all error messages for the object. Each message # should contain information about the field, if applicable. def test_errors_full_messages assert model.respond_to?(:errors), "The model should respond to errors" assert model.errors.full_messages.is_a?(Array), "errors#full_messages should return an Array" end private def model assert @model.respond_to?(:to_model), "The object should respond_to to_model" @model.to_model end def assert_boolean(result, name) assert result == true || result == false, "#{name} should be a boolean" end end end end activemodel-3.2.16/lib/active_model.rb0000644000175000017500000000416212247654710017164 0ustar ondrejondrej#-- # Copyright (c) 2004-2011 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) require 'active_support' require 'active_model/version' module ActiveModel extend ActiveSupport::Autoload autoload :AttributeMethods autoload :BlockValidator, 'active_model/validator' autoload :Callbacks autoload :Conversion autoload :Dirty autoload :EachValidator, 'active_model/validator' autoload :Errors autoload :Lint autoload :MassAssignmentSecurity autoload :Name, 'active_model/naming' autoload :Naming autoload :Observer, 'active_model/observing' autoload :Observing autoload :SecurePassword autoload :Serialization autoload :TestCase autoload :Translation autoload :Validations autoload :Validator module Serializers extend ActiveSupport::Autoload autoload :JSON autoload :Xml end end require 'active_support/i18n' I18n.load_path << File.dirname(__FILE__) + '/active_model/locale/en.yml' activemodel-3.2.16/metadata.yml0000644000175000017500000000623612247654710015745 0ustar ondrejondrej--- !ruby/object:Gem::Specification name: activemodel version: !ruby/object:Gem::Version version: 3.2.16 platform: ruby authors: - David Heinemeier Hansson autorequire: bindir: bin cert_chain: [] date: 2013-12-03 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: activesupport requirement: !ruby/object:Gem::Requirement requirements: - - '=' - !ruby/object:Gem::Version version: 3.2.16 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '=' - !ruby/object:Gem::Version version: 3.2.16 - !ruby/object:Gem::Dependency name: builder requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 3.0.0 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 3.0.0 description: A toolkit for building modeling frameworks like Active Record and Active Resource. Rich support for attributes, callbacks, validations, observers, serialization, internationalization, and testing. email: david@loudthinking.com executables: [] extensions: [] extra_rdoc_files: [] files: - CHANGELOG.md - MIT-LICENSE - README.rdoc - lib/active_model/attribute_methods.rb - lib/active_model/callbacks.rb - lib/active_model/conversion.rb - lib/active_model/dirty.rb - lib/active_model/errors.rb - lib/active_model/lint.rb - lib/active_model/locale/en.yml - lib/active_model/mass_assignment_security/permission_set.rb - lib/active_model/mass_assignment_security/sanitizer.rb - lib/active_model/mass_assignment_security.rb - lib/active_model/naming.rb - lib/active_model/observer_array.rb - lib/active_model/observing.rb - lib/active_model/railtie.rb - lib/active_model/secure_password.rb - lib/active_model/serialization.rb - lib/active_model/serializers/json.rb - lib/active_model/serializers/xml.rb - lib/active_model/test_case.rb - lib/active_model/translation.rb - lib/active_model/validations/acceptance.rb - lib/active_model/validations/callbacks.rb - lib/active_model/validations/confirmation.rb - lib/active_model/validations/exclusion.rb - lib/active_model/validations/format.rb - lib/active_model/validations/inclusion.rb - lib/active_model/validations/length.rb - lib/active_model/validations/numericality.rb - lib/active_model/validations/presence.rb - lib/active_model/validations/validates.rb - lib/active_model/validations/with.rb - lib/active_model/validations.rb - lib/active_model/validator.rb - lib/active_model/version.rb - lib/active_model.rb homepage: http://www.rubyonrails.org licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.8.7 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.0.2 signing_key: specification_version: 4 summary: A toolkit for building modeling frameworks (part of Rails). test_files: [] activemodel-3.2.16/MIT-LICENSE0000644000175000017500000000206212247654710015067 0ustar ondrejondrejCopyright (c) 2004-2011 David Heinemeier Hansson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.