validated_object 1.1.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 97d91eb8801c44a0daecab2f6bf5e66c1dc34908
4
- data.tar.gz: b53ae1848ed9176217969907ff95d4ceb6f0d06b
2
+ SHA256:
3
+ metadata.gz: beeec5e7c798a88c65b4f5a492ce3e59505dacf6a0a1f8de4da90ca59c73f873
4
+ data.tar.gz: 3c18ec02b076c71a020eaf7825fa2014321e09ee43a5490373698bfd8deb3c59
5
5
  SHA512:
6
- metadata.gz: 7df6a6cacb4a691183fe606828b572a74e08b139d136e8e6826e5fd2ff3f441443b2f4ef451da96a65040075a46ecfee7e123da9f1ed911308c26b586e0482fe
7
- data.tar.gz: 86ff719a5c3f23f76f843c049a1071b5ff79e6b20953ca482a3cedf33904adde167553d6efce284e067a0f69bb3841534f1bceb2d29a6bd01ed1dacd77bd8931
6
+ metadata.gz: 279331de46a2f201ee2eafcb1633ab0ad3b428fa7651276e7754a4e06b6a740f1c473fd14e6296d428d74e3ee39c962bdbcc0e0ebaf6f7bbc7a7fdd393bc56c1
7
+ data.tar.gz: afe9a3252da50c7bd028ebbfec81729e0ecf71e0c8c5ff1272d31e616593d41e031a87b11602cfb0337dac3c21d0abad1af024007757c3cab462df66c79fa163
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1
4
3
  - 2.2.2
