# The generated code is based on Ruby on Rails source code # You can find the license of Ruby on Rails from following. #Copyright (c) 2005-2019 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. module ActiveModel class Attribute class UserProvidedDefault < FromUser # :nodoc: # :nodoc: def initialize: (untyped name, untyped value, untyped `type`, untyped database_default) -> untyped def value_before_type_cast: () -> untyped def with_type: (untyped `type`) -> untyped def marshal_dump: () -> untyped def marshal_load: (untyped values) -> untyped private attr_reader user_provided_value: untyped end end end module ActiveModel class Attribute def self.from_database: (untyped name, untyped value, untyped `type`) -> FromDatabase def self.from_user: (untyped name, untyped value, untyped `type`, ?untyped? original_attribute) -> FromUser def self.with_cast_value: (untyped name, untyped value, untyped `type`) -> WithCastValue def self.null: (untyped name) -> Null def self.uninitialized: (untyped name, untyped `type`) -> Uninitialized attr_reader name: untyped attr_reader value_before_type_cast: untyped attr_reader type: untyped # This method should not be called directly. # Use #from_database or #from_user def initialize: (untyped name, untyped value_before_type_cast, untyped `type`, ?untyped? original_attribute) -> untyped def value: () -> untyped def original_value: () -> untyped def value_for_database: () -> untyped def changed?: () -> untyped def changed_in_place?: () -> untyped def forgetting_assignment: () -> untyped def with_value_from_user: (untyped value) -> untyped def with_value_from_database: (untyped value) -> untyped def with_cast_value: (untyped value) -> untyped def with_type: (untyped `type`) -> untyped def type_cast: () -> untyped def initialized?: () -> ::TrueClass def came_from_user?: () -> ::FalseClass def has_been_read?: () -> untyped def ==: (untyped other) -> untyped alias eql? == def hash: () -> untyped def init_with: (untyped coder) -> untyped def encode_with: (untyped coder) -> untyped def original_value_for_database: () -> untyped private attr_reader original_attribute: untyped alias assigned? original_attribute def initialize_dup: (untyped other) -> untyped def changed_from_assignment?: () -> untyped def _original_value_for_database: () -> untyped class FromDatabase < Attribute # :nodoc: def type_cast: (untyped value) -> untyped def _original_value_for_database: () -> untyped end class FromUser < Attribute # :nodoc: def type_cast: (untyped value) -> untyped def came_from_user?: () -> untyped end class WithCastValue < Attribute # :nodoc: def type_cast: (untyped value) -> untyped def changed_in_place?: () -> ::FalseClass end class Null < Attribute # :nodoc: def initialize: (untyped name) -> untyped def type_cast: () -> nil def with_type: (untyped `type`) -> untyped def with_value_from_database: (untyped value) -> untyped alias with_value_from_user with_value_from_database alias with_cast_value with_value_from_database end class Uninitialized < Attribute # :nodoc: UNINITIALIZED_ORIGINAL_VALUE: untyped def initialize: (untyped name, untyped `type`) -> untyped def value: () { (untyped) -> untyped } -> untyped def original_value: () -> untyped def value_for_database: () -> nil def initialized?: () -> ::FalseClass def forgetting_assignment: () -> untyped def with_type: (untyped `type`) -> untyped end end end module ActiveModel module AttributeAssignment include ActiveModel::ForbiddenAttributesProtection # Allows you to set all the attributes by passing in a hash of attributes with # keys matching the attribute names. # # If the passed hash responds to permitted? method and the return value # of this method is +false+ an ActiveModel::ForbiddenAttributesError # exception is raised. # # class Cat # include ActiveModel::AttributeAssignment # attr_accessor :name, :status # end # # cat = Cat.new # cat.assign_attributes(name: "Gorby", status: "yawning") # cat.name # => 'Gorby' # cat.status # => 'yawning' # cat.assign_attributes(status: "sleeping") # cat.name # => 'Gorby' # cat.status # => 'sleeping' def assign_attributes: (untyped new_attributes) -> (nil | untyped) alias attributes= assign_attributes private def _assign_attributes: (untyped attributes) -> untyped def _assign_attribute: (untyped k, untyped v) -> untyped end end module ActiveModel # Raised when an attribute is not defined. # # class User < ActiveRecord::Base # has_many :pets # end # # user = User.first # user.pets.select(:id).first.user_id # # => ActiveModel::MissingAttributeError: missing attribute: user_id class MissingAttributeError[T] < NoMethodError[T] end # == Active \Model \Attribute \Methods # # Provides a way to add prefixes and suffixes to your methods as # well as handling the creation of ActiveRecord::Base-like # class methods such as +table_name+. # # The requirements to implement ActiveModel::AttributeMethods are to: # # * include ActiveModel::AttributeMethods in your class. # * Call each of its methods 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. # * Define 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. # # 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 # # def attributes # { 'name' => @name } # end # # 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 module AttributeMethods extend ActiveSupport::Concern NAME_COMPILABLE_REGEXP: untyped CALL_COMPILABLE_REGEXP: untyped module ClassMethods # 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. # # 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: (*untyped prefixes) -> untyped # 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. # # 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: (*untyped suffixes) -> untyped # 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. # # 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) # send("#{attr}=", 'Default Name') # end # end # # person = Person.new # person.name # => 'Gem' # person.reset_name_to_default! # person.name # => 'Default Name' def attribute_method_affix: (*untyped affixes) -> untyped # Allows you to make aliases for attributes. # # class Person # include ActiveModel::AttributeMethods # # attr_accessor :name # attribute_method_suffix '_short?' # define_attribute_methods :name # # alias_attribute :nickname, :name # # private # # def attribute_short?(attr) # send(attr).length < 5 # end # end # # person = Person.new # person.name = 'Bob' # person.name # => "Bob" # person.nickname # => "Bob" # person.name_short? # => true # person.nickname_short? # => true def alias_attribute: (untyped new_name, untyped old_name) -> untyped # Is +new_name+ an alias? def attribute_alias?: (untyped new_name) -> untyped # Returns the original name for the alias +name+ def attribute_alias: (untyped name) -> untyped # Declares the attributes that should be prefixed and suffixed by # ActiveModel::AttributeMethods. # # To use, pass 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 declarations. # define_attribute_methods :name, :age, :address # # private # # def clear_attribute(attr) # send("#{attr}=", nil) # end # end def define_attribute_methods: (*untyped attr_names) -> untyped # Declares an attribute that should be prefixed and suffixed by # ActiveModel::AttributeMethods. # # To use, pass an attribute name (as string or symbol). Be sure to declare # +define_attribute_method+ after you define any prefix, suffix or affix # method, or they will not hook in. # # class Person # include ActiveModel::AttributeMethods # # attr_accessor :name # attribute_method_suffix '_short?' # # # Call to define_attribute_method must appear after the # # attribute_method_prefix, attribute_method_suffix or # # attribute_method_affix declarations. # define_attribute_method :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 define_attribute_method: (untyped attr_name) -> untyped # Removes all the previously dynamically defined methods from the class. # # class Person # include ActiveModel::AttributeMethods # # attr_accessor :name # attribute_method_suffix '_short?' # define_attribute_method :name # # private # # def attribute_short?(attr) # send(attr).length < 5 # end # end # # person = Person.new # person.name = 'Bob' # person.name_short? # => true # # Person.undefine_attribute_methods # # person.name_short? # => NoMethodError def undefine_attribute_methods: () -> untyped private def generated_attribute_methods: () -> untyped def instance_method_already_implemented?: (untyped method_name) -> untyped # The methods +method_missing+ and +respond_to?+ of this module are # invoked often in a typical rails, both of which invoke the method # +matched_attribute_method+. The latter method iterates through an # array doing regular expression matches, which results in a lot of # object creations. Most of the time 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: () -> untyped def attribute_method_matchers_matching: (untyped method_name) -> untyped # Define a method `name` in `mod` that dispatches to `send` # using the given `extra` args. This falls back on `define_method` # and `send` if the given names cannot be compiled. def define_proxy_call: (untyped include_private, untyped mod, untyped name, untyped target, *untyped extra) -> untyped class AttributeMethodMatcher # nodoc: attr_reader prefix: untyped # nodoc: attr_reader suffix: untyped # nodoc: attr_reader target: untyped class AttributeMethodMatch[T] < ::Struct[T] attr_accessor target(): untyped attr_accessor attr_name(): untyped end def initialize: (?::Hash[untyped, untyped] options) -> untyped def match: (untyped method_name) -> untyped def method_name: (untyped attr_name) -> untyped def plain?: () -> untyped end end # Allows access to the object attributes, which are held in the hash # returned by attributes, as though they were first-class # methods. So a +Person+ class with a +name+ attribute can for example use # Person#name and Person#name= and never directly use # the attributes hash -- except for multiple assignments with # ActiveRecord::Base#attributes=. # # 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: (untyped method, *untyped args) { () -> untyped } -> untyped # +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 tell +attribute_missing+ to dispatch the # attribute. This method can be overloaded to customize the behavior. def attribute_missing: (untyped match, *untyped args) { () -> untyped } -> untyped # A +Person+ instance 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?: (untyped method, ?bool include_private_methods) -> untyped private def attribute_method?: (untyped attr_name) -> untyped # Returns a struct representing the matching attribute method. # The struct's attributes are prefix, base and suffix. def matched_attribute_method: (untyped method_name) -> untyped def missing_attribute: (untyped attr_name, untyped stack) -> untyped def _read_attribute: (untyped attr) -> untyped module AttrNames # :nodoc: DEF_SAFE_NAME: untyped # We want to generate the methods via module_eval rather than # define_method, because define_method is slower on dispatch. # Evaluating many similar methods may use more memory as the instruction # sequences are duplicated and cached (in MRI). define_method may # be slower on dispatch, but if you're careful about the closure # created, then define_method will consume much less memory. # # But sometimes the database might return columns with # characters that are not allowed in normal method names (like # 'my_column(omg)'. So to work around this we first define with # the __temp__ identifier, and then use alias method to rename # it to what we want. # # We are also defining a constant to hold the frozen string of # the attribute name. Using a constant means that we do not have # to allocate an object on each call to the attribute method. # Making it frozen means that it doesn't get duped when used to # key the @attributes in read_attribute. def self.define_attribute_accessor_method: (untyped mod, untyped attr_name, ?writer: bool writer) { (untyped, untyped) -> untyped } -> untyped end end end module ActiveModel class AttributeMutationTracker # :nodoc: OPTION_NOT_GIVEN: untyped def initialize: (untyped attributes, ?untyped forced_changes) -> untyped def changed_attribute_names: () -> untyped def changed_values: () -> untyped def changes: () -> untyped def change_to_attribute: (untyped attr_name) -> untyped def any_changes?: () -> untyped def changed?: (untyped attr_name, ?to: untyped to, ?from: untyped from) -> untyped def changed_in_place?: (untyped attr_name) -> untyped def forget_change: (untyped attr_name) -> untyped def original_value: (untyped attr_name) -> untyped def force_change: (untyped attr_name) -> untyped private attr_reader attributes: untyped attr_reader forced_changes: untyped def attr_names: () -> untyped def attribute_changed?: (untyped attr_name) -> untyped def fetch_value: (untyped attr_name) -> untyped end class ForcedMutationTracker < AttributeMutationTracker # :nodoc: def initialize: (untyped attributes, ?::Hash[untyped, untyped] forced_changes) -> untyped def changed_in_place?: (untyped attr_name) -> ::FalseClass def change_to_attribute: (untyped attr_name) -> untyped def forget_change: (untyped attr_name) -> untyped def original_value: (untyped attr_name) -> untyped def force_change: (untyped attr_name) -> untyped def finalize_changes: () -> untyped private attr_reader finalized_changes: untyped def attr_names: () -> untyped def attribute_changed?: (untyped attr_name) -> untyped def fetch_value: (untyped attr_name) -> untyped def clone_value: (untyped attr_name) -> untyped end class NullMutationTracker # :nodoc: include Singleton def changed_attribute_names: () -> ::Array[untyped] def changed_values: () -> ::Hash[untyped, untyped] def changes: () -> ::Hash[untyped, untyped] def change_to_attribute: (untyped attr_name) -> nil def any_changes?: () -> ::FalseClass def changed?: (untyped attr_name) -> ::FalseClass def changed_in_place?: (untyped attr_name) -> ::FalseClass def original_value: (untyped attr_name) -> nil end end module ActiveModel class AttributeSet class Builder # :nodoc: # :nodoc: attr_reader types: untyped # :nodoc: # :nodoc: attr_reader default_attributes: untyped def initialize: (untyped types, ?::Hash[untyped, untyped] default_attributes) -> untyped def build_from_database: (?::Hash[untyped, untyped] values, ?::Hash[untyped, untyped] additional_types) -> AttributeSet end end class LazyAttributeHash def initialize: (untyped types, untyped values, untyped additional_types, untyped default_attributes, ?::Hash[untyped, untyped] delegate_hash) -> untyped def key?: (untyped key) -> untyped def []: (untyped key) -> untyped def []=: (untyped key, untyped value) -> untyped def deep_dup: () -> untyped def initialize_dup: (untyped _) -> untyped def select: () { (untyped, untyped) -> untyped } -> untyped def ==: (untyped other) -> untyped def marshal_dump: () -> ::Array[untyped] def marshal_load: (untyped values) -> untyped def materialize: () -> untyped private attr_reader types: untyped attr_reader values: untyped attr_reader additional_types: untyped attr_reader delegate_hash: untyped attr_reader default_attributes: untyped def assign_default_value: (untyped name) -> untyped end end module ActiveModel class AttributeSet class YAMLEncoder # Attempts to do more intelligent YAML dumping of an # ActiveModel::AttributeSet to reduce the size of the resulting string # :nodoc: def initialize: (untyped default_types) -> untyped def encode: (untyped attribute_set, untyped coder) -> untyped def decode: (untyped coder) -> untyped private attr_reader default_types: untyped end end end module ActiveModel class AttributeSet def initialize: (untyped attributes) -> untyped def []: (untyped name) -> untyped def []=: (untyped name, untyped value) -> untyped def values_before_type_cast: () -> untyped def to_hash: () -> untyped alias to_h to_hash def key?: (untyped name) -> untyped def keys: () -> untyped def fetch_value: (untyped name) { () -> untyped } -> untyped def write_from_database: (untyped name, untyped value) -> untyped def write_from_user: (untyped name, untyped value) -> untyped def write_cast_value: (untyped name, untyped value) -> untyped def freeze: () -> untyped def deep_dup: () -> untyped def initialize_dup: (untyped _) -> untyped def initialize_clone: (untyped _) -> untyped def reset: (untyped key) -> untyped def accessed: () -> untyped def map: () { () -> untyped } -> AttributeSet def ==: (untyped other) -> untyped attr_reader attributes: untyped private def initialized_attributes: () -> untyped end end module ActiveModel module Attributes # nodoc: extend ActiveSupport::Concern include ActiveModel::AttributeMethods module ClassMethods def attribute: (untyped name, ?untyped `type`, **untyped options) -> untyped # Returns an array of attribute names as strings # # class Person # include ActiveModel::Attributes # # attribute :name, :string # attribute :age, :integer # end # # Person.attribute_names # # => ["name", "age"] def attribute_names: () -> untyped private def define_method_attribute=: (untyped name) -> untyped NO_DEFAULT_PROVIDED: untyped def define_default_attribute: (untyped name, untyped value, untyped `type`) -> untyped end def initialize: () -> untyped # Returns a hash of all the attributes with their names as keys and the values of the attributes as values. # # class Person # include ActiveModel::Model # include ActiveModel::Attributes # # attribute :name, :string # attribute :age, :integer # end # # person = Person.new(name: 'Francesco', age: 22) # person.attributes # # => {"name"=>"Francesco", "age"=>22} def attributes: () -> untyped # Returns an array of attribute names as strings # # class Person # include ActiveModel::Attributes # # attribute :name, :string # attribute :age, :integer # end # # person = Person.new # person.attribute_names # # => ["name", "age"] def attribute_names: () -> untyped private def write_attribute: (untyped attr_name, untyped value) -> untyped def attribute: (untyped attr_name) -> untyped # Dispatch target for *= attribute methods. def attribute=: (untyped attribute_name, untyped value) -> untyped end end 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 throws +:abort+. # # 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 model. # # before_create :action_before_create # # def action_before_create # # Your code here # end # # When defining an around callback remember to yield to the block, otherwise # it won't be executed: # # around_create :log_status # # def log_status # puts 'going to call the block...' # yield # puts 'block successfully called.' # end # # You can choose to have only specific 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. # # NOTE: Calling the same callback multiple times will overwrite previous callback definitions. # module Callbacks def self.extended: (untyped base) -> untyped # 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 # # NOTE: +method_name+ passed to define_model_callbacks must not end with # !, ? or =. def define_model_callbacks: (*untyped callbacks) -> untyped private def _define_before_model_callback: (untyped klass, untyped callback) -> untyped def _define_around_model_callback: (untyped klass, untyped callback) -> untyped def _define_after_model_callback: (untyped klass, untyped callback) -> untyped end end module ActiveModel # == Active \Model \Conversion # # 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 == cm # => true # cm.to_key # => nil # cm.to_param # => nil # cm.to_partial_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+. # # class Person # include ActiveModel::Conversion # end # # person = Person.new # person.to_model == person # => true # # 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: () -> untyped # Returns an Array of all key attributes if any of the attributes is set, whether or not # the object is persisted. Returns +nil+ if there are no key attributes. # # class Person # include ActiveModel::Conversion # attr_accessor :id # # def initialize(id) # @id = id # end # end # # person = Person.new(1) # person.to_key # => [1] def to_key: () -> untyped # Returns a +string+ representing the object's key suitable for use in URLs, # or +nil+ if persisted? is +false+. # # class Person # include ActiveModel::Conversion # attr_accessor :id # # def initialize(id) # @id = id # end # # def persisted? # true # end # end # # person = Person.new(1) # person.to_param # => "1" def to_param: () -> untyped # Returns a +string+ identifying the path associated with the object. # ActionPack uses this to find a suitable partial to represent the object. # # class Person # include ActiveModel::Conversion # end # # person = Person.new # person.to_partial_path # => "people/person" def to_partial_path: () -> untyped module ClassMethods def _to_partial_path: () -> untyped end end end 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. # * Call changes_applied after the changes are persisted. # * Call clear_changes_information when you want to reset the changes # information. # * Call restore_attributes when you want to restore previous data. # # A minimal implementation could be: # # class Person # include ActiveModel::Dirty # # define_attribute_methods :name # # def initialize # @name = nil # end # # def name # @name # end # # def name=(val) # name_will_change! unless val == @name # @name = val # end # # def save # # do persistence work # # changes_applied # end # # def reload! # # get the values from the persistence layer # # clear_changes_information # end # # def rollback! # restore_attributes # end # end # # A newly instantiated +Person+ object is unchanged: # # person = Person.new # person.changed? # => false # # Change the name: # # person.name = 'Bob' # person.changed? # => true # person.name_changed? # => true # person.name_changed?(from: nil, to: "Bob") # => true # person.name_was # => nil # person.name_change # => [nil, "Bob"] # person.name = 'Bill' # person.name_change # => [nil, "Bill"] # # Save the changes: # # person.save # person.changed? # => false # person.name_changed? # => false # # Reset the changes: # # person.previous_changes # => {"name" => [nil, "Bill"]} # person.name_previously_changed? # => true # person.name_previous_change # => [nil, "Bill"] # person.reload! # person.previous_changes # => {} # # Rollback the changes: # # person.name = "Uncle Bob" # person.rollback! # person.name # => "Bill" # 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 \Active \Model can't track changes to in-place attributes. Note # that Active Record can detect in-place modifications automatically. You do # not need to call [attribute_name]_will_change! on Active Record models. # # person.name_will_change! # person.name_change # => ["Bill", "Bill"] # person.name << 'y' # person.name_change # => ["Bill", "Billy"] module Dirty extend ActiveSupport::Concern include ActiveModel::AttributeMethods def initialize_dup: (untyped other) -> untyped # Clears dirty data and moves +changes+ to +previously_changed+ and # +mutations_from_database+ to +mutations_before_last_save+ respectively. def changes_applied: () -> untyped # Returns +true+ if any of the attributes has unsaved changes, +false+ otherwise. # # person.changed? # => false # person.name = 'bob' # person.changed? # => true def changed?: () -> untyped # Returns an array with the name of the attributes with unsaved changes. # # person.changed # => [] # person.name = 'bob' # person.changed # => ["name"] def changed: () -> untyped def attribute_changed?: (untyped attr_name, **untyped options) -> untyped def attribute_was: (untyped attr_name) -> untyped def attribute_previously_changed?: (untyped attr_name) -> untyped # Restore all previous data of the provided attributes. def restore_attributes: (?untyped attr_names) -> untyped # Clears all dirty data: current changes and previous changes. def clear_changes_information: () -> untyped def clear_attribute_changes: (untyped attr_names) -> untyped # Returns a hash of the attributes with unsaved changes indicating their original # values like attr => original value. # # person.name # => "bob" # person.name = 'robert' # person.changed_attributes # => {"name" => "bob"} def changed_attributes: () -> untyped # Returns a hash of changed attributes indicating their original # and new values like attr => [original value, new value]. # # person.changes # => {} # person.name = 'bob' # person.changes # => { "name" => ["bill", "bob"] } def changes: () -> untyped # Returns a hash of attributes that were changed before the model was saved. # # person.name # => "bob" # person.name = 'robert' # person.save # person.previous_changes # => {"name" => ["bob", "robert"]} def previous_changes: () -> untyped def attribute_changed_in_place?: (untyped attr_name) -> untyped private def clear_attribute_change: (untyped attr_name) -> untyped def mutations_from_database: () -> untyped def forget_attribute_assignments: () -> untyped def mutations_before_last_save: () -> untyped # Dispatch target for *_change attribute methods. def attribute_change: (untyped attr_name) -> untyped # Dispatch target for *_previous_change attribute methods. def attribute_previous_change: (untyped attr_name) -> untyped # Dispatch target for *_will_change! attribute methods. def attribute_will_change!: (untyped attr_name) -> untyped # Dispatch target for restore_*! attribute methods. def restore_attribute!: (untyped attr_name) -> untyped end end module ActiveModel # == Active \Model \Errors # # Provides a modified +Hash+ that you can include in your object # for handling error messages and interacting with Action View 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, :blank, message: "cannot 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 self.human_attribute_name(attr, options = {}) # attr # end # # def self.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: # # person = Person.new # person.validate! # => ["cannot be nil"] # person.errors.full_messages # => ["name cannot be nil"] # # etc.. class Errors include Enumerable[untyped] CALLBACKS_OPTIONS: ::Array[untyped] MESSAGE_OPTIONS: ::Array[untyped] attr_accessor self.i18n_customize_full_message: untyped attr_reader messages: untyped attr_reader details: untyped # 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: (untyped base) -> untyped def initialize_dup: (untyped other) -> untyped def copy!: (untyped other) -> untyped # Merges the errors from other. # # other - The ActiveModel::Errors instance. # # Examples # # person.errors.merge!(other) def merge!: (untyped other) -> untyped # Removes all errors except the given keys. Returns a hash containing the removed errors. # # person.errors.keys # => [:name, :age, :gender, :city] # person.errors.slice!(:age, :gender) # => { :name=>["cannot be nil"], :city=>["cannot be nil"] } # person.errors.keys # => [:age, :gender] def slice!: (*untyped keys) -> untyped # Clear the error messages. # # person.errors.full_messages # => ["name cannot be nil"] # person.errors.clear # person.errors.full_messages # => [] def clear: () -> untyped # Returns +true+ if the error messages include an error for the given key # +attribute+, +false+ otherwise. # # person.errors.messages # => {:name=>["cannot be nil"]} # person.errors.include?(:name) # => true # person.errors.include?(:age) # => false def include?: (untyped attribute) -> untyped alias has_key? include? alias key? include? # Delete messages for +key+. Returns the deleted messages. # # person.errors[:name] # => ["cannot be nil"] # person.errors.delete(:name) # => ["cannot be nil"] # person.errors[:name] # => [] def delete: (untyped key) -> untyped # When passed a symbol or a name of a method, returns an array of errors # for the method. # # person.errors[:name] # => ["cannot be nil"] # person.errors['name'] # => ["cannot be nil"] def []: (untyped attribute) -> untyped # 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. # # person.errors.add(:name, :blank, message: "can't be blank") # person.errors.each do |attribute, error| # # Will yield :name and "can't be blank" # end # # person.errors.add(:name, :not_specified, message: "must be specified") # person.errors.each do |attribute, error| # # Will yield :name and "can't be blank" # # then yield :name and "must be specified" # end def each: () { ([untyped, untyped]) -> untyped } -> untyped # Returns the number of error messages. # # person.errors.add(:name, :blank, message: "can't be blank") # person.errors.size # => 1 # person.errors.add(:name, :not_specified, message: "must be specified") # person.errors.size # => 2 def size: () -> untyped alias count size # Returns all message values. # # person.errors.messages # => {:name=>["cannot be nil", "must be specified"]} # person.errors.values # => [["cannot be nil", "must be specified"]] def values: () -> untyped # Returns all message keys. # # person.errors.messages # => {:name=>["cannot be nil", "must be specified"]} # person.errors.keys # => [:name] def keys: () -> untyped # Returns +true+ if no errors are found, +false+ otherwise. # If the error message is a string it can be empty. # # person.errors.full_messages # => ["name cannot be nil"] # person.errors.empty? # => false def empty?: () -> untyped alias blank? empty? # Returns an xml formatted representation of the Errors hash. # # person.errors.add(:name, :blank, message: "can't be blank") # person.errors.add(:name, :not_specified, message: "must be specified") # person.errors.to_xml # # => # # # # # # name can't be blank # # name must be specified # # def to_xml: (?::Hash[untyped, untyped] options) -> untyped # Returns a Hash that can be used as the JSON representation for this # object. You can pass the :full_messages option. This determines # if the json object should contain full messages or not (false by default). # # person.errors.as_json # => {:name=>["cannot be nil"]} # person.errors.as_json(full_messages: true) # => {:name=>["name cannot be nil"]} def as_json: (?untyped? options) -> untyped # Returns a Hash of attributes with their error messages. If +full_messages+ # is +true+, it will contain full messages (see +full_message+). # # person.errors.to_hash # => {:name=>["cannot be nil"]} # person.errors.to_hash(true) # => {:name=>["name cannot be nil"]} def to_hash: (?bool full_messages) -> untyped # Adds +message+ to the error messages and used validator type to +details+ on +attribute+. # More than one error can be added to the same +attribute+. # If no +message+ is supplied, :invalid is assumed. # # person.errors.add(:name) # # => ["is invalid"] # person.errors.add(:name, :not_implemented, message: "must be implemented") # # => ["is invalid", "must be implemented"] # # person.errors.messages # # => {:name=>["is invalid", "must be implemented"]} # # person.errors.details # # => {:name=>[{error: :not_implemented}, {error: :invalid}]} # # If +message+ is a symbol, it will be translated using the appropriate # scope (see +generate_message+). # # If +message+ is a proc, it will be called, allowing for things like # Time.now to be used within an error. # # If the :strict option is set to +true+, it will raise # ActiveModel::StrictValidationFailed instead of adding the error. # :strict option can also be set to any other exception. # # person.errors.add(:name, :invalid, strict: true) # # => ActiveModel::StrictValidationFailed: Name is invalid # person.errors.add(:name, :invalid, strict: NameIsInvalid) # # => NameIsInvalid: Name is invalid # # person.errors.messages # => {} # # +attribute+ should be set to :base if the error is not # directly associated with a single attribute. # # person.errors.add(:base, :name_or_email_blank, # message: "either name or email must be present") # person.errors.messages # # => {:base=>["either name or email must be present"]} # person.errors.details # # => {:base=>[{error: :name_or_email_blank}]} def add: (untyped attribute, ?::Symbol message, ?::Hash[untyped, untyped] options) -> untyped # Returns +true+ if an error on the attribute with the given message is # present, or +false+ otherwise. +message+ is treated the same as for +add+. # # person.errors.add :name, :blank # person.errors.added? :name, :blank # => true # person.errors.added? :name, "can't be blank" # => true # # If the error message requires options, then it returns +true+ with # the correct options, or +false+ with incorrect or missing options. # # person.errors.add :name, :too_long, { count: 25 } # person.errors.added? :name, :too_long, count: 25 # => true # person.errors.added? :name, "is too long (maximum is 25 characters)" # => true # person.errors.added? :name, :too_long, count: 24 # => false # person.errors.added? :name, :too_long # => false # person.errors.added? :name, "is too long" # => false def added?: (untyped attribute, ?::Symbol message, ?::Hash[untyped, untyped] options) -> untyped # Returns +true+ if an error on the attribute with the given message is # present, or +false+ otherwise. +message+ is treated the same as for +add+. # # person.errors.add :age # person.errors.add :name, :too_long, { count: 25 } # person.errors.of_kind? :age # => true # person.errors.of_kind? :name # => false # person.errors.of_kind? :name, :too_long # => true # person.errors.of_kind? :name, "is too long (maximum is 25 characters)" # => true # person.errors.of_kind? :name, :not_too_long # => false # person.errors.of_kind? :name, "is too long" # => false def of_kind?: (untyped attribute, ?::Symbol message) -> untyped # Returns all the full error messages in an array. # # class Person # validates_presence_of :name, :address, :email # validates_length_of :name, in: 5..30 # end # # person = Person.create(address: '123 First St.') # person.errors.full_messages # # => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"] def full_messages: () -> untyped alias to_a full_messages # Returns all the full error messages for a given attribute in an array. # # class Person # validates_presence_of :name, :email # validates_length_of :name, in: 5..30 # end # # person = Person.create() # person.errors.full_messages_for(:name) # # => ["Name is too short (minimum is 5 characters)", "Name can't be blank"] def full_messages_for: (untyped attribute) -> untyped # Returns a full message for a given attribute. # # person.errors.full_message(:name, 'is invalid') # => "Name is invalid" # # The `"%{attribute} %{message}"` error format can be overridden with either # # * activemodel.errors.models.person/contacts/addresses.attributes.street.format # * activemodel.errors.models.person/contacts/addresses.format # * activemodel.errors.models.person.attributes.name.format # * activemodel.errors.models.person.format # * errors.format def full_message: (untyped attribute, untyped message) -> untyped # Translates an error message in its default scope # (activemodel.errors.messages). # # Error messages are first looked up in activemodel.errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE, # if it's not there, it's looked up in activemodel.errors.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: (untyped attribute, ?::Symbol `type`, ?::Hash[untyped, untyped] options) -> untyped def marshal_dump: () -> ::Array[untyped] def marshal_load: (untyped array) -> untyped def init_with: (untyped coder) -> untyped private def normalize_message: (untyped attribute, untyped message, untyped options) -> untyped def normalize_detail: (untyped message, untyped options) -> untyped def without_default_proc: (untyped hash) -> untyped def apply_default_array: (untyped hash) -> untyped end # Raised when a validation cannot be corrected by end users and are considered # exceptional. # # class Person # include ActiveModel::Validations # # attr_accessor :name # # validates_presence_of :name, strict: true # end # # person = Person.new # person.name = nil # person.valid? # # => ActiveModel::StrictValidationFailed: Name can't be blank class StrictValidationFailed < StandardError end # Raised when attribute values are out of range. class RangeError < ::RangeError end # Raised when unknown attributes are supplied via mass assignment. # # class Person # include ActiveModel::AttributeAssignment # include ActiveModel::Validations # end # # person = Person.new # person.assign_attributes(name: 'Gorby') # # => ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person. class UnknownAttributeError[T] < NoMethodError[T] attr_reader record: untyped attr_reader attribute: untyped def initialize: (untyped record, untyped attribute) -> untyped end end module ActiveModel # Raised when forbidden attributes are used for mass assignment. # # class Person < ActiveRecord::Base # end # # params = ActionController::Parameters.new(name: 'Bob') # Person.new(params) # # => ActiveModel::ForbiddenAttributesError # # params.permit! # Person.new(params) # # => # class ForbiddenAttributesError < StandardError end module ForbiddenAttributesProtection private def sanitize_for_mass_assignment: (untyped attributes) -> untyped alias sanitize_forbidden_attributes sanitize_for_mass_assignment end end module ActiveModel # Returns the version of the currently loaded \Active \Model as a Gem::Version def self.gem_version: () -> Gem::Version module VERSION MAJOR: ::Integer MINOR: ::Integer TINY: ::Integer PRE: ::String STRING: untyped end end module 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. # # Note an object is not required to implement all APIs in order to work # with Action Pack. This module only intends to provide guidance in case # you want all features out of the box. # # 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 # Passes if the object's model responds to to_key and if calling # this method returns +nil+ when the object is not persisted. # Fails otherwise. # # to_key returns an Enumerable of all (primary) key attributes # of the model, and is used to a generate unique DOM id for the object. def test_to_key: () -> untyped # Passes if the object's model responds to to_param and if # calling this method returns +nil+ when the object is not persisted. # Fails otherwise. # # to_param is used to represent the object's key in URLs. # 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. def test_to_param: () -> untyped # Passes if the object's model responds to to_partial_path and if # calling this method returns a string. Fails otherwise. # # to_partial_path is used for looking up partials. For example, # a BlogPost model might return "blog_posts/blog_post". def test_to_partial_path: () -> untyped # Passes if the object's model responds to persisted? and if # calling this method returns either +true+ or +false+. Fails otherwise. # # persisted? is used when calculating the URL for an object. # If the object is not persisted, a form for that object, for instance, # will route to the create action. If it is persisted, a form for the # object will route to the update action. def test_persisted?: () -> untyped # Passes if the object's model responds to model_name both as # an instance method and as a class method, and if calling this method # returns a string with some convenience methods: :human, # :singular and :plural. # # Check ActiveModel::Naming for more information. def test_model_naming: () -> untyped # Passes if the object's model responds to errors and if calling # [](attribute) on the result of this method returns an array. # Fails otherwise. # # errors[attribute] is used to retrieve the errors of a model # for a given attribute. If errors are present, the method should return # 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, the method should return an empty array. def test_errors_aref: () -> untyped private def model: () -> untyped def assert_boolean: (untyped result, untyped name) -> untyped end end end module ActiveModel # == Active \Model \Basic \Model # # Includes the required interface for an object to interact with # Action Pack and Action View, using different Active Model modules. # It includes model name introspections, conversions, translations and # validations. Besides that, it allows you to initialize the object with a # hash of attributes, pretty much like Active Record does. # # A minimal implementation could be: # # class Person # include ActiveModel::Model # attr_accessor :name, :age # end # # person = Person.new(name: 'bob', age: '18') # person.name # => "bob" # person.age # => "18" # # Note that, by default, ActiveModel::Model implements persisted? # to return +false+, which is the most common case. You may want to override # it in your class to simulate a different scenario: # # class Person # include ActiveModel::Model # attr_accessor :id, :name # # def persisted? # self.id == 1 # end # end # # person = Person.new(id: 1, name: 'bob') # person.persisted? # => true # # Also, if for some reason you need to run code on initialize, make # sure you call +super+ if you want the attributes hash initialization to # happen. # # class Person # include ActiveModel::Model # attr_accessor :id, :name, :omg # # def initialize(attributes={}) # super # @omg ||= true # end # end # # person = Person.new(id: 1, name: 'bob') # person.omg # => true # # For more detailed information on other functionalities available, please # refer to the specific modules included in ActiveModel::Model # (see below). module Model extend ActiveSupport::Concern include ActiveModel::AttributeAssignment include ActiveModel::Validations include ActiveModel::Conversion extend ActiveModel::Naming extend ActiveModel::Translation # Initializes a new model with the given +params+. # # class Person # include ActiveModel::Model # attr_accessor :name, :age # end # # person = Person.new(name: 'bob', age: '18') # person.name # => "bob" # person.age # => "18" def initialize: (?::Hash[untyped, untyped] attributes) -> untyped # Indicates if the model is persisted. Default is +false+. # # class Person # include ActiveModel::Model # attr_accessor :id, :name # end # # person = Person.new(id: 1, name: 'bob') # person.persisted? # => false def persisted?: () -> ::FalseClass end end module ActiveModel class Name include Comparable attr_reader singular: untyped attr_reader plural: untyped attr_reader element: untyped attr_reader collection: untyped attr_reader singular_route_key: untyped attr_reader route_key: untyped attr_reader param_key: untyped attr_reader i18n_key: untyped attr_reader name: untyped alias cache_key collection # Returns a new ActiveModel::Name instance. By default, the +namespace+ # and +name+ option will take the namespace and name of the given class # respectively. # # module Foo # class Bar # end # end # # ActiveModel::Name.new(Foo::Bar).to_s # # => "Foo::Bar" def initialize: (untyped klass, ?untyped? namespace, ?untyped? name) -> untyped # Transform the model name into a more human format, using I18n. By default, # it will underscore then humanize the class name. # # class BlogPost # extend ActiveModel::Naming # end # # BlogPost.model_name.human # => "Blog post" # # Specify +options+ with additional translating options. def human: (?::Hash[untyped, untyped] options) -> untyped private def _singularize: (untyped string) -> untyped 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.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 def self.extended: (untyped base) -> untyped # Returns an ActiveModel::Name object for module. It can be # used to retrieve all kinds of naming-related information # (See ActiveModel::Name for more information). # # class Person # extend ActiveModel::Naming # end # # Person.model_name.name # => "Person" # Person.model_name.class # => ActiveModel::Name # Person.model_name.singular # => "person" # Person.model_name.plural # => "people" def model_name: () -> untyped # Returns the plural class name of a record or class. # # ActiveModel::Naming.plural(post) # => "posts" # ActiveModel::Naming.plural(Highrise::Person) # => "highrise_people" def self.plural: (untyped record_or_class) -> untyped # Returns the singular class name of a record or class. # # ActiveModel::Naming.singular(post) # => "post" # ActiveModel::Naming.singular(Highrise::Person) # => "highrise_person" def self.singular: (untyped record_or_class) -> untyped # Identifies whether the class name of a record or class is uncountable. # # ActiveModel::Naming.uncountable?(Sheep) # => true # ActiveModel::Naming.uncountable?(Post) # => false def self.uncountable?: (untyped record_or_class) -> untyped # 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.singular_route_key(Blog::Post) # => "post" # # # For shared engine: # ActiveModel::Naming.singular_route_key(Blog::Post) # => "blog_post" def self.singular_route_key: (untyped record_or_class) -> untyped # 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: (untyped record_or_class) -> untyped # 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: (untyped record_or_class) -> untyped def self.model_name_from_record_or_class: (untyped record_or_class) -> untyped end end module ActiveModel class Railtie < Rails::Railtie end end module ActiveModel module SecurePassword extend ActiveSupport::Concern # BCrypt hash function can handle maximum 72 bytes, and if we pass # password of length more than 72 bytes it ignores extra characters. # Hence need to put a restriction on password length. MAX_PASSWORD_LENGTH_ALLOWED: ::Integer attr_accessor self.min_cost: untyped module ClassMethods # Adds methods to set and authenticate against a BCrypt password. # This mechanism requires you to have a +XXX_digest+ attribute. # Where +XXX+ is the attribute name of your desired password. # # The following validations are added automatically: # * Password must be present on creation # * Password length should be less than or equal to 72 bytes # * Confirmation of password (using a +XXX_confirmation+ attribute) # # If confirmation validation is not needed, simply leave out the # value for +XXX_confirmation+ (i.e. don't provide a form field for # it). When this attribute has a +nil+ value, the validation will not be # triggered. # # For further customizability, it is possible to suppress the default # validations by passing validations: false as an argument. # # Add bcrypt (~> 3.1.7) to Gemfile to use #has_secure_password: # # gem 'bcrypt', '~> 3.1.7' # # Example using Active Record (which automatically includes ActiveModel::SecurePassword): # # # Schema: User(name:string, password_digest:string, recovery_password_digest:string) # class User < ActiveRecord::Base # has_secure_password # has_secure_password :recovery_password, validations: false # 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.recovery_password = "42password" # user.recovery_password_digest # => "$2a$04$iOfhwahFymCs5weB3BNH/uXkTG65HR.qpW.bNhEjFP3ftli3o5DQC" # user.save # => true # user.authenticate('notright') # => false # user.authenticate('mUc3m00RsqyRe') # => user # user.authenticate_recovery_password('42password') # => user # User.find_by(name: 'david').try(:authenticate, 'notright') # => false # User.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe') # => user def has_secure_password: (?::Symbol attribute, ?validations: bool validations) -> untyped end class InstanceMethodsOnActivation < Module def initialize: (untyped attribute) -> untyped end end end module ActiveModel # == Active \Model \Serialization # # Provides a basic serialization to a serializable_hash for your objects. # # A minimal implementation could be: # # class Person # include ActiveModel::Serialization # # attr_accessor :name # # def attributes # {'name' => nil} # end # end # # Which would provide you with: # # person = Person.new # person.serializable_hash # => {"name"=>nil} # person.name = "Bob" # person.serializable_hash # => {"name"=>"Bob"} # # An +attributes+ hash must be defined and should contain any attributes you # need to be serialized. Attributes must be strings, not symbols. # When called, serializable hash will use instance methods that match the name # of the attributes hash's keys. In order to override this behavior, take a look # at the private method +read_attribute_for_serialization+. # # ActiveModel::Serializers::JSON module automatically includes # the ActiveModel::Serialization module, so there is no need to # explicitly include ActiveModel::Serialization. # # A minimal implementation including JSON would be: # # class Person # include ActiveModel::Serializers::JSON # # attr_accessor :name # # def attributes # {'name' => nil} # 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.name = "Bob" # person.serializable_hash # => {"name"=>"Bob"} # person.as_json # => {"name"=>"Bob"} # person.to_json # => "{\"name\":\"Bob\"}" # # Valid options are :only, :except, :methods and # :include. The following are all valid examples: # # person.serializable_hash(only: 'name') # person.serializable_hash(include: :address) # person.serializable_hash(include: { address: { only: 'city' }}) module Serialization # Returns a serialized hash of your object. # # class Person # include ActiveModel::Serialization # # attr_accessor :name, :age # # def attributes # {'name' => nil, 'age' => nil} # end # # def capitalized_name # name.capitalize # end # end # # person = Person.new # person.name = 'bob' # person.age = 22 # person.serializable_hash # => {"name"=>"bob", "age"=>22} # person.serializable_hash(only: :name) # => {"name"=>"bob"} # person.serializable_hash(except: :name) # => {"age"=>22} # person.serializable_hash(methods: :capitalized_name) # # => {"name"=>"bob", "age"=>22, "capitalized_name"=>"Bob"} # # Example with :include option # # class User # include ActiveModel::Serializers::JSON # attr_accessor :name, :notes # Emulate has_many :notes # def attributes # {'name' => nil} # end # end # # class Note # include ActiveModel::Serializers::JSON # attr_accessor :title, :text # def attributes # {'title' => nil, 'text' => nil} # end # end # # note = Note.new # note.title = 'Battle of Austerlitz' # note.text = 'Some text here' # # user = User.new # user.name = 'Napoleon' # user.notes = [note] # # user.serializable_hash # # => {"name" => "Napoleon"} # user.serializable_hash(include: { notes: { only: 'title' }}) # # => {"name" => "Napoleon", "notes" => [{"title"=>"Battle of Austerlitz"}]} def serializable_hash: (?untyped? options) -> untyped 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::Serialization # # def initialize(data = {}) # @data = data # end # # def read_attribute_for_serialization(key) # @data[key] # end # end alias read_attribute_for_serialization send def serializable_add_includes: (?::Hash[untyped, untyped] options) { (untyped, untyped, untyped) -> untyped } -> (nil | untyped) end end module ActiveModel module Serializers # == Active \Model \JSON \Serializer module JSON extend ActiveSupport::Concern include ActiveModel::Serialization extend ActiveModel::Naming # 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+, +as_json+ will emit a single root node named # after the object's type. The default value for include_root_in_json # option is +false+. # # user = User.find(1) # user.as_json # # => { "id" => 1, "name" => "Konata Izumi", "age" => 16, # # "created_at" => "2006-08-01T17:27:133.000Z", "awesome" => true} # # ActiveRecord::Base.include_root_in_json = true # # user.as_json # # => { "user" => { "id" => 1, "name" => "Konata Izumi", "age" => 16, # # "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true } } # # This behavior can also be achieved by setting the :root option # to +true+ as in: # # user = User.find(1) # user.as_json(root: true) # # => { "user" => { "id" => 1, "name" => "Konata Izumi", "age" => 16, # # "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true } } # # Without any +options+, the returned Hash will include all the model's # attributes. # # user = User.find(1) # user.as_json # # => { "id" => 1, "name" => "Konata Izumi", "age" => 16, # # "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true} # # The :only and :except options can be used to limit # the attributes included, and work similar to the +attributes+ method. # # 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-01T17:27:13.000Z", "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-01T17:27:13.000Z", "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-01T17:27:13.000Z", "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: (?untyped? options) -> untyped # Sets the model +attributes+ from a JSON string. Returns +self+. # # class Person # include ActiveModel::Serializers::JSON # # attr_accessor :name, :age, :awesome # # def attributes=(hash) # hash.each do |key, value| # send("#{key}=", value) # end # end # # def attributes # instance_values # end # end # # json = { name: 'bob', age: 22, awesome:true }.to_json # person = Person.new # person.from_json(json) # => # # person.name # => "bob" # person.age # => 22 # person.awesome # => true # # The default value for +include_root+ is +false+. You can change it to # +true+ if the given JSON string includes a single root node. # # json = { person: { name: 'bob', age: 22, awesome:true } }.to_json # person = Person.new # person.from_json(json, true) # => # # person.name # => "bob" # person.age # => 22 # person.awesome # => true def from_json: (untyped json, ?untyped include_root) -> untyped end end end 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 # 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: () -> untyped # 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: (untyped attribute, ?::Hash[untyped, untyped] options) -> untyped end end module ActiveModel module Type class BigInteger < Integer private def max_value: () -> untyped end end end module ActiveModel module Type class Binary < Value # :nodoc: def type: () -> :binary def binary?: () -> ::TrueClass def cast: (untyped value) -> untyped def serialize: (untyped value) -> (nil | Data) def changed_in_place?: (untyped raw_old_value, untyped value) -> untyped class Data # :nodoc: def initialize: (untyped value) -> untyped def to_s: () -> untyped alias to_str to_s def hex: () -> untyped def ==: (untyped other) -> untyped end end end end module ActiveModel module Type # == Active \Model \Type \Boolean # # A class that behaves like a boolean type, including rules for coercion of user input. # # === Coercion # Values set from user input will first be coerced into the appropriate ruby type. # Coercion behavior is roughly mapped to Ruby's boolean semantics. # # - "false", "f" , "0", +0+ or any other value in +FALSE_VALUES+ will be coerced to +false+ # - Empty strings are coerced to +nil+ # - All other values will be coerced to +true+ class Boolean < Value FALSE_VALUES: untyped def type: () -> :boolean def serialize: (untyped value) -> untyped private def cast_value: (untyped value) -> untyped end end end module ActiveModel module Type class Date < Value # :nodoc: include Helpers::Timezone def type: () -> :date def type_cast_for_schema: (untyped value) -> untyped private def cast_value: (untyped value) -> untyped ISO_DATE: untyped def fast_string_to_date: (untyped string) -> untyped def fallback_string_to_date: (untyped string) -> untyped def new_date: (untyped year, untyped mon, untyped mday) -> untyped def value_from_multiparameter_assignment: () -> untyped end end end module ActiveModel module Type class DateTime < Value # :nodoc: include Helpers::Timezone include Helpers::TimeValue def type: () -> :datetime private def cast_value: (untyped value) -> (untyped | nil) # '0.123456' -> 123456 # '1.123456' -> 123456 def microseconds: (untyped time) -> untyped def fallback_string_to_time: (untyped string) -> untyped def value_from_multiparameter_assignment: (untyped values_hash) -> untyped end end end module ActiveModel module Type class Decimal < Value # :nodoc: include Helpers::Numeric BIGDECIMAL_PRECISION: ::Integer def type: () -> :decimal def type_cast_for_schema: (untyped value) -> untyped private def cast_value: (untyped value) -> untyped def convert_float_to_big_decimal: (untyped value) -> untyped def float_precision: () -> untyped def apply_scale: (untyped value) -> untyped end end end module ActiveModel module Type class Float < Value # :nodoc: include Helpers::Numeric def type: () -> :float def type_cast_for_schema: (untyped value) -> ("::Float::NAN" | untyped) private def cast_value: (untyped value) -> untyped end end end module ActiveModel module Type module Helpers # :nodoc: all class AcceptsMultiparameterTime < Module def initialize: (?defaults: ::Hash[untyped, untyped] defaults) -> (nil | untyped) end end end end module ActiveModel module Type module Helpers # :nodoc: all module Mutable def cast: (untyped value) -> untyped # +raw_old_value+ will be the `_before_type_cast` version of the # value (likely a string). +new_value+ will be the current, type # cast value. def changed_in_place?: (untyped raw_old_value, untyped new_value) -> untyped end end end end module ActiveModel module Type module Helpers # :nodoc: all module Numeric def serialize: (untyped value) -> untyped def cast: (untyped value) -> untyped def changed?: (untyped old_value, untyped _new_value, untyped new_value_before_type_cast) -> untyped private def number_to_non_number?: (untyped old_value, untyped new_value_before_type_cast) -> untyped def non_numeric_string?: (untyped value) -> untyped NUMERIC_REGEX: untyped end end end end module ActiveModel module Type module Helpers # :nodoc: all module TimeValue def serialize: (untyped value) -> untyped def apply_seconds_precision: (untyped value) -> untyped def type_cast_for_schema: (untyped value) -> untyped def user_input_in_time_zone: (untyped value) -> untyped private def new_time: (untyped year, untyped mon, untyped mday, untyped hour, untyped min, untyped sec, untyped microsec, ?untyped? offset) -> (nil | untyped) ISO_DATETIME: untyped # Doesn't handle time zones. def fast_string_to_time: (untyped string) -> untyped end end end end module ActiveModel module Type module Helpers # :nodoc: all module Timezone def is_utc?: () -> untyped def default_timezone: () -> untyped end end end end module ActiveModel module Type class ImmutableString < Value # :nodoc: def type: () -> :string def serialize: (untyped value) -> untyped private def cast_value: (untyped value) -> untyped end end end module ActiveModel module Type class Integer < Value # :nodoc: include Helpers::Numeric # Column storage size in bytes. # 4 bytes means an integer as opposed to smallint etc. DEFAULT_LIMIT: ::Integer def initialize: () -> untyped def type: () -> :integer def deserialize: (untyped value) -> (nil | untyped) def serialize: (untyped value) -> (nil | untyped) private attr_reader range: untyped def cast_value: (untyped value) -> untyped def ensure_in_range: (untyped value) -> untyped def max_value: () -> untyped def min_value: () -> untyped def _limit: () -> untyped end end end module ActiveModel # :stopdoc: module Type class Registry def initialize: () -> untyped def register: (untyped type_name, ?untyped? klass, **untyped options) { () -> untyped } -> untyped def lookup: (untyped symbol, *untyped args, **untyped kwargs) -> untyped private attr_reader registrations: untyped def registration_klass: () -> untyped def find_registration: (untyped symbol, *untyped args) -> untyped end class Registration # Options must be taken because of https://bugs.ruby-lang.org/issues/10856 def initialize: (untyped name, untyped block) -> untyped def call: (untyped _registry, *untyped args, **untyped kwargs) -> untyped def matches?: (untyped type_name, *untyped args, **untyped kwargs) -> untyped private attr_reader name: untyped attr_reader block: untyped end end end module ActiveModel module Type class String < ImmutableString # :nodoc: def changed_in_place?: (untyped raw_old_value, untyped new_value) -> untyped private def cast_value: (untyped value) -> untyped end end end module ActiveModel module Type class Time < Value # :nodoc: include Helpers::Timezone include Helpers::TimeValue def type: () -> :time def user_input_in_time_zone: (untyped value) -> (nil | untyped) private def cast_value: (untyped value) -> (untyped | nil) end end end module ActiveModel module Type class Value attr_reader precision: untyped attr_reader scale: untyped attr_reader limit: untyped def initialize: (?scale: untyped? scale, ?limit: untyped? limit, ?precision: untyped? precision) -> untyped def type: () -> nil # Converts a value from database input to the appropriate ruby type. The # return value of this method will be returned from # ActiveRecord::AttributeMethods::Read#read_attribute. The default # implementation just calls Value#cast. # # +value+ The raw input, as provided from the database. def deserialize: (untyped value) -> untyped # Type casts a value from user input (e.g. from a setter). This value may # be a string from the form builder, or a ruby object passed to a setter. # There is currently no way to differentiate between which source it came # from. # # The return value of this method will be returned from # ActiveRecord::AttributeMethods::Read#read_attribute. See also: # Value#cast_value. # # +value+ The raw input, as provided to the attribute setter. def cast: (untyped value) -> untyped # Casts a value from the ruby type to a type that the database knows how # to understand. The returned value from this method should be a # +String+, +Numeric+, +Date+, +Time+, +Symbol+, +true+, +false+, or # +nil+. def serialize: (untyped value) -> untyped def type_cast_for_schema: (untyped value) -> untyped def binary?: () -> ::FalseClass # Determines whether a value has changed for dirty checking. +old_value+ # and +new_value+ will always be type-cast. Types should not need to # override this method. def changed?: (untyped old_value, untyped new_value, untyped _new_value_before_type_cast) -> untyped # Determines whether the mutable value has been modified since it was # read. Returns +false+ by default. If your type returns an object # which could be mutated, you should override this method. You will need # to either: # # - pass +new_value+ to Value#serialize and compare it to # +raw_old_value+ # # or # # - pass +raw_old_value+ to Value#deserialize and compare it to # +new_value+ # # +raw_old_value+ The original value, before being passed to # +deserialize+. # # +new_value+ The current value, after type casting. def changed_in_place?: (untyped raw_old_value, untyped new_value) -> ::FalseClass def value_constructed_by_mass_assignment?: (untyped _value) -> ::FalseClass def force_equality?: (untyped _value) -> ::FalseClass def map: (untyped value) { (untyped) -> untyped } -> untyped def ==: (untyped other) -> untyped alias eql? == def hash: () -> untyped def assert_valid_value: () -> nil private def cast_value: (untyped value) -> untyped end end end module ActiveModel module Type attr_accessor self.registry: untyped # Add a new type to the registry, allowing it to be gotten through ActiveModel::Type#lookup def self.register: (untyped type_name, ?untyped? klass, **untyped options) { () -> untyped } -> untyped def self.lookup: (*untyped args, **untyped kwargs) -> untyped def self.default_value: () -> untyped end end module ActiveModel module Validations class AbsenceValidator < EachValidator # == \Active \Model Absence Validator # nodoc: def validate_each: (untyped record, untyped attr_name, untyped value) -> untyped end module HelperMethods # Validates that the specified attributes are blank (as defined by # Object#present?). Happens by default on save. # # class Person < ActiveRecord::Base # validates_absence_of :first_name # end # # The first_name attribute must be in the object and it must be blank. # # Configuration options: # * :message - A custom error message (default is: "must be blank"). # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+. # See ActiveModel::Validations#validates for more information def validates_absence_of: (*untyped attr_names) -> untyped end end end module ActiveModel module Validations class AcceptanceValidator < EachValidator # :nodoc: def initialize: (untyped options) -> untyped def validate_each: (untyped record, untyped attribute, untyped value) -> untyped private def setup!: (untyped klass) -> untyped def acceptable_option?: (untyped value) -> untyped class LazilyDefineAttributes < Module def initialize: (untyped attributes) -> untyped def included: (untyped klass) -> untyped def matches?: (untyped method_name) -> untyped def define_on: (untyped klass) -> untyped def ==: (untyped other) -> untyped attr_reader attributes: untyped end end module HelperMethods # Encapsulates the pattern of wanting to validate the acceptance of a # terms of service check box (or similar agreement). # # 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"). # * :accept - Specifies a value that is considered accepted. # Also accepts an array of possible values. The default value is # an array ["1", true], which makes it easy to relate to an HTML # checkbox. This should be set to, or include, +true+ if you are validating # a database column, since the attribute is typecast from "1" to +true+ # before validation. # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+. # See ActiveModel::Validations#validates for more information. def validates_acceptance_of: (*untyped attr_names) -> untyped end end end module ActiveModel module Validations # == Active \Model \Validation \Callbacks # # Provides an interface for any class to have +before_validation+ and # +after_validation+ callbacks. # # First, include ActiveModel::Validations::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+ throws # +:abort+ then valid? will not be called. module Callbacks extend ActiveSupport::Concern include ActiveSupport::Callbacks module ClassMethods # Defines a callback that will get called right before validation. # # class Person # include ActiveModel::Validations # include ActiveModel::Validations::Callbacks # # attr_accessor :name # # validates_length_of :name, maximum: 6 # # before_validation :remove_whitespaces # # private # # def remove_whitespaces # name.strip! # end # end # # person = Person.new # person.name = ' bob ' # person.valid? # => true # person.name # => "bob" def before_validation: (*untyped args) { () -> untyped } -> untyped # Defines a callback that will get called right after validation. # # class Person # include ActiveModel::Validations # include ActiveModel::Validations::Callbacks # # attr_accessor :name, :status # # validates_presence_of :name # # after_validation :set_status # # private # # def set_status # self.status = errors.empty? # end # end # # person = Person.new # person.name = '' # person.valid? # => false # person.status # => false # person.name = 'bob' # person.valid? # => true # person.status # => true def after_validation: (*untyped args) { () -> untyped } -> untyped end private # Overwrite run validations to include callbacks. def run_validations!: () -> untyped end end end module ActiveModel module Validations module Clusivity # nodoc: ERROR_MESSAGE: ::String def check_validity!: () -> untyped private def include?: (untyped record, untyped value) -> untyped def delimiter: () -> untyped # After Ruby 2.2, Range#include? on non-number-or-time-ish ranges checks all # possible values in the range for equality, which is slower but more accurate. # Range#cover? uses the previous logic of comparing a value with the range # endpoints, which is fast but is only accurate on Numeric, Time, Date, # or DateTime ranges. def inclusion_method: (untyped enumerable) -> untyped end end end module ActiveModel module Validations class ConfirmationValidator < EachValidator # :nodoc: def initialize: (untyped options) -> untyped def validate_each: (untyped record, untyped attribute, untyped value) -> untyped private def setup!: (untyped klass) -> untyped def confirmation_value_equal?: (untyped record, untyped attribute, untyped value, untyped confirmed) -> untyped end module HelperMethods # Encapsulates the pattern of wanting to validate a password or email # address field with a confirmation. # # 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+. 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 # %{translated_attribute_name}"). # * :case_sensitive - Looks for an exact match. Ignored by # non-text columns (+true+ by default). # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+. # See ActiveModel::Validations#validates for more information def validates_confirmation_of: (*untyped attr_names) -> untyped end end end module ActiveModel module Validations class ExclusionValidator < EachValidator # :nodoc: include Clusivity def validate_each: (untyped record, untyped attribute, untyped value) -> untyped 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: ->(person) { [person.username, person.first_name] }, # message: 'should not be the same as your username or first name' # validates_exclusion_of :karma, in: :reserved_karmas # end # # Configuration options: # * :in - An enumerable object of items that the value shouldn't # be part of. This can be supplied as a proc, lambda or symbol which returns an # enumerable. If the enumerable is a numerical, time or datetime range the test # is performed with Range#cover?, otherwise with include?. When # using a proc or lambda the instance under validation is passed as an argument. # * :within - A synonym(or alias) for :in # Range#cover?, otherwise with include?. # * :message - Specifies a custom error message (default is: "is # reserved"). # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+. # See ActiveModel::Validations#validates for more information def validates_exclusion_of: (*untyped attr_names) -> untyped end end end module ActiveModel module Validations class FormatValidator < EachValidator # :nodoc: def validate_each: (untyped record, untyped attribute, untyped value) -> untyped def check_validity!: () -> untyped private def option_call: (untyped record, untyped name) -> untyped def record_error: (untyped record, untyped attribute, untyped name, untyped value) -> untyped def check_options_validity: (untyped name) -> untyped def regexp_using_multiline_anchors?: (untyped regexp) -> untyped 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: ->(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. # # Due to frequent misuse of ^ and $, you need to pass # the multiline: true option in case you use any of these two # anchors in the provided regular expression. In most cases, you should be # using \A and \z. # # 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"). # * :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. # * :multiline - Set to true if your regular expression contains # anchors that match the beginning or end of lines as opposed to the # beginning or end of the string. These anchors are ^ and $. # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+. # See ActiveModel::Validations#validates for more information def validates_format_of: (*untyped attr_names) -> untyped end end end module ActiveModel module Validations module HelperMethods private def _merge_attributes: (untyped attr_names) -> untyped end end end module ActiveModel module Validations class InclusionValidator < EachValidator # :nodoc: include Clusivity def validate_each: (untyped record, untyped attribute, untyped value) -> untyped 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 :role, in: %w( admin contributor ) # 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: ->(person) { STATES[person.country] } # validates_inclusion_of :karma, in: :available_karmas # end # # Configuration options: # * :in - An enumerable object of available items. This can be # supplied as a proc, lambda or symbol which returns an enumerable. If the # enumerable is a numerical, time or datetime range the test is performed # with Range#cover?, otherwise with include?. When using # a proc or lambda the instance under validation is passed as an argument. # * :within - A synonym(or alias) for :in # * :message - Specifies a custom error message (default is: "is # not included in the list"). # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+. # See ActiveModel::Validations#validates for more information def validates_inclusion_of: (*untyped attr_names) -> untyped end end end module ActiveModel module Validations class LengthValidator < EachValidator # :nodoc: MESSAGES: untyped CHECKS: untyped RESERVED_OPTIONS: ::Array[untyped] def initialize: (untyped options) -> untyped def check_validity!: () -> untyped def validate_each: (untyped record, untyped attribute, untyped value) -> untyped private def skip_nil_check?: (untyped key) -> untyped end module HelperMethods # Validates that the specified attributes match the length restrictions # supplied. Only one constraint option can be used at a time apart from # +:minimum+ and +:maximum+ that can be combined together: # # 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 :words_in_essay, minimum: 100, too_short: 'Your essay must be at least 100 words.' # # private # # def words_in_essay # essay.scan(/\w+/) # end # end # # Constraint options: # # * :minimum - The minimum size of the attribute. # * :maximum - The maximum size of the attribute. Allows +nil+ by # default if not used with +:minimum+. # * :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. # # Other options: # # * :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 (minimum 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. # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+ and +:strict+. # See ActiveModel::Validations#validates for more information def validates_length_of: (*untyped attr_names) -> untyped alias validates_size_of validates_length_of end end end module ActiveModel module Validations class NumericalityValidator < EachValidator # :nodoc: CHECKS: untyped RESERVED_OPTIONS: untyped INTEGER_REGEX: untyped HEXADECIMAL_REGEX: untyped def check_validity!: () -> untyped def validate_each: (untyped record, untyped attr_name, untyped value) -> (nil | untyped) private def is_number?: (untyped raw_value) -> untyped def parse_as_number: (untyped raw_value) -> untyped def is_integer?: (untyped raw_value) -> untyped def is_hexadecimal_literal?: (untyped raw_value) -> untyped def filtered_options: (untyped value) -> untyped def allow_only_integer?: (untyped record) -> untyped def record_attribute_changed_in_place?: (untyped record, untyped attr_name) -> untyped 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"). # * :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 Integer 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. # * :other_than - Specifies the value must be other than the # supplied value. # * :odd - Specifies the value must be an odd number. # * :even - Specifies the value must be an even number. # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+ . # See ActiveModel::Validations#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 # * :only_integer # # For example: # # class Person < ActiveRecord::Base # validates_numericality_of :width, less_than: ->(person) { person.height } # validates_numericality_of :width, greater_than: :minimum_weight # end def validates_numericality_of: (*untyped attr_names) -> untyped end end end module ActiveModel module Validations class PresenceValidator < EachValidator # :nodoc: def validate_each: (untyped record, untyped attr_name, untyped value) -> untyped end module HelperMethods # Validates that the specified attributes are not blank (as defined by # Object#blank?). Happens by default on save. # # 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"). # # There is also a list of default options supported by every validator: # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+. # See ActiveModel::Validations#validates for more information def validates_presence_of: (*untyped attr_names) -> untyped end end end module ActiveModel 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 # # The power of the +validates+ method comes when using custom validators # and default validators in one call for a given attribute. # # 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, 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. # # 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. # # validates :email, format: /@/ # validates :role, inclusion: %(admin contributor) # 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]. # # There is also a list of options that could be used along with validators: # # * :on - Specifies the contexts where this validation is active. # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. on: :create or # on: :custom_validation_context or # on: [:create, :custom_validation_context]) # * :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. # * :allow_nil - Skip validation if the attribute is +nil+. # * :allow_blank - Skip validation if the attribute is blank. # * :strict - If the :strict option is set to true # will raise ActiveModel::StrictValidationFailed instead of adding the error. # :strict option can also be set to any other exception. # # Example: # # validates :password, presence: true, confirmation: true, if: :password_required? # validates :token, length: 24, strict: TokenLengthException # # # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+, +:strict+ # and +:message+ can be given to one specific validator, as a hash: # # validates :password, presence: { if: :password_required?, message: 'is forgotten.' }, confirmation: true def validates: (*untyped attributes) -> untyped # This method is used to define validations that cannot be corrected by end # users and are 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 # the validation itself. # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates! :name, presence: true # end # # person = Person.new # person.name = '' # person.valid? # # => ActiveModel::StrictValidationFailed: Name can't be blank def validates!: (*untyped attributes) -> untyped private # 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: () -> ::Array[:if | :unless | :on | :allow_blank | :allow_nil | :strict] def _parse_validates_options: (untyped options) -> untyped end end end module ActiveModel module Validations class WithValidator < EachValidator # :nodoc: def validate_each: (untyped record, untyped attr, untyped val) -> untyped 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 the contexts where this validation is active. # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. on: :create or # on: :custom_validation_context or # on: [:create, :custom_validation_context]) # * :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::Validations#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: (*untyped args) ?{ () -> untyped } -> untyped 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: (*untyped args) { () -> untyped } -> untyped end end 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.messages # => {first_name:["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 extend ActiveModel::Naming extend ActiveModel::Callbacks extend ActiveModel::Translation extend HelperMethods include HelperMethods attr_accessor validation_context: untyped 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, allow_blank: true do |record, attr, value| # record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z # end # end # # Options: # * :on - Specifies the contexts where this validation is active. # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. on: :create or # on: :custom_validation_context or # on: [:create, :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: (*untyped attr_names) { () -> untyped } -> untyped VALID_OPTIONS_FOR_VALIDATE: untyped # 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 # # Note that the return value of validation methods is not relevant. # It's not possible to halt the validate callback chain. # # Options: # * :on - Specifies the contexts where this validation is active. # Runs in all validation contexts by default +nil+. You can pass a symbol # or an array of symbols. (e.g. on: :create or # on: :custom_validation_context or # on: [:create, :custom_validation_context]) # * :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. # # NOTE: Calling +validate+ multiple times on the same method will overwrite previous definitions. # def validate: (*untyped args) ?{ (untyped) -> untyped } -> untyped # List all validators that are being used to validate the model using # +validates_with+ method. # # class Person # include ActiveModel::Validations # # validates_with MyValidator # validates_with OtherValidator, on: :create # validates_with StrictValidator, strict: true # end # # Person.validators # # => [ # # #, # # #, # # # # # ] def validators: () -> untyped # Clears all of the validators and validations. # # Note that this will clear anything that is being used to validate # the model for both the +validates_with+ and +validate+ methods. # It clears the validators that are created with an invocation of # +validates_with+ and the callbacks that are set by an invocation # of +validate+. # # class Person # include ActiveModel::Validations # # validates_with MyValidator # validates_with OtherValidator, on: :create # validates_with StrictValidator, strict: true # validate :cannot_be_robot # # def cannot_be_robot # errors.add(:base, 'A person cannot be a robot') if person_is_robot # end # end # # Person.validators # # => [ # # #, # # #, # # # # # ] # # If one runs Person.clear_validators! and then checks to see what # validators this class has, you would obtain: # # Person.validators # => [] # # Also, the callback set by validate :cannot_be_robot will be erased # so that: # # Person._validate_callbacks.empty? # => true # def clear_validators!: () -> untyped # List all validators that are being used to validate a specific attribute. # # class Person # include ActiveModel::Validations # # attr_accessor :name , :age # # validates_presence_of :name # validates_inclusion_of :age, in: 0..99 # end # # Person.validators_on(:name) # # => [ # # #, # # ] def validators_on: (*untyped attributes) -> untyped # Returns +true+ if +attribute+ is an attribute method, +false+ otherwise. # # class Person # include ActiveModel::Validations # # attr_accessor :name # end # # User.attribute_method?(:name) # => true # User.attribute_method?(:age) # => false def attribute_method?: (untyped attribute) -> untyped def inherited: (untyped base) -> untyped end def initialize_dup: (untyped other) -> untyped # Returns the +Errors+ object that holds all information about attribute # error messages. # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name # end # # person = Person.new # person.valid? # => false # person.errors # => # def errors: () -> untyped # Runs all the specified validations and returns +true+ if no errors were # added otherwise +false+. # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name # end # # person = Person.new # person.name = '' # person.valid? # => false # person.name = 'david' # person.valid? # => true # # Context can optionally be supplied to define which callbacks to test # against (the context is defined on the validations using :on). # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name, on: :new # end # # person = Person.new # person.valid? # => true # person.valid?(:new) # => false def valid?: (?untyped? context) -> untyped alias validate valid? # Performs the opposite of valid?. Returns +true+ if errors were # added, +false+ otherwise. # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name # end # # person = Person.new # person.name = '' # person.invalid? # => true # person.name = 'david' # person.invalid? # => false # # Context can optionally be supplied to define which callbacks to test # against (the context is defined on the validations using :on). # # class Person # include ActiveModel::Validations # # attr_accessor :name # validates_presence_of :name, on: :new # end # # person = Person.new # person.invalid? # => false # person.invalid?(:new) # => true def invalid?: (?untyped? context) -> untyped # Runs all the validations within the specified context. Returns +true+ if # no errors are found, raises +ValidationError+ otherwise. # # Validations with no :on option will run no matter the context. Validations with # some :on option will only run in the specified context. def validate!: (?untyped? context) -> untyped # 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 private def run_validations!: () -> untyped def raise_validation_error: () -> untyped end # = Active Model ValidationError # # Raised by validate! when the model is invalid. Use the # +model+ method to retrieve the record which did not validate. # # begin # complex_operation_that_internally_calls_validate! # rescue ActiveModel::ValidationError => invalid # puts invalid.model.errors # end class ValidationError < StandardError attr_reader model: untyped def initialize: (untyped model) -> untyped end end module ActiveModel # == 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.add(: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 # # Note that the validator is initialized only once for the whole application # life cycle, and not on each validation run. # # The easiest way to add custom validators for validating individual attributes # is with the convenient ActiveModel::EachValidator. # # class TitleValidator < ActiveModel::EachValidator # def validate_each(record, attribute, value) # record.errors.add attribute, 'must be Mr., Mrs., or Dr.' unless %w(Mr. Mrs. Dr.).include?(value) # 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, title: true # end # # It can be useful to access the class that is using that validator when there are prerequisites such # as an +attr_accessor+ being present. This class is accessible via options[:class] in the constructor. # To setup your validator override the constructor. # # class MyValidator < ActiveModel::Validator # def initialize(options={}) # super # options[:class].attr_accessor :custom_attribute # end # end class Validator attr_reader options: untyped # Returns the kind of the validator. # # PresenceValidator.kind # => :presence # AcceptanceValidator.kind # => :acceptance def self.kind: () -> untyped # Accepts options that will be made available through the +options+ reader. def initialize: (?::Hash[untyped, untyped] options) -> untyped # Returns the kind for this validator. # # PresenceValidator.new(attributes: [:username]).kind # => :presence # AcceptanceValidator.new(attributes: [:terms]).kind # => :acceptance def kind: () -> untyped # Override this method in subclasses with validation logic, adding errors # to the records +errors+ array where necessary. def validate: (untyped record) -> untyped end class EachValidator < Validator # +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. # nodoc: attr_reader attributes: untyped # 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: (untyped options) -> untyped # Performs validation on the supplied record. By default this will call # +validate_each+ to determine validity therefore subclasses should # override +validate_each+ with validation logic. def validate: (untyped record) -> untyped # Override this method in subclasses with the validation logic, adding # errors to the records +errors+ array where necessary. def validate_each: (untyped record, untyped attribute, untyped value) -> untyped # 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!: () -> nil end class BlockValidator < EachValidator # +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. # nodoc: def initialize: (untyped options) { () -> untyped } -> untyped private def validate_each: (untyped record, untyped attribute, untyped value) -> untyped end end module ActiveModel # Returns the version of the currently loaded \Active \Model as a Gem::Version def self.version: () -> untyped end module ActiveModel extend ActiveSupport::Autoload module Serializers extend ActiveSupport::Autoload end def self.eager_load!: () -> untyped end