5
- before_install: gem install bundler -v 1.10.6
4
+ - 2.3.1
5
+ - 2.7.1
6
+ before_install: gem install bundler
data/README.md CHANGED
@@ -1,28 +1,18 @@
1
- [![Gem Version](https://badge.fury.io/rb/validated_object.svg)](https://badge.fury.io/rb/validated_object) [![Build Status](https://travis-ci.org/dogweather/validated_object.svg?branch=master)](https://travis-ci.org/dogweather/validated_object) [![Code Climate](https://codeclimate.com/github/dogweather/validated_object/badges/gpa.svg)](https://codeclimate.com/github/dogweather/validated_object)
1
+ [![Gem Version](https://badge.fury.io/rb/validated_object.svg)](https://badge.fury.io/rb/validated_object) [![Build Status](https://travis-ci.org/public-law/validated_object.svg?branch=master)](https://travis-ci.org/public-law/validated_object) [![Code Climate](https://codeclimate.com/github/dogweather/validated_object/badges/gpa.svg)](https://codeclimate.com/github/dogweather/validated_object)
2
2
 
3
3
  # ValidatedObject
4
4
 
5
- Uses
6
- [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates)
7
- to create self-validating Plain Old Ruby objects. I wrote it for helping with CSV data imports into my Rails apps.
8
- Very readable error messages are also important in that context, to track down parsing errors. This gem provides those too.
5
+ Plain Old Ruby Objects + Rails Validations = **self-checking Ruby objects**.
9
6
 
10
7
 
11
- ## Installation
8
+ ## Goals
12
9
 
13
- Add this line to your application's Gemfile:
10
+ * Very readable error messages
11
+ * Clean, minimal syntax
14
12
 
15
- ```ruby
16
- gem 'validated_object'
17
- ```
13
+ This is a small layer around
14
+ [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates). (About 18 lines of code.) So if you know how to use Rails Validations, you're good to go. I wrote this to help with CSV data imports and [website microdata generation](https://github.com/dogweather/schema-dot-org).
18
15
 
19
- And then execute:
20
-
21
- $ bundle
22
-
23
- Or install it yourself as:
24
-
25
- $ gem install validated_object
26
16
 
27
17
  ## Usage
28
18
 
@@ -33,47 +23,119 @@ All of the [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveM
33
23
 
34
24
  ```ruby
35
25
  class Dog < ValidatedObject::Base
36
- attr_accessor :name, :birthday
26
+ # Plain old Ruby
27
+ attr_accessor :name, :birthday # attr_reader is supported as well for read-only attributes
37
28
 
29
+ # Plain old Rails
38
30
  validates :name, presence: true
39
- validates :birthday, type: Date, allow_nil: true
31
+
32
+ # A new type-validation if you'd like to use it
33
+ validates :birthday, type: Date, allow_nil: true # Strongly typed but optional
40
34
  end
41
35
  ```
42
36
 
37
+ The included `TypeValidator` is what enables `type: Date`, above. All classes can be checked, as well as a pseudo-class `Boolean`. E.g.:
38
+
39
+ ```ruby
40
+ #...
41
+ validates :premium_membership, type: Boolean
42
+ #...
43
+ ```
44
+
43
45
  ### Instantiating and automatically validating
44
46
 
45
47
  ```ruby
46
- # The dog1 instance validates itself at the end of instantiation.
47
- # Here, it succeeds and so doesn't raise an exception.
48
- dog1 = Dog.new do |d|
49
- d.name = 'Spot'
50
- end
48
+ # This Dog instance validates itself at the end of instantiation.
49
+ spot = Dog.new(name: 'Spot')
50
+ ```
51
51
 
52
- # We can also explicitly test for validity
53
- dog1.valid? # => true
52
+ ```ruby
53
+ # We can also explicitly test for validity because all of
54
+ # ActiveModel::Validations is available.
55
+ spot.valid? # => true
54
56
 
55
- dog1.birthday = Date.new(2015, 1, 23)
56
- dog1.valid? # => true
57
+ spot.birthday = Date.new(2015, 1, 23)
58
+ spot.valid? # => true
57
59
  ```
58
60
 
59
- ### Making an instance _invalid_
61
+ ### Good error messages
62
+
63
+ Any of the standard Validations methods can be
64
+ used to test an instance, plus the custom `check_validations!` convenience method:
60
65
 
61
66
  ```ruby
62
- dog1.birthday = '2015-01-23'
63
- dog1.valid? # => false
64
- dog1.check_validations! # => ArgumentError: Birthday is class String, not Date
67
+ spot.birthday = '2015-01-23'
68
+ spot.valid? # => false
69
+ spot.check_validations! # => ArgumentError: Birthday is a String, not a Date
65
70
  ```
66
71
 
72
+ Note the clear, explicit error message. These are great when reading a log
73
+ file following a data import. It describes all the invalid conditions. Let's
74
+ test it by making another attribute invalid:
75
+
76
+ ```ruby
77
+ spot.name = nil
78
+ spot.check_validations! # => ArgumentError: Name can't be blank; Birthday is a String, not a Date
79
+ ```
80
+
81
+
82
+ ### Use in parsing data
83
+
84
+ I often use a validated object in a loop to import data, e.g.:
85
+
86
+ ```ruby
87
+ # Import a CSV file of dogs
88
+ dogs = []
89
+ csv.next_row do |row|
90
+ begin
91
+ dogs << Dog.new(name: row.name)
92
+ rescue ArgumentError => e
93
+ logger.warn(e)
94
+ end
95
+ end
96
+ ```
97
+
98
+ The result is that `dogs` is an array of guaranteed valid Dog objects. And the
99
+ error log lists unparseable rows with good info for tracking down problems in
100
+ the data.
101
+
102
+ ### Use in code generation
103
+
104
+ My [Schema.org microdata generation gem](https://github.com/dogweather/schema-dot-org) uses ValidatedObjects to recursively create well formed HTML / JSON-LD.
105
+
106
+ ## Installation
107
+
108
+ Add this line to your application's Gemfile:
109
+
110
+ ```ruby
111
+ gem 'validated_object'
112
+ ```
113
+
114
+ And then execute:
115
+
116
+ $ bundle
117
+
118
+ Or install it yourself as:
119
+
120
+ $ gem install validated_object
121
+
122
+
67
123
 
68
124
  ## Development
69
125
 
70
- (TODO: Verify these instructions.) After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
126
+ (TODO: Verify these instructions.) After checking out the repo, run `bin/setup`
127
+ to install dependencies. Then, run `rake spec` to run the tests. You can also
128
+ run `bin/console` for an interactive prompt that will allow you to experiment.
71
129
 
72
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
130
+ To install this gem onto your local machine, run `bundle exec rake install`. To
131
+ release a new version, update the version number in `version.rb`, and then run
132
+ `bundle exec rake release`, which will create a git tag for the version, push
133
+ git commits and tags, and push the `.gem` file to
134
+ [rubygems.org](https://rubygems.org).
73
135
 
74
136
  ## Contributing
75
137
 
76
- Bug reports and pull requests are welcome on GitHub at https://github.com/dogweather/validated_object.
138
+ Bug reports and pull requests are welcome on GitHub.
77
139
 
78
140
 
79
141
  ## License
@@ -1,11 +1,15 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
1
4
  require 'active_model'
5
+ require 'sorbet-runtime'
2
6
  require 'validated_object/version'
3
7
 
4
8
  module ValidatedObject
5
9
  # @abstract Subclass and add `attr_accessor` and validations
6
10
  # to create custom validating objects.
7
11
  #
8
- # Uses [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates)
12
+ # Uses {http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates ActiveModel::Validations}
9
13
  # to create self-validating Plain Old Ruby objects. This is especially
10
14
  # useful when importing data from one system into another. This class also
11
15
  # creates very readable error messages.
@@ -21,9 +25,7 @@ module ValidatedObject
21
25
  # @example Instantiating and automatically validating
22
26
  # # The dog1 instance validates itself at the end of instantiation.
23
27
  # # Here, it succeeds and so doesn't raise an exception.
24
- # dog1 = Dog.new do |d|
25
- # d.name = 'Spot'
26
- # end
28
+ # dog1 = Dog.new name: 'Spot'
27
29
  #
28
30
  # # We can also explicitly test for validity
29
31
  # dog1.valid? # => true
@@ -41,28 +43,41 @@ module ValidatedObject
41
43
  # @see http://www.rubyinside.com/rails-3-0s-activemodel-how-to-give-ruby-classes-some-activerecord-magic-2937.html Rails 3.0′s ActiveModel: How To Give Ruby Classes Some ActiveRecord Magic, Peter Cooper
42
44
  class Base
43
45
  include ActiveModel::Validations
46
+ extend T::Sig
47
+
48
+ SymbolHash = T.type_alias { T::Hash[Symbol, T.untyped] }
49
+
50
+ EMPTY_HASH = T.let({}.freeze, SymbolHash)
44
51
 
45
- # Implements a pseudo-boolean class.
52
+ # A private class definition, not intended to
53
+ # be used directly. Implements a pseudo-boolean class
54
+ # enabling validations like this:
55
+ #
56
+ # validates :enabled, type: Boolean
46
57
  class Boolean
47
58
  end
48
59
 
49
60
  # Instantiate and validate a new object.
50
- #
51
- # @yieldparam [ValidatedObject] new_object the yielded new object
52
- # for configuration.
61
+ # @example
62
+ # maru = Dog.new(birthday: Date.today, name: 'Maru')
53
63
  #
54
64
  # @raise [ArgumentError] if the object is not valid at the
55
- # end of initialization.
56
- def initialize
57
- yield(self)
65
+ # end of initialization or `attributes` is not a Hash.
66
+ sig { params(attributes: SymbolHash).returns(ValidatedObject::Base)}
67
+ def initialize(attributes = EMPTY_HASH)
68
+ set_instance_variables from_hash: attributes
58
69
  check_validations!
59
70
  self
60
71
  end
61
72
 
62
73
  # Run any validations and raise an error if invalid.
74
+ #
63
75
  # @raise [ArgumentError] if any validations fail.
76
+ # @return [ValidatedObject::Base] the receiver
77
+ sig {returns(ValidatedObject::Base)}
64
78
  def check_validations!
65
79
  raise ArgumentError, errors.full_messages.join('; ') if invalid?
80
+
66
81
  self
67
82
  end
68
83
 
@@ -70,25 +85,79 @@ module ValidatedObject
70
85
  # or a subclass. It supports a pseudo-boolean class for convenient
71
86
  # validation. (Ruby doesn't have a built-in Boolean.)
72
87
  #
88
+ # Automatically used in a `type` validation:
89
+ #
73
90
  # @example Ensure that weight is a number
74
91
  # class Dog < ValidatedObject::Base
75
92
  # attr_accessor :weight, :neutered
76
- # validates :weight, type: Numeric
77
- # validates :neutered, type: Boolean
93
+ # validates :weight, type: Numeric # Typed and required
94
+ # validates :neutered, type: Boolean, allow_nil: true # Typed but optional
78
95
  # end
79
96
  class TypeValidator < ActiveModel::EachValidator
97
+ extend T::Sig
98
+
80
99
  # @return [nil]
100
+ sig do
101
+ params(
102
+ record: T.untyped,
103
+ attribute: T.untyped,
104
+ value: T.untyped
105
+ )
106
+ .void
107
+ end
81
108
  def validate_each(record, attribute, value)
82
- expected_class = options[:with]
109
+ validation_options = T.let(options, SymbolHash)
110
+
111
+ expected_class = validation_options[:with]
112
+
113
+ return if pseudo_boolean?(expected_class, value) ||
114
+ expected_class?(expected_class, value)
115
+
116
+ save_error(record, attribute, value, validation_options)
117
+ end
118
+
119
+ private
120
+
121
+ sig {params(expected_class: T.untyped, value: T.untyped).returns(T.untyped)}
122
+ def pseudo_boolean?(expected_class, value)
123
+ expected_class == Boolean && boolean?(value)
124
+ end
125
+
126
+ sig {params(expected_class: T.untyped, value: T.untyped).returns(T.untyped)}
127
+ def expected_class?(expected_class, value)
128
+ value.is_a?(expected_class)
129
+ end
130
+
131
+ sig {params(value: T.untyped).returns(T.untyped)}
132
+ def boolean?(value)
133
+ value.is_a?(TrueClass) || value.is_a?(FalseClass)
134
+ end
135
+
136
+ sig do
137
+ params(
138
+ record: T.untyped,
139
+ attribute: T.untyped,
140
+ value: T.untyped,
141
+ validation_options: SymbolHash
142
+ )
143
+ .void
144
+ end
145
+ def save_error(record, attribute, value, validation_options)
146
+ record.errors.add attribute,
147
+ validation_options[:message] || "is a #{value.class}, not a #{validation_options[:with]}"
148
+ end
149
+ end
150
+
151
+ private
83
152
 
84
- if expected_class == Boolean
85
- return if value.is_a?(TrueClass) || value.is_a?(FalseClass)
86
- else
87
- return if value.is_a?(expected_class)
88
- end
153
+ sig {params(from_hash: SymbolHash).void}
154
+ def set_instance_variables(from_hash:)
155
+ from_hash.each do |variable_name, variable_value|
156
+ # Test for the attribute reader
157
+ send variable_name.to_sym
89
158
 
90
- msg = options[:message] || "is class #{value.class}, not #{expected_class}"
91
- record.errors.add attribute, msg
159
+ # Set value in a way that succeeds even if attr is read-only
160
+ instance_variable_set "@#{variable_name}".to_sym, variable_value
92
161
  end
93
162
  end
94
163
  end
@@ -1,3 +1,6 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
1
4
  module ValidatedObject
2
- VERSION = '1.1.0'.freeze
5
+ VERSION = '2.1.0'
3
6
  end
@@ -0,0 +1,18 @@
1
+ # typed: ignore
2
+ require 'date'
3
+ require 'validated_object'
4
+
5
+ class Dog < ValidatedObject::Base
6
+ attr_reader :name, :birthday
7
+ validates :name, presence: true
8
+ validates :birthday, type: Date, allow_nil: true
9
+ end
10
+
11
+ phoebe = Dog.new(name: 'Phoebe')
12
+ puts phoebe.inspect
13
+
14
+ maru = Dog.new(birthday: Date.today, name: 'Maru')
15
+ puts maru.inspect
16
+
17
+ hiro = Dog.new(birthday: 'today')
18
+ puts hiro.inspect
@@ -0,0 +1,2 @@
1
+ --dir
2
+ .
@@ -0,0 +1,210 @@
1
+ # This file is autogenerated. Do not edit it by hand. Regenerate it with:
2
+ # srb rbi gems
3
+
4
+ # typed: ignore
5
+ #
6
+ # If you would like to make changes to this file, great! Please create the gem's shim here:
7
+ #
8
+ # https://github.com/sorbet/sorbet-typed/new/master?filename=lib/activemodel/all/activemodel.rbi
9
+ #
10
+ # activemodel-6.0.3.2
11
+
12
+ module ActiveModel
13
+ def self.eager_load!; end
14
+ def self.gem_version; end
15
+ def self.version; end
16
+ extend ActiveSupport::Autoload
17
+ end
18
+ module ActiveModel::VERSION
19
+ end
20
+ module ActiveModel::Serializers
21
+ extend ActiveSupport::Autoload
22
+ end
23
+ module ActiveModel::Validations
24
+ def errors; end
25
+ def initialize_dup(other); end
26
+ def invalid?(context = nil); end
27
+ def raise_validation_error; end
28
+ def read_attribute_for_validation(*arg0); end
29
+ def run_validations!; end
30
+ def valid?(context = nil); end
31
+ def validate!(context = nil); end
32
+ def validate(context = nil); end
33
+ def validates_with(*args, &block); end
34
+ extend ActiveSupport::Concern
35
+ end
36
+ module ActiveModel::Validations::ClassMethods
37
+ def _parse_validates_options(options); end
38
+ def _validates_default_keys; end
39
+ def attribute_method?(attribute); end
40
+ def clear_validators!; end
41
+ def inherited(base); end
42
+ def validate(*args, &block); end
43
+ def validates!(*attributes); end
44
+ def validates(*attributes); end
45
+ def validates_each(*attr_names, &block); end
46
+ def validates_with(*args, &block); end
47
+ def validators; end
48
+ def validators_on(*attributes); end
49
+ end
50
+ module ActiveModel::Validations::Clusivity
51
+ def check_validity!; end
52
+ def delimiter; end
53
+ def include?(record, value); end
54
+ def inclusion_method(enumerable); end
55
+ end
56
+ class ActiveModel::Validator
57
+ def initialize(options = nil); end
58
+ def kind; end
59
+ def options; end
60
+ def self.kind; end
61
+ def validate(record); end
62
+ end
63
+ class ActiveModel::EachValidator < ActiveModel::Validator
64
+ def attributes; end
65
+ def check_validity!; end
66
+ def initialize(options); end
67
+ def validate(record); end
68
+ def validate_each(record, attribute, value); end
69
+ end
70
+ class ActiveModel::BlockValidator < ActiveModel::EachValidator
71
+ def initialize(options, &block); end
72
+ def validate_each(record, attribute, value); end
73
+ end
74
+ class ActiveModel::Validations::InclusionValidator < ActiveModel::EachValidator
75
+ def validate_each(record, attribute, value); end
76
+ include ActiveModel::Validations::Clusivity
77
+ end
78
+ module ActiveModel::Validations::HelperMethods
79
+ def _merge_attributes(attr_names); end
80
+ def validates_absence_of(*attr_names); end
81
+ def validates_acceptance_of(*attr_names); end
82
+ def validates_confirmation_of(*attr_names); end
83
+ def validates_exclusion_of(*attr_names); end
84
+ def validates_format_of(*attr_names); end
85
+ def validates_inclusion_of(*attr_names); end
86
+ def validates_length_of(*attr_names); end
87
+ def validates_numericality_of(*attr_names); end
88
+ def validates_presence_of(*attr_names); end
89
+ def validates_size_of(*attr_names); end
90
+ end
91
+ class ActiveModel::Validations::AbsenceValidator < ActiveModel::EachValidator
92
+ def validate_each(record, attr_name, value); end
93
+ end
94
+ class ActiveModel::Validations::NumericalityValidator < ActiveModel::EachValidator
95
+ def allow_only_integer?(record); end
96
+ def check_validity!; end
97
+ def filtered_options(value); end
98
+ def is_hexadecimal_literal?(raw_value); end
99
+ def is_integer?(raw_value); end
100
+ def is_number?(raw_value); end
101
+ def parse_as_number(raw_value); end
102
+ def record_attribute_changed_in_place?(record, attr_name); end
103
+ def validate_each(record, attr_name, value); end
104
+ end
105
+ module ActiveModel::Validations::Callbacks
106
+ def run_validations!; end
107
+ extend ActiveSupport::Concern
108
+ end
109
+ module ActiveModel::Validations::Callbacks::ClassMethods
110
+ def after_validation(*args, &block); end
111
+ def before_validation(*args, &block); end
112
+ end
113
+ class ActiveModel::Validations::ExclusionValidator < ActiveModel::EachValidator
114
+ def validate_each(record, attribute, value); end
115
+ include ActiveModel::Validations::Clusivity
116
+ end
117
+ class ActiveModel::Validations::ConfirmationValidator < ActiveModel::EachValidator
118
+ def confirmation_value_equal?(record, attribute, value, confirmed); end
119
+ def initialize(options); end
120
+ def setup!(klass); end
121
+ def validate_each(record, attribute, value); end
122
+ end
123
+ class ActiveModel::Validations::FormatValidator < ActiveModel::EachValidator
124
+ def check_options_validity(name); end
125
+ def check_validity!; end
126
+ def option_call(record, name); end
127
+ def record_error(record, attribute, name, value); end
128
+ def regexp_using_multiline_anchors?(regexp); end
129
+ def validate_each(record, attribute, value); end
130
+ end
131
+ class ActiveModel::Validations::PresenceValidator < ActiveModel::EachValidator
132
+ def validate_each(record, attr_name, value); end
133
+ end
134
+ class ActiveModel::Validations::LengthValidator < ActiveModel::EachValidator
135
+ def check_validity!; end
136
+ def initialize(options); end
137
+ def skip_nil_check?(key); end
138
+ def validate_each(record, attribute, value); end
139
+ end
140
+ class ActiveModel::Validations::AcceptanceValidator < ActiveModel::EachValidator
141
+ def acceptable_option?(value); end
142
+ def initialize(options); end
143
+ def setup!(klass); end
144
+ def validate_each(record, attribute, value); end
145
+ end
146
+ class ActiveModel::Validations::AcceptanceValidator::LazilyDefineAttributes < Module
147
+ def ==(other); end
148
+ def attributes; end
149
+ def define_on(klass); end
150
+ def included(klass); end
151
+ def initialize(attributes); end
152
+ def matches?(method_name); end
153
+ end
154
+ class ActiveModel::Validations::WithValidator < ActiveModel::EachValidator
155
+ def validate_each(record, attr, val); end
156
+ end
157
+ class ActiveModel::ValidationError < StandardError
158
+ def initialize(model); end
159
+ def model; end
160
+ end
161
+ class ActiveModel::Name
162
+ def !~(**, &&); end
163
+ def <=>(**, &&); end
164
+ def ==(arg); end
165
+ def ===(arg); end
166
+ def =~(**, &&); end
167
+ def _singularize(string); end
168
+ def as_json(**, &&); end
169
+ def cache_key; end
170
+ def collection; end
171
+ def element; end
172
+ def eql?(**, &&); end
173
+ def human(options = nil); end
174
+ def i18n_key; end
175
+ def initialize(klass, namespace = nil, name = nil); end
176
+ def match?(**, &&); end
177
+ def name; end
178
+ def param_key; end
179
+ def plural; end
180
+ def route_key; end
181
+ def singular; end
182
+ def singular_route_key; end
183
+ def to_s(**, &&); end
184
+ def to_str(**, &&); end
185
+ include Comparable
186
+ end
187
+ module ActiveModel::Naming
188
+ def model_name; end
189
+ def self.extended(base); end
190
+ def self.model_name_from_record_or_class(record_or_class); end
191
+ def self.param_key(record_or_class); end
192
+ def self.plural(record_or_class); end
193
+ def self.route_key(record_or_class); end
194
+ def self.singular(record_or_class); end
195
+ def self.singular_route_key(record_or_class); end
196
+ def self.uncountable?(record_or_class); end
197
+ end
198
+ module ActiveModel::Callbacks
199
+ def _define_after_model_callback(klass, callback); end
200
+ def _define_around_model_callback(klass, callback); end
201
+ def _define_before_model_callback(klass, callback); end
202
+ def define_model_callbacks(*callbacks); end
203
+ def self.extended(base); end
204
+ end
205
+ module ActiveModel::Translation
206
+ def human_attribute_name(attribute, options = nil); end
207
+ def i18n_scope; end
208
+ def lookup_ancestors; end
209
+ include ActiveModel::Naming
210
+ end