rails 4.0.0 → 4.2.11.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +30 -23
- data/guides/CHANGELOG.md +108 -6
- data/guides/Rakefile +21 -6
- data/guides/assets/images/akshaysurve.jpg +0 -0
- data/guides/assets/images/edge_badge.png +0 -0
- data/guides/assets/images/feature_tile.gif +0 -0
- data/guides/assets/images/footer_tile.gif +0 -0
- data/guides/assets/images/fxn.png +0 -0
- data/guides/assets/images/getting_started/article_with_comments.png +0 -0
- data/guides/assets/images/getting_started/challenge.png +0 -0
- data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
- data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
- data/guides/assets/images/getting_started/form_with_errors.png +0 -0
- data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
- data/guides/assets/images/getting_started/new_article.png +0 -0
- data/guides/assets/images/getting_started/rails_welcome.png +0 -0
- data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
- data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
- data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
- data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
- data/guides/assets/images/header_tile.gif +0 -0
- data/guides/assets/images/icons/README +1 -1
- data/guides/assets/images/icons/callouts/11.png +0 -0
- data/guides/assets/images/icons/callouts/12.png +0 -0
- data/guides/assets/images/icons/callouts/13.png +0 -0
- data/guides/assets/images/icons/callouts/15.png +0 -0
- data/guides/assets/images/icons/caution.png +0 -0
- data/guides/assets/images/icons/example.png +0 -0
- data/guides/assets/images/radar.png +0 -0
- data/guides/assets/images/rails4_features.png +0 -0
- data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
- data/guides/assets/images/vijaydev.jpg +0 -0
- data/guides/assets/javascripts/guides.js +36 -34
- data/guides/assets/stylesheets/main.css +6 -2
- data/guides/assets/stylesheets/print.css +1 -1
- data/guides/bug_report_templates/action_controller_gem.rb +47 -0
- data/guides/bug_report_templates/action_controller_master.rb +54 -0
- data/guides/bug_report_templates/active_record_gem.rb +5 -2
- data/guides/bug_report_templates/active_record_master.rb +3 -2
- data/guides/bug_report_templates/generic_gem.rb +15 -0
- data/guides/bug_report_templates/generic_master.rb +26 -0
- data/guides/rails_guides.rb +23 -4
- data/guides/rails_guides/generator.rb +1 -1
- data/guides/rails_guides/helpers.rb +4 -2
- data/guides/rails_guides/levenshtein.rb +27 -21
- data/guides/rails_guides/markdown.rb +11 -7
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/source/2_2_release_notes.md +3 -3
- data/guides/source/2_3_release_notes.md +12 -12
- data/guides/source/3_0_release_notes.md +10 -13
- data/guides/source/3_1_release_notes.md +7 -4
- data/guides/source/3_2_release_notes.md +17 -14
- data/guides/source/4_0_release_notes.md +110 -54
- data/guides/source/4_1_release_notes.md +730 -0
- data/guides/source/4_2_release_notes.md +877 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +6 -2
- data/guides/source/action_controller_overview.md +223 -57
- data/guides/source/action_mailer_basics.md +129 -76
- data/guides/source/action_view_overview.md +247 -246
- data/guides/source/active_job_basics.md +339 -0
- data/guides/source/active_model_basics.md +374 -20
- data/guides/source/active_record_basics.md +46 -45
- data/guides/source/active_record_callbacks.md +83 -28
- data/guides/source/{migrations.md → active_record_migrations.md} +191 -275
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +382 -300
- data/guides/source/active_record_validations.md +64 -55
- data/guides/source/active_support_core_extensions.md +229 -187
- data/guides/source/active_support_instrumentation.md +23 -22
- data/guides/source/api_documentation_guidelines.md +167 -15
- data/guides/source/asset_pipeline.md +768 -294
- data/guides/source/association_basics.md +188 -96
- data/guides/source/autoloading_and_reloading_constants.md +1311 -0
- data/guides/source/caching_with_rails.md +45 -11
- data/guides/source/command_line.md +96 -65
- data/guides/source/configuring.md +404 -70
- data/guides/source/contributing_to_ruby_on_rails.md +270 -130
- data/guides/source/credits.html.erb +7 -3
- data/guides/source/debugging_rails_applications.md +471 -284
- data/guides/source/development_dependencies_install.md +115 -21
- data/guides/source/documents.yaml +31 -9
- data/guides/source/engines.md +737 -291
- data/guides/source/form_helpers.md +137 -89
- data/guides/source/generators.md +60 -28
- data/guides/source/getting_started.md +1007 -596
- data/guides/source/i18n.md +178 -96
- data/guides/source/index.html.erb +2 -1
- data/guides/source/initialization.md +248 -104
- data/guides/source/kindle/toc.html.erb +1 -1
- data/guides/source/layout.html.erb +14 -22
- data/guides/source/layouts_and_rendering.md +78 -46
- data/guides/source/maintenance_policy.md +78 -0
- data/guides/source/nested_model_forms.md +10 -7
- data/guides/source/plugins.md +66 -57
- data/guides/source/rails_application_templates.md +49 -12
- data/guides/source/rails_on_rack.md +50 -60
- data/guides/source/routing.md +190 -139
- data/guides/source/ruby_on_rails_guides_guidelines.md +12 -13
- data/guides/source/security.md +134 -83
- data/guides/source/testing.md +322 -200
- data/guides/source/upgrading_ruby_on_rails.md +834 -37
- data/guides/source/working_with_javascript_in_rails.md +36 -26
- data/guides/w3c_validator.rb +2 -0
- metadata +93 -116
- data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
- data/guides/assets/images/getting_started/new_post.png +0 -0
- data/guides/assets/images/getting_started/post_with_comments.png +0 -0
- data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
- data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
- data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
- data/guides/assets/images/jaimeiniesta.jpg +0 -0
- data/guides/code/getting_started/Gemfile +0 -43
- data/guides/code/getting_started/Gemfile.lock +0 -150
- data/guides/code/getting_started/README.rdoc +0 -28
- data/guides/code/getting_started/Rakefile +0 -6
- data/guides/code/getting_started/app/assets/javascripts/application.js +0 -16
- data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
- data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
- data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
- data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -17
- data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -47
- data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
- data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
- data/guides/code/getting_started/app/models/comment.rb +0 -3
- data/guides/code/getting_started/app/models/post.rb +0 -7
- data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
- data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
- data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
- data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
- data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
- data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
- data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -3
- data/guides/code/getting_started/bin/bundle +0 -4
- data/guides/code/getting_started/bin/rails +0 -4
- data/guides/code/getting_started/bin/rake +0 -4
- data/guides/code/getting_started/config.ru +0 -4
- data/guides/code/getting_started/config/application.rb +0 -18
- data/guides/code/getting_started/config/boot.rb +0 -4
- data/guides/code/getting_started/config/database.yml +0 -25
- data/guides/code/getting_started/config/environment.rb +0 -5
- data/guides/code/getting_started/config/environments/development.rb +0 -30
- data/guides/code/getting_started/config/environments/production.rb +0 -80
- data/guides/code/getting_started/config/environments/test.rb +0 -36
- data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
- data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
- data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
- data/guides/code/getting_started/config/initializers/locale.rb +0 -9
- data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
- data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
- data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
- data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
- data/guides/code/getting_started/config/locales/en.yml +0 -23
- data/guides/code/getting_started/config/routes.rb +0 -7
- data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
- data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
- data/guides/code/getting_started/db/schema.rb +0 -33
- data/guides/code/getting_started/db/seeds.rb +0 -7
- data/guides/code/getting_started/public/404.html +0 -58
- data/guides/code/getting_started/public/422.html +0 -58
- data/guides/code/getting_started/public/500.html +0 -57
- data/guides/code/getting_started/public/favicon.ico +0 -0
- data/guides/code/getting_started/public/robots.txt +0 -5
- data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
- data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
- data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
- data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
- data/guides/code/getting_started/test/models/comment_test.rb +0 -7
- data/guides/code/getting_started/test/models/post_test.rb +0 -7
- data/guides/code/getting_started/test/test_helper.rb +0 -15
- data/guides/source/kindle/KINDLE.md +0 -26
@@ -85,7 +85,7 @@ end
|
|
85
85
|
We can see how it works by looking at some `rails console` output:
|
86
86
|
|
87
87
|
```ruby
|
88
|
-
$ rails console
|
88
|
+
$ bin/rails console
|
89
89
|
>> p = Person.new(name: "John Doe")
|
90
90
|
=> #<Person id: nil, name: "John Doe", created_at: nil, updated_at: nil>
|
91
91
|
>> p.new_record?
|
@@ -120,8 +120,8 @@ database only if the object is valid:
|
|
120
120
|
* `update!`
|
121
121
|
|
122
122
|
The bang versions (e.g. `save!`) raise an exception if the record is invalid.
|
123
|
-
The non-bang versions don't
|
124
|
-
`create`
|
123
|
+
The non-bang versions don't, `save` and `update` return `false`,
|
124
|
+
`create` just returns the object.
|
125
125
|
|
126
126
|
### Skipping Validations
|
127
127
|
|
@@ -162,8 +162,8 @@ Person.create(name: nil).valid? # => false
|
|
162
162
|
```
|
163
163
|
|
164
164
|
After Active Record has performed validations, any errors found can be accessed
|
165
|
-
through the `errors` instance method, which returns a collection of errors.
|
166
|
-
definition, an object is valid if this collection is empty after running
|
165
|
+
through the `errors.messages` instance method, which returns a collection of errors.
|
166
|
+
By definition, an object is valid if this collection is empty after running
|
167
167
|
validations.
|
168
168
|
|
169
169
|
Note that an object instantiated with `new` will not report errors even if it's
|
@@ -175,28 +175,28 @@ class Person < ActiveRecord::Base
|
|
175
175
|
end
|
176
176
|
|
177
177
|
>> p = Person.new
|
178
|
-
|
179
|
-
>> p.errors
|
180
|
-
|
178
|
+
# => #<Person id: nil, name: nil>
|
179
|
+
>> p.errors.messages
|
180
|
+
# => {}
|
181
181
|
|
182
182
|
>> p.valid?
|
183
|
-
|
184
|
-
>> p.errors
|
185
|
-
|
183
|
+
# => false
|
184
|
+
>> p.errors.messages
|
185
|
+
# => {name:["can't be blank"]}
|
186
186
|
|
187
187
|
>> p = Person.create
|
188
|
-
|
189
|
-
>> p.errors
|
190
|
-
|
188
|
+
# => #<Person id: nil, name: nil>
|
189
|
+
>> p.errors.messages
|
190
|
+
# => {name:["can't be blank"]}
|
191
191
|
|
192
192
|
>> p.save
|
193
|
-
|
193
|
+
# => false
|
194
194
|
|
195
195
|
>> p.save!
|
196
|
-
|
196
|
+
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
|
197
197
|
|
198
198
|
>> Person.create!
|
199
|
-
|
199
|
+
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
|
200
200
|
```
|
201
201
|
|
202
202
|
`invalid?` is simply the inverse of `valid?`. It triggers your validations,
|
@@ -243,7 +243,7 @@ line of code you can add the same kind of validation to several attributes.
|
|
243
243
|
All of them accept the `:on` and `:message` options, which define when the
|
244
244
|
validation should be run and what message should be added to the `errors`
|
245
245
|
collection if it fails, respectively. The `:on` option takes one of the values
|
246
|
-
`:
|
246
|
+
`:create` or `:update`. There is a default error
|
247
247
|
message for each one of the validation helpers. These messages are used when
|
248
248
|
the `:message` option isn't specified. Let's take a look at each one of the
|
249
249
|
available helpers.
|
@@ -337,7 +337,7 @@ set. In fact, this set can be any enumerable object.
|
|
337
337
|
```ruby
|
338
338
|
class Account < ActiveRecord::Base
|
339
339
|
validates :subdomain, exclusion: { in: %w(www us ca jp),
|
340
|
-
message: "
|
340
|
+
message: "%{value} is reserved." }
|
341
341
|
end
|
342
342
|
```
|
343
343
|
|
@@ -357,10 +357,12 @@ given regular expression, which is specified using the `:with` option.
|
|
357
357
|
```ruby
|
358
358
|
class Product < ActiveRecord::Base
|
359
359
|
validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
|
360
|
-
message: "
|
360
|
+
message: "only allows letters" }
|
361
361
|
end
|
362
362
|
```
|
363
363
|
|
364
|
+
Alternatively, you can require that the specified attribute does _not_ match the regular expression by using the `:without` option.
|
365
|
+
|
364
366
|
The default error message is _"is invalid"_.
|
365
367
|
|
366
368
|
### `inclusion`
|
@@ -425,7 +427,7 @@ class Essay < ActiveRecord::Base
|
|
425
427
|
validates :content, length: {
|
426
428
|
minimum: 300,
|
427
429
|
maximum: 400,
|
428
|
-
tokenizer: lambda { |str| str.
|
430
|
+
tokenizer: lambda { |str| str.split(/\s+/) },
|
429
431
|
too_short: "must have at least %{count} words",
|
430
432
|
too_long: "must have at most %{count} words"
|
431
433
|
}
|
@@ -438,8 +440,6 @@ provide a personalized message or use `presence: true` instead. When
|
|
438
440
|
`:in` or `:within` have a lower limit of 1, you should either provide a
|
439
441
|
personalized message or call `presence` prior to `length`.
|
440
442
|
|
441
|
-
The `size` helper is an alias for `length`.
|
442
|
-
|
443
443
|
### `numericality`
|
444
444
|
|
445
445
|
This helper validates that your attributes have only numeric values. By
|
@@ -526,9 +526,16 @@ If you validate the presence of an object associated via a `has_one` or
|
|
526
526
|
`marked_for_destruction?`.
|
527
527
|
|
528
528
|
Since `false.blank?` is true, if you want to validate the presence of a boolean
|
529
|
-
field you should use
|
529
|
+
field you should use one of the following validations:
|
530
|
+
|
531
|
+
```ruby
|
532
|
+
validates :boolean_field_name, presence: true
|
533
|
+
validates :boolean_field_name, inclusion: { in: [true, false] }
|
534
|
+
validates :boolean_field_name, exclusion: { in: [nil] }
|
535
|
+
```
|
530
536
|
|
531
|
-
|
537
|
+
By using one of these validations, you will ensure the value will NOT be `nil`
|
538
|
+
which would result in a `NULL` value in most cases.
|
532
539
|
|
533
540
|
### `absence`
|
534
541
|
|
@@ -577,7 +584,9 @@ This helper validates that the attribute's value is unique right before the
|
|
577
584
|
object gets saved. It does not create a uniqueness constraint in the database,
|
578
585
|
so it may happen that two different database connections create two records
|
579
586
|
with the same value for a column that you intend to be unique. To avoid that,
|
580
|
-
you must create a unique index in your database.
|
587
|
+
you must create a unique index on both columns in your database. See
|
588
|
+
[the MySQL manual](http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html)
|
589
|
+
for more details about multiple column indexes.
|
581
590
|
|
582
591
|
```ruby
|
583
592
|
class Account < ActiveRecord::Base
|
@@ -618,10 +627,6 @@ The default error message is _"has already been taken"_.
|
|
618
627
|
This helper passes the record to a separate class for validation.
|
619
628
|
|
620
629
|
```ruby
|
621
|
-
class Person < ActiveRecord::Base
|
622
|
-
validates_with GoodnessValidator
|
623
|
-
end
|
624
|
-
|
625
630
|
class GoodnessValidator < ActiveModel::Validator
|
626
631
|
def validate(record)
|
627
632
|
if record.first_name == "Evil"
|
@@ -629,6 +634,10 @@ class GoodnessValidator < ActiveModel::Validator
|
|
629
634
|
end
|
630
635
|
end
|
631
636
|
end
|
637
|
+
|
638
|
+
class Person < ActiveRecord::Base
|
639
|
+
validates_with GoodnessValidator
|
640
|
+
end
|
632
641
|
```
|
633
642
|
|
634
643
|
NOTE: Errors added to `record.errors[:base]` relate to the state of the record
|
@@ -646,10 +655,6 @@ Like all other validations, `validates_with` takes the `:if`, `:unless` and
|
|
646
655
|
validator class as `options`:
|
647
656
|
|
648
657
|
```ruby
|
649
|
-
class Person < ActiveRecord::Base
|
650
|
-
validates_with GoodnessValidator, fields: [:first_name, :last_name]
|
651
|
-
end
|
652
|
-
|
653
658
|
class GoodnessValidator < ActiveModel::Validator
|
654
659
|
def validate(record)
|
655
660
|
if options[:fields].any?{|field| record.send(field) == "Evil" }
|
@@ -657,6 +662,10 @@ class GoodnessValidator < ActiveModel::Validator
|
|
657
662
|
end
|
658
663
|
end
|
659
664
|
end
|
665
|
+
|
666
|
+
class Person < ActiveRecord::Base
|
667
|
+
validates_with GoodnessValidator, fields: [:first_name, :last_name]
|
668
|
+
end
|
660
669
|
```
|
661
670
|
|
662
671
|
Note that the validator will be initialized *only once* for the whole application
|
@@ -677,14 +686,14 @@ class GoodnessValidator
|
|
677
686
|
def initialize(person)
|
678
687
|
@person = person
|
679
688
|
end
|
680
|
-
|
689
|
+
|
681
690
|
def validate
|
682
691
|
if some_complex_condition_involving_ivars_and_private_methods?
|
683
692
|
@person.errors[:base] << "This person is evil"
|
684
693
|
end
|
685
694
|
end
|
686
|
-
|
687
|
-
#
|
695
|
+
|
696
|
+
# ...
|
688
697
|
end
|
689
698
|
```
|
690
699
|
|
@@ -698,7 +707,7 @@ we don't want names and surnames to begin with lower case.
|
|
698
707
|
```ruby
|
699
708
|
class Person < ActiveRecord::Base
|
700
709
|
validates_each :name, :surname do |record, attr, value|
|
701
|
-
record.errors.add(attr, 'must start with upper case') if value =~ /\A[
|
710
|
+
record.errors.add(attr, 'must start with upper case') if value =~ /\A[[:lower:]]/
|
702
711
|
end
|
703
712
|
end
|
704
713
|
```
|
@@ -736,8 +745,8 @@ class Topic < ActiveRecord::Base
|
|
736
745
|
validates :title, length: { is: 5 }, allow_blank: true
|
737
746
|
end
|
738
747
|
|
739
|
-
Topic.create(
|
740
|
-
Topic.create(
|
748
|
+
Topic.create(title: "").valid? # => true
|
749
|
+
Topic.create(title: nil).valid? # => true
|
741
750
|
```
|
742
751
|
|
743
752
|
### `:message`
|
@@ -765,10 +774,9 @@ class Person < ActiveRecord::Base
|
|
765
774
|
validates :age, numericality: true, on: :update
|
766
775
|
|
767
776
|
# the default (validates on both create and update)
|
768
|
-
validates :name, presence: true
|
777
|
+
validates :name, presence: true
|
769
778
|
end
|
770
779
|
```
|
771
|
-
The last line is in review state and as of now, it is not running in any version of Rails 3.2.x as discussed in this [issue](https://github.com/rails/rails/issues/10248)
|
772
780
|
|
773
781
|
Strict Validations
|
774
782
|
------------------
|
@@ -784,7 +792,7 @@ end
|
|
784
792
|
Person.new.valid? # => ActiveModel::StrictValidationFailed: Name can't be blank
|
785
793
|
```
|
786
794
|
|
787
|
-
There is also an ability to pass custom exception to `:strict` option
|
795
|
+
There is also an ability to pass custom exception to `:strict` option.
|
788
796
|
|
789
797
|
```ruby
|
790
798
|
class Person < ActiveRecord::Base
|
@@ -872,7 +880,7 @@ should happen, an `Array` can be used. Moreover, you can apply both `:if` and
|
|
872
880
|
```ruby
|
873
881
|
class Computer < ActiveRecord::Base
|
874
882
|
validates :mouse, presence: true,
|
875
|
-
if: ["market.retail?", :desktop?]
|
883
|
+
if: ["market.retail?", :desktop?],
|
876
884
|
unless: Proc.new { |c| c.trackpad.present? }
|
877
885
|
end
|
878
886
|
```
|
@@ -911,8 +919,8 @@ end
|
|
911
919
|
The easiest way to add custom validators for validating individual attributes
|
912
920
|
is with the convenient `ActiveModel::EachValidator`. In this case, the custom
|
913
921
|
validator class must implement a `validate_each` method which takes three
|
914
|
-
arguments: record, attribute and value
|
915
|
-
attribute to be validated and the value of the attribute in the passed
|
922
|
+
arguments: record, attribute, and value. These correspond to the instance, the
|
923
|
+
attribute to be validated, and the value of the attribute in the passed
|
916
924
|
instance.
|
917
925
|
|
918
926
|
```ruby
|
@@ -936,8 +944,9 @@ own custom validators.
|
|
936
944
|
|
937
945
|
You can also create methods that verify the state of your models and add
|
938
946
|
messages to the `errors` collection when they are invalid. You must then
|
939
|
-
register these methods by using the `validate`
|
940
|
-
|
947
|
+
register these methods by using the `validate`
|
948
|
+
([API](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validate))
|
949
|
+
class method, passing in the symbols for the validation methods' names.
|
941
950
|
|
942
951
|
You can pass more than one symbol for each class method and the respective
|
943
952
|
validations will be run in the same order as they were registered.
|
@@ -993,12 +1002,12 @@ end
|
|
993
1002
|
|
994
1003
|
person = Person.new
|
995
1004
|
person.valid? # => false
|
996
|
-
person.errors
|
1005
|
+
person.errors.messages
|
997
1006
|
# => {:name=>["can't be blank", "is too short (minimum is 3 characters)"]}
|
998
1007
|
|
999
1008
|
person = Person.new(name: "John Doe")
|
1000
1009
|
person.valid? # => true
|
1001
|
-
person.errors # =>
|
1010
|
+
person.errors.messages # => {}
|
1002
1011
|
```
|
1003
1012
|
|
1004
1013
|
### `errors[]`
|
@@ -1130,15 +1139,15 @@ generating a scaffold, Rails will put some ERB into the `_form.html.erb` that
|
|
1130
1139
|
it generates that displays the full list of errors on that model.
|
1131
1140
|
|
1132
1141
|
Assuming we have a model that's been saved in an instance variable named
|
1133
|
-
`@
|
1142
|
+
`@article`, it looks like this:
|
1134
1143
|
|
1135
1144
|
```ruby
|
1136
|
-
<% if @
|
1145
|
+
<% if @article.errors.any? %>
|
1137
1146
|
<div id="error_explanation">
|
1138
|
-
<h2><%= pluralize(@
|
1147
|
+
<h2><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h2>
|
1139
1148
|
|
1140
1149
|
<ul>
|
1141
|
-
<% @
|
1150
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1142
1151
|
<li><%= msg %></li>
|
1143
1152
|
<% end %>
|
1144
1153
|
</ul>
|
@@ -1152,7 +1161,7 @@ the entry.
|
|
1152
1161
|
|
1153
1162
|
```
|
1154
1163
|
<div class="field_with_errors">
|
1155
|
-
<input id="
|
1164
|
+
<input id="article_title" name="article[title]" size="30" type="text" value="">
|
1156
1165
|
</div>
|
1157
1166
|
```
|
1158
1167
|
|
@@ -37,9 +37,10 @@ For every single method defined as a core extension this guide has a note that s
|
|
37
37
|
|
38
38
|
NOTE: Defined in `active_support/core_ext/object/blank.rb`.
|
39
39
|
|
40
|
-
That means that
|
40
|
+
That means that you can require it like this:
|
41
41
|
|
42
42
|
```ruby
|
43
|
+
require 'active_support'
|
43
44
|
require 'active_support/core_ext/object/blank'
|
44
45
|
```
|
45
46
|
|
@@ -52,6 +53,7 @@ The next level is to simply load all extensions to `Object`. As a rule of thumb,
|
|
52
53
|
Thus, to load all extensions to `Object` (including `blank?`):
|
53
54
|
|
54
55
|
```ruby
|
56
|
+
require 'active_support'
|
55
57
|
require 'active_support/core_ext/object'
|
56
58
|
```
|
57
59
|
|
@@ -60,6 +62,7 @@ require 'active_support/core_ext/object'
|
|
60
62
|
You may prefer just to load all core extensions, there is a file for that:
|
61
63
|
|
62
64
|
```ruby
|
65
|
+
require 'active_support'
|
63
66
|
require 'active_support/core_ext'
|
64
67
|
```
|
65
68
|
|
@@ -96,12 +99,13 @@ INFO: The predicate for strings uses the Unicode-aware character class `[:space:
|
|
96
99
|
|
97
100
|
WARNING: Note that numbers are not mentioned. In particular, 0 and 0.0 are **not** blank.
|
98
101
|
|
99
|
-
For example, this method from `
|
102
|
+
For example, this method from `ActionController::HttpAuthentication::Token::ControllerMethods` uses `blank?` for checking whether a token is present:
|
100
103
|
|
101
104
|
```ruby
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
+
def authenticate(controller, &login_procedure)
|
106
|
+
token, options = token_and_options(controller.request)
|
107
|
+
unless token.blank?
|
108
|
+
login_procedure.call(token, options)
|
105
109
|
end
|
106
110
|
end
|
107
111
|
```
|
@@ -153,12 +157,12 @@ Active Support provides `duplicable?` to programmatically query an object about
|
|
153
157
|
|
154
158
|
```ruby
|
155
159
|
"foo".duplicable? # => true
|
156
|
-
"".duplicable?
|
160
|
+
"".duplicable? # => true
|
157
161
|
0.0.duplicable? # => false
|
158
|
-
false.duplicable?
|
162
|
+
false.duplicable? # => false
|
159
163
|
```
|
160
164
|
|
161
|
-
By definition all objects are `duplicable?` except `nil`, `false`, `true`, symbols, numbers, class, and
|
165
|
+
By definition all objects are `duplicable?` except `nil`, `false`, `true`, symbols, numbers, class, module, and method objects.
|
162
166
|
|
163
167
|
WARNING: Any class can disallow duplication by removing `dup` and `clone` or raising exceptions from them. Thus only `rescue` can tell whether a given arbitrary object is duplicable. `duplicable?` depends on the hard-coded list above, but it is much faster than `rescue`. Use it only if you know the hard-coded list is enough in your use case.
|
164
168
|
|
@@ -166,7 +170,7 @@ NOTE: Defined in `active_support/core_ext/object/duplicable.rb`.
|
|
166
170
|
|
167
171
|
### `deep_dup`
|
168
172
|
|
169
|
-
The `deep_dup` method returns deep copy of a given object. Normally, when you `dup` an object that contains other objects,
|
173
|
+
The `deep_dup` method returns deep copy of a given object. Normally, when you `dup` an object that contains other objects, Ruby does not `dup` them, so it creates a shallow copy of the object. If you have an array with a string, for example, it will look like this:
|
170
174
|
|
171
175
|
```ruby
|
172
176
|
array = ['string']
|
@@ -175,14 +179,14 @@ duplicate = array.dup
|
|
175
179
|
duplicate.push 'another-string'
|
176
180
|
|
177
181
|
# the object was duplicated, so the element was added only to the duplicate
|
178
|
-
array
|
179
|
-
duplicate
|
182
|
+
array # => ['string']
|
183
|
+
duplicate # => ['string', 'another-string']
|
180
184
|
|
181
185
|
duplicate.first.gsub!('string', 'foo')
|
182
186
|
|
183
187
|
# first element was not duplicated, it will be changed in both arrays
|
184
|
-
array
|
185
|
-
duplicate
|
188
|
+
array # => ['foo']
|
189
|
+
duplicate # => ['foo', 'another-string']
|
186
190
|
```
|
187
191
|
|
188
192
|
As you can see, after duplicating the `Array` instance, we got another object, therefore we can modify it and the original object will stay unchanged. This is not true for array's elements, however. Since `dup` does not make deep copy, the string inside the array is still the same object.
|
@@ -195,8 +199,8 @@ duplicate = array.deep_dup
|
|
195
199
|
|
196
200
|
duplicate.first.gsub!('string', 'foo')
|
197
201
|
|
198
|
-
array
|
199
|
-
duplicate
|
202
|
+
array # => ['string']
|
203
|
+
duplicate # => ['foo']
|
200
204
|
```
|
201
205
|
|
202
206
|
If the object is not duplicable, `deep_dup` will just return it:
|
@@ -418,6 +422,12 @@ TIP: Since `with_options` forwards calls to its receiver they can be nested. Eac
|
|
418
422
|
|
419
423
|
NOTE: Defined in `active_support/core_ext/object/with_options.rb`.
|
420
424
|
|
425
|
+
### JSON support
|
426
|
+
|
427
|
+
Active Support provides a better implementation of `to_json` than the `json` gem ordinarily provides for Ruby objects. This is because some classes, like `Hash`, `OrderedHash` and `Process::Status` need special handling in order to provide a proper JSON representation.
|
428
|
+
|
429
|
+
NOTE: Defined in `active_support/core_ext/object/json.rb`.
|
430
|
+
|
421
431
|
### Instance Variables
|
422
432
|
|
423
433
|
Active Support provides several methods to ease access to instance variables.
|
@@ -439,6 +449,22 @@ C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
|
|
439
449
|
|
440
450
|
NOTE: Defined in `active_support/core_ext/object/instance_variables.rb`.
|
441
451
|
|
452
|
+
#### `instance_variable_names`
|
453
|
+
|
454
|
+
The method `instance_variable_names` returns an array. Each name includes the "@" sign.
|
455
|
+
|
456
|
+
```ruby
|
457
|
+
class C
|
458
|
+
def initialize(x, y)
|
459
|
+
@x, @y = x, y
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
C.new(0, 1).instance_variable_names # => ["@x", "@y"]
|
464
|
+
```
|
465
|
+
|
466
|
+
NOTE: Defined in `active_support/core_ext/object/instance_variables.rb`.
|
467
|
+
|
442
468
|
### Silencing Warnings, Streams, and Exceptions
|
443
469
|
|
444
470
|
The methods `silence_warnings` and `enable_warnings` change the value of `$VERBOSE` accordingly for the duration of their block, and reset it afterwards:
|
@@ -546,12 +572,12 @@ NOTE: Defined in `active_support/core_ext/module/aliasing.rb`.
|
|
546
572
|
|
547
573
|
#### `alias_attribute`
|
548
574
|
|
549
|
-
Model attributes have a reader, a writer, and a predicate. You can alias a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (
|
575
|
+
Model attributes have a reader, a writer, and a predicate. You can alias a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (one mnemonic is that they go in the same order as if you did an assignment):
|
550
576
|
|
551
577
|
```ruby
|
552
578
|
class User < ActiveRecord::Base
|
553
|
-
#
|
554
|
-
#
|
579
|
+
# You can refer to the email column as "login".
|
580
|
+
# This can be meaningful for authentication code.
|
555
581
|
alias_attribute :login, :email
|
556
582
|
end
|
557
583
|
```
|
@@ -598,7 +624,7 @@ NOTE: Defined in `active_support/core_ext/module/attr_internal.rb`.
|
|
598
624
|
|
599
625
|
#### Module Attributes
|
600
626
|
|
601
|
-
The macros `mattr_reader`, `mattr_writer`, and `mattr_accessor` are
|
627
|
+
The macros `mattr_reader`, `mattr_writer`, and `mattr_accessor` are the same as the `cattr_*` macros defined for class. In fact, the `cattr_*` macros are just aliases for the `mattr_*` macros. Check [Class Attributes](#class-attributes).
|
602
628
|
|
603
629
|
For example, the dependencies mechanism uses them:
|
604
630
|
|
@@ -709,7 +735,7 @@ X.local_constants # => [:X1, :X2, :Y]
|
|
709
735
|
X::Y.local_constants # => [:Y1, :X1]
|
710
736
|
```
|
711
737
|
|
712
|
-
The names are returned as symbols.
|
738
|
+
The names are returned as symbols.
|
713
739
|
|
714
740
|
NOTE: Defined in `active_support/core_ext/module/introspection.rb`.
|
715
741
|
|
@@ -735,7 +761,7 @@ Arguments may be bare constant names:
|
|
735
761
|
Math.qualified_const_get("E") # => 2.718281828459045
|
736
762
|
```
|
737
763
|
|
738
|
-
These methods are analogous to their
|
764
|
+
These methods are analogous to their built-in counterparts. In particular,
|
739
765
|
`qualified_constant_defined?` accepts an optional second argument to be
|
740
766
|
able to say whether you want the predicate to look in the ancestors.
|
741
767
|
This flag is taken into account for each constant in the expression while
|
@@ -766,7 +792,7 @@ N.qualified_const_defined?("C::X") # => true
|
|
766
792
|
As the last example implies, the second argument defaults to true,
|
767
793
|
as in `const_defined?`.
|
768
794
|
|
769
|
-
For coherence with the
|
795
|
+
For coherence with the built-in methods only relative paths are accepted.
|
770
796
|
Absolute qualified constant names like `::Math::PI` raise `NameError`.
|
771
797
|
|
772
798
|
NOTE: Defined in `active_support/core_ext/module/qualified_const.rb`.
|
@@ -862,7 +888,7 @@ class User < ActiveRecord::Base
|
|
862
888
|
end
|
863
889
|
```
|
864
890
|
|
865
|
-
With that configuration you get a user's name via
|
891
|
+
With that configuration you get a user's name via their profile, `user.profile.name`, but it could be handy to still be able to access such attribute directly:
|
866
892
|
|
867
893
|
```ruby
|
868
894
|
class User < ActiveRecord::Base
|
@@ -938,20 +964,7 @@ NOTE: Defined in `active_support/core_ext/module/delegation.rb`
|
|
938
964
|
|
939
965
|
There are cases where you need to define a method with `define_method`, but don't know whether a method with that name already exists. If it does, a warning is issued if they are enabled. No big deal, but not clean either.
|
940
966
|
|
941
|
-
The method `redefine_method` prevents such a potential warning, removing the existing method before if needed.
|
942
|
-
|
943
|
-
```ruby
|
944
|
-
redefine_method("#{reflection.name}=") do |new_value|
|
945
|
-
association = association_instance_get(reflection.name)
|
946
|
-
|
947
|
-
if association.nil? || association.target != new_value
|
948
|
-
association = association_proxy_class.new(self, reflection)
|
949
|
-
end
|
950
|
-
|
951
|
-
association.replace(new_value)
|
952
|
-
association_instance_set(reflection.name, new_value.nil? ? nil : association)
|
953
|
-
end
|
954
|
-
```
|
967
|
+
The method `redefine_method` prevents such a potential warning, removing the existing method before if needed.
|
955
968
|
|
956
969
|
NOTE: Defined in `active_support/core_ext/module/remove_method.rb`
|
957
970
|
|
@@ -998,7 +1011,7 @@ self.default_params = {
|
|
998
1011
|
}.freeze
|
999
1012
|
```
|
1000
1013
|
|
1001
|
-
They can be
|
1014
|
+
They can also be accessed and overridden at the instance level.
|
1002
1015
|
|
1003
1016
|
```ruby
|
1004
1017
|
A.x = 1
|
@@ -1038,7 +1051,7 @@ For convenience `class_attribute` also defines an instance predicate which is th
|
|
1038
1051
|
|
1039
1052
|
When `:instance_reader` is `false`, the instance predicate returns a `NoMethodError` just like the reader method.
|
1040
1053
|
|
1041
|
-
If you do not want the instance predicate,
|
1054
|
+
If you do not want the instance predicate, pass `instance_predicate: false` and it will not be defined.
|
1042
1055
|
|
1043
1056
|
NOTE: Defined in `active_support/core_ext/class/attribute.rb`
|
1044
1057
|
|
@@ -1067,6 +1080,15 @@ end
|
|
1067
1080
|
|
1068
1081
|
we can access `field_error_proc` in views.
|
1069
1082
|
|
1083
|
+
Also, you can pass a block to `cattr_*` to set up the attribute with a default value:
|
1084
|
+
|
1085
|
+
```ruby
|
1086
|
+
class MysqlAdapter < AbstractAdapter
|
1087
|
+
# Generates class methods to access @@emulate_booleans with default value of true.
|
1088
|
+
cattr_accessor(:emulate_booleans) { true }
|
1089
|
+
end
|
1090
|
+
```
|
1091
|
+
|
1070
1092
|
The generation of the reader instance method can be prevented by setting `:instance_reader` to `false` and the generation of the writer instance method can be prevented by setting `:instance_writer` to `false`. Generation of both methods can be prevented by setting `:instance_accessor` to `false`. In all cases, the value must be exactly `false` and not any false value.
|
1071
1093
|
|
1072
1094
|
```ruby
|
@@ -1084,7 +1106,7 @@ end
|
|
1084
1106
|
|
1085
1107
|
A model may find it useful to set `:instance_accessor` to `false` as a way to prevent mass-assignment from setting the attribute.
|
1086
1108
|
|
1087
|
-
NOTE: Defined in `active_support/core_ext/
|
1109
|
+
NOTE: Defined in `active_support/core_ext/module/attribute_accessors.rb`.
|
1088
1110
|
|
1089
1111
|
### Subclasses & Descendants
|
1090
1112
|
|
@@ -1143,9 +1165,9 @@ Inserting data into HTML templates needs extra care. For example, you can't just
|
|
1143
1165
|
|
1144
1166
|
#### Safe Strings
|
1145
1167
|
|
1146
|
-
Active Support has the concept of
|
1168
|
+
Active Support has the concept of _(html) safe_ strings. A safe string is one that is marked as being insertable into HTML as is. It is trusted, no matter whether it has been escaped or not.
|
1147
1169
|
|
1148
|
-
Strings are considered to be
|
1170
|
+
Strings are considered to be _unsafe_ by default:
|
1149
1171
|
|
1150
1172
|
```ruby
|
1151
1173
|
"".html_safe? # => false
|
@@ -1224,6 +1246,18 @@ Calling `to_s` on a safe string returns a safe string, but coercion with `to_str
|
|
1224
1246
|
|
1225
1247
|
Calling `dup` or `clone` on safe strings yields safe strings.
|
1226
1248
|
|
1249
|
+
### `remove`
|
1250
|
+
|
1251
|
+
The method `remove` will remove all occurrences of the pattern:
|
1252
|
+
|
1253
|
+
```ruby
|
1254
|
+
"Hello World".remove(/Hello /) => "World"
|
1255
|
+
```
|
1256
|
+
|
1257
|
+
There's also the destructive version `String#remove!`.
|
1258
|
+
|
1259
|
+
NOTE: Defined in `active_support/core_ext/string/filters.rb`.
|
1260
|
+
|
1227
1261
|
### `squish`
|
1228
1262
|
|
1229
1263
|
The method `squish` strips leading and trailing whitespace, and substitutes runs of whitespace with a single space each:
|
@@ -1234,7 +1268,7 @@ The method `squish` strips leading and trailing whitespace, and substitutes runs
|
|
1234
1268
|
|
1235
1269
|
There's also the destructive version `String#squish!`.
|
1236
1270
|
|
1237
|
-
Note that it handles both ASCII and Unicode whitespace
|
1271
|
+
Note that it handles both ASCII and Unicode whitespace.
|
1238
1272
|
|
1239
1273
|
NOTE: Defined in `active_support/core_ext/string/filters.rb`.
|
1240
1274
|
|
@@ -1276,6 +1310,38 @@ In above examples "dear" gets cut first, but then `:separator` prevents it.
|
|
1276
1310
|
|
1277
1311
|
NOTE: Defined in `active_support/core_ext/string/filters.rb`.
|
1278
1312
|
|
1313
|
+
### `truncate_words`
|
1314
|
+
|
1315
|
+
The method `truncate_words` returns a copy of its receiver truncated after a given number of words:
|
1316
|
+
|
1317
|
+
```ruby
|
1318
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(4)
|
1319
|
+
# => "Oh dear! Oh dear!..."
|
1320
|
+
```
|
1321
|
+
|
1322
|
+
Ellipsis can be customized with the `:omission` option:
|
1323
|
+
|
1324
|
+
```ruby
|
1325
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(4, omission: '…')
|
1326
|
+
# => "Oh dear! Oh dear!…"
|
1327
|
+
```
|
1328
|
+
|
1329
|
+
Pass a `:separator` to truncate the string at a natural break:
|
1330
|
+
|
1331
|
+
```ruby
|
1332
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(3, separator: '!')
|
1333
|
+
# => "Oh dear! Oh dear! I shall be late..."
|
1334
|
+
```
|
1335
|
+
|
1336
|
+
The option `:separator` can be a regexp:
|
1337
|
+
|
1338
|
+
```ruby
|
1339
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(4, separator: /\s/)
|
1340
|
+
# => "Oh dear! Oh dear!..."
|
1341
|
+
```
|
1342
|
+
|
1343
|
+
NOTE: Defined in `active_support/core_ext/string/filters.rb`.
|
1344
|
+
|
1279
1345
|
### `inquiry`
|
1280
1346
|
|
1281
1347
|
The `inquiry` method converts a string into a `StringInquirer` object making equality checks prettier.
|
@@ -1356,6 +1422,8 @@ The third argument, `indent_empty_lines`, is a flag that says whether empty line
|
|
1356
1422
|
|
1357
1423
|
The `indent!` method performs indentation in-place.
|
1358
1424
|
|
1425
|
+
NOTE: Defined in `active_support/core_ext/string/indent.rb`.
|
1426
|
+
|
1359
1427
|
### Access
|
1360
1428
|
|
1361
1429
|
#### `at(position)`
|
@@ -1423,7 +1491,7 @@ The method `pluralize` returns the plural of its receiver:
|
|
1423
1491
|
|
1424
1492
|
As the previous example shows, Active Support knows some irregular plurals and uncountable nouns. Built-in rules can be extended in `config/initializers/inflections.rb`. That file is generated by the `rails` command and has instructions in comments.
|
1425
1493
|
|
1426
|
-
`pluralize` can also take an optional `count` parameter.
|
1494
|
+
`pluralize` can also take an optional `count` parameter. If `count == 1` the singular form will be returned. For any other value of `count` the plural form will be returned:
|
1427
1495
|
|
1428
1496
|
```ruby
|
1429
1497
|
"dude".pluralize(0) # => "dudes"
|
@@ -1507,7 +1575,7 @@ ActiveSupport::Inflector.inflections do |inflect|
|
|
1507
1575
|
inflect.acronym 'SSL'
|
1508
1576
|
end
|
1509
1577
|
|
1510
|
-
"SSLError".underscore.camelize
|
1578
|
+
"SSLError".underscore.camelize # => "SSLError"
|
1511
1579
|
```
|
1512
1580
|
|
1513
1581
|
`camelize` is aliased to `camelcase`.
|
@@ -1595,6 +1663,9 @@ Given a string with a qualified constant name, `demodulize` returns the very con
|
|
1595
1663
|
"Product".demodulize # => "Product"
|
1596
1664
|
"Backoffice::UsersController".demodulize # => "UsersController"
|
1597
1665
|
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
|
1666
|
+
"::Inflections".demodulize # => "Inflections"
|
1667
|
+
"".demodulize # => ""
|
1668
|
+
|
1598
1669
|
```
|
1599
1670
|
|
1600
1671
|
Active Record for example uses this method to compute the name of a counter cache column:
|
@@ -1689,7 +1760,7 @@ NOTE: Defined in `active_support/core_ext/string/inflections.rb`.
|
|
1689
1760
|
The method `constantize` resolves the constant reference expression in its receiver:
|
1690
1761
|
|
1691
1762
|
```ruby
|
1692
|
-
"
|
1763
|
+
"Integer".constantize # => Integer
|
1693
1764
|
|
1694
1765
|
module M
|
1695
1766
|
X = 1
|
@@ -1729,28 +1800,47 @@ NOTE: Defined in `active_support/core_ext/string/inflections.rb`.
|
|
1729
1800
|
|
1730
1801
|
#### `humanize`
|
1731
1802
|
|
1732
|
-
The method `humanize`
|
1803
|
+
The method `humanize` tweaks an attribute name for display to end users.
|
1804
|
+
|
1805
|
+
Specifically performs these transformations:
|
1806
|
+
|
1807
|
+
* Applies human inflection rules to the argument.
|
1808
|
+
* Deletes leading underscores, if any.
|
1809
|
+
* Removes a "_id" suffix if present.
|
1810
|
+
* Replaces underscores with spaces, if any.
|
1811
|
+
* Downcases all words except acronyms.
|
1812
|
+
* Capitalizes the first word.
|
1813
|
+
|
1814
|
+
The capitalization of the first word can be turned off by setting the
|
1815
|
+
+:capitalize+ option to false (default is true).
|
1733
1816
|
|
1734
1817
|
```ruby
|
1735
|
-
"name".humanize
|
1736
|
-
"author_id".humanize
|
1737
|
-
"
|
1818
|
+
"name".humanize # => "Name"
|
1819
|
+
"author_id".humanize # => "Author"
|
1820
|
+
"author_id".humanize(capitalize: false) # => "author"
|
1821
|
+
"comments_count".humanize # => "Comments count"
|
1822
|
+
"_id".humanize # => "Id"
|
1738
1823
|
```
|
1739
1824
|
|
1740
|
-
|
1825
|
+
If "SSL" was defined to be an acronym:
|
1741
1826
|
|
1742
1827
|
```ruby
|
1743
|
-
|
1744
|
-
|
1828
|
+
'ssl_error'.humanize # => "SSL error"
|
1829
|
+
```
|
1745
1830
|
|
1746
|
-
|
1747
|
-
|
1748
|
-
attr_name = attribute.to_s.gsub('.', '_').humanize
|
1749
|
-
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
|
1750
|
-
...
|
1751
|
-
end
|
1831
|
+
The helper method `full_messages` uses `humanize` as a fallback to include
|
1832
|
+
attribute names:
|
1752
1833
|
|
1753
|
-
|
1834
|
+
```ruby
|
1835
|
+
def full_messages
|
1836
|
+
map { |attribute, message| full_message(attribute, message) }
|
1837
|
+
end
|
1838
|
+
|
1839
|
+
def full_message
|
1840
|
+
...
|
1841
|
+
attr_name = attribute.to_s.tr('.', '_').humanize
|
1842
|
+
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
|
1843
|
+
...
|
1754
1844
|
end
|
1755
1845
|
```
|
1756
1846
|
|
@@ -1860,24 +1950,6 @@ as well as adding or subtracting their results from a Time object. For example:
|
|
1860
1950
|
(4.months + 5.years).from_now
|
1861
1951
|
```
|
1862
1952
|
|
1863
|
-
While these methods provide precise calculation when used as in the examples above, care
|
1864
|
-
should be taken to note that this is not true if the result of `months', `years', etc is
|
1865
|
-
converted before use:
|
1866
|
-
|
1867
|
-
```ruby
|
1868
|
-
# equivalent to 30.days.to_i.from_now
|
1869
|
-
1.month.to_i.from_now
|
1870
|
-
|
1871
|
-
# equivalent to 365.25.days.to_f.from_now
|
1872
|
-
1.year.to_f.from_now
|
1873
|
-
```
|
1874
|
-
|
1875
|
-
In such cases, Ruby's core [Date](http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html) and
|
1876
|
-
[Time](http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html) should be used for precision
|
1877
|
-
date and time arithmetic.
|
1878
|
-
|
1879
|
-
NOTE: Defined in `active_support/core_ext/numeric/time.rb`.
|
1880
|
-
|
1881
1953
|
### Formatting
|
1882
1954
|
|
1883
1955
|
Enables the formatting of numbers in a variety of ways.
|
@@ -1963,7 +2035,7 @@ Produce a string representation of a number in human-readable words:
|
|
1963
2035
|
1234567890123456.to_s(:human) # => "1.23 Quadrillion"
|
1964
2036
|
```
|
1965
2037
|
|
1966
|
-
NOTE: Defined in `active_support/core_ext/numeric/
|
2038
|
+
NOTE: Defined in `active_support/core_ext/numeric/conversions.rb`.
|
1967
2039
|
|
1968
2040
|
Extensions to `Integer`
|
1969
2041
|
-----------------------
|
@@ -2011,8 +2083,33 @@ NOTE: Defined in `active_support/core_ext/integer/inflections.rb`.
|
|
2011
2083
|
|
2012
2084
|
Extensions to `BigDecimal`
|
2013
2085
|
--------------------------
|
2086
|
+
### `to_s`
|
2014
2087
|
|
2015
|
-
|
2088
|
+
The method `to_s` is aliased to `to_formatted_s`. This provides a convenient way to display a BigDecimal value in floating-point notation:
|
2089
|
+
|
2090
|
+
```ruby
|
2091
|
+
BigDecimal.new(5.00, 6).to_s # => "5.0"
|
2092
|
+
```
|
2093
|
+
|
2094
|
+
### `to_formatted_s`
|
2095
|
+
|
2096
|
+
Te method `to_formatted_s` provides a default specifier of "F". This means that a simple call to `to_formatted_s` or `to_s` will result in floating point representation instead of engineering notation:
|
2097
|
+
|
2098
|
+
```ruby
|
2099
|
+
BigDecimal.new(5.00, 6).to_formatted_s # => "5.0"
|
2100
|
+
```
|
2101
|
+
|
2102
|
+
and that symbol specifiers are also supported:
|
2103
|
+
|
2104
|
+
```ruby
|
2105
|
+
BigDecimal.new(5.00, 6).to_formatted_s(:db) # => "5.0"
|
2106
|
+
```
|
2107
|
+
|
2108
|
+
Engineering notation is still supported:
|
2109
|
+
|
2110
|
+
```ruby
|
2111
|
+
BigDecimal.new(5.00, 6).to_formatted_s("e") # => "0.5E1"
|
2112
|
+
```
|
2016
2113
|
|
2017
2114
|
Extensions to `Enumerable`
|
2018
2115
|
--------------------------
|
@@ -2207,8 +2304,6 @@ The defaults for these options can be localized, their keys are:
|
|
2207
2304
|
| `:words_connector` | `support.array.words_connector` |
|
2208
2305
|
| `:last_word_connector` | `support.array.last_word_connector` |
|
2209
2306
|
|
2210
|
-
Options `:connector` and `:skip_last_comma` are deprecated.
|
2211
|
-
|
2212
2307
|
NOTE: Defined in `active_support/core_ext/array/conversions.rb`.
|
2213
2308
|
|
2214
2309
|
#### `to_formatted_s`
|
@@ -2383,7 +2478,7 @@ dup[1][2] = 4
|
|
2383
2478
|
array[1][2] == nil # => true
|
2384
2479
|
```
|
2385
2480
|
|
2386
|
-
NOTE: Defined in `active_support/core_ext/
|
2481
|
+
NOTE: Defined in `active_support/core_ext/object/deep_dup.rb`.
|
2387
2482
|
|
2388
2483
|
### Grouping
|
2389
2484
|
|
@@ -2517,8 +2612,7 @@ To do so, the method loops over the pairs and builds nodes that depend on the _v
|
|
2517
2612
|
```ruby
|
2518
2613
|
XML_TYPE_NAMES = {
|
2519
2614
|
"Symbol" => "symbol",
|
2520
|
-
"
|
2521
|
-
"Bignum" => "integer",
|
2615
|
+
"Integer" => "integer",
|
2522
2616
|
"BigDecimal" => "decimal",
|
2523
2617
|
"Float" => "float",
|
2524
2618
|
"TrueClass" => "boolean",
|
@@ -2609,45 +2703,7 @@ hash[:b][:e] == nil # => true
|
|
2609
2703
|
hash[:b][:d] == [3, 4] # => true
|
2610
2704
|
```
|
2611
2705
|
|
2612
|
-
NOTE: Defined in `active_support/core_ext/
|
2613
|
-
|
2614
|
-
### Diffing
|
2615
|
-
|
2616
|
-
The method `diff` returns a hash that represents a diff of the receiver and the argument with the following logic:
|
2617
|
-
|
2618
|
-
* Pairs `key`, `value` that exist in both hashes do not belong to the diff hash.
|
2619
|
-
|
2620
|
-
* If both hashes have `key`, but with different values, the pair in the receiver wins.
|
2621
|
-
|
2622
|
-
* The rest is just merged.
|
2623
|
-
|
2624
|
-
```ruby
|
2625
|
-
{a: 1}.diff(a: 1)
|
2626
|
-
# => {}, first rule
|
2627
|
-
|
2628
|
-
{a: 1}.diff(a: 2)
|
2629
|
-
# => {:a=>1}, second rule
|
2630
|
-
|
2631
|
-
{a: 1}.diff(b: 2)
|
2632
|
-
# => {:a=>1, :b=>2}, third rule
|
2633
|
-
|
2634
|
-
{a: 1, b: 2, c: 3}.diff(b: 1, c: 3, d: 4)
|
2635
|
-
# => {:a=>1, :b=>2, :d=>4}, all rules
|
2636
|
-
|
2637
|
-
{}.diff({}) # => {}
|
2638
|
-
{a: 1}.diff({}) # => {:a=>1}
|
2639
|
-
{}.diff(a: 1) # => {:a=>1}
|
2640
|
-
```
|
2641
|
-
|
2642
|
-
An important property of this diff hash is that you can retrieve the original hash by applying `diff` twice:
|
2643
|
-
|
2644
|
-
```ruby
|
2645
|
-
hash.diff(hash2).diff(hash2) == hash
|
2646
|
-
```
|
2647
|
-
|
2648
|
-
Diffing hashes may be useful for error messages related to expected option hashes for example.
|
2649
|
-
|
2650
|
-
NOTE: Defined in `active_support/core_ext/hash/diff.rb`.
|
2706
|
+
NOTE: Defined in `active_support/core_ext/object/deep_dup.rb`.
|
2651
2707
|
|
2652
2708
|
### Working with Keys
|
2653
2709
|
|
@@ -2675,26 +2731,29 @@ NOTE: Defined in `active_support/core_ext/hash/except.rb`.
|
|
2675
2731
|
The method `transform_keys` accepts a block and returns a hash that has applied the block operations to each of the keys in the receiver:
|
2676
2732
|
|
2677
2733
|
```ruby
|
2678
|
-
{nil => nil, 1 => 1, a: :a}.transform_keys{ |key| key.to_s.upcase }
|
2734
|
+
{nil => nil, 1 => 1, a: :a}.transform_keys { |key| key.to_s.upcase }
|
2679
2735
|
# => {"" => nil, "A" => :a, "1" => 1}
|
2680
2736
|
```
|
2681
2737
|
|
2682
|
-
|
2738
|
+
In case of key collision, one of the values will be chosen. The chosen value may not always be the same given the same hash:
|
2683
2739
|
|
2684
2740
|
```ruby
|
2685
|
-
{"a" => 1, a: 2}.transform_keys{ |key| key.to_s.upcase }
|
2686
|
-
#
|
2741
|
+
{"a" => 1, a: 2}.transform_keys { |key| key.to_s.upcase }
|
2742
|
+
# The result could either be
|
2743
|
+
# => {"A"=>2}
|
2744
|
+
# or
|
2745
|
+
# => {"A"=>1}
|
2687
2746
|
```
|
2688
2747
|
|
2689
2748
|
This method may be useful for example to build specialized conversions. For instance `stringify_keys` and `symbolize_keys` use `transform_keys` to perform their key conversions:
|
2690
2749
|
|
2691
2750
|
```ruby
|
2692
2751
|
def stringify_keys
|
2693
|
-
transform_keys{ |key| key.to_s }
|
2752
|
+
transform_keys { |key| key.to_s }
|
2694
2753
|
end
|
2695
2754
|
...
|
2696
2755
|
def symbolize_keys
|
2697
|
-
transform_keys{ |key| key.to_sym rescue key }
|
2756
|
+
transform_keys { |key| key.to_sym rescue key }
|
2698
2757
|
end
|
2699
2758
|
```
|
2700
2759
|
|
@@ -2703,7 +2762,7 @@ There's also the bang variant `transform_keys!` that applies the block operation
|
|
2703
2762
|
Besides that, one can use `deep_transform_keys` and `deep_transform_keys!` to perform the block operation on all the keys in the given hash and all the hashes nested into it. An example of the result is:
|
2704
2763
|
|
2705
2764
|
```ruby
|
2706
|
-
{nil => nil, 1 => 1, nested: {a: 3, 5 => 5}}.deep_transform_keys{ |key| key.to_s.upcase }
|
2765
|
+
{nil => nil, 1 => 1, nested: {a: 3, 5 => 5}}.deep_transform_keys { |key| key.to_s.upcase }
|
2707
2766
|
# => {""=>nil, "1"=>1, "NESTED"=>{"A"=>3, "5"=>5}}
|
2708
2767
|
```
|
2709
2768
|
|
@@ -2718,11 +2777,14 @@ The method `stringify_keys` returns a hash that has a stringified version of the
|
|
2718
2777
|
# => {"" => nil, "a" => :a, "1" => 1}
|
2719
2778
|
```
|
2720
2779
|
|
2721
|
-
|
2780
|
+
In case of key collision, one of the values will be chosen. The chosen value may not always be the same given the same hash:
|
2722
2781
|
|
2723
2782
|
```ruby
|
2724
2783
|
{"a" => 1, a: 2}.stringify_keys
|
2725
|
-
#
|
2784
|
+
# The result could either be
|
2785
|
+
# => {"a"=>2}
|
2786
|
+
# or
|
2787
|
+
# => {"a"=>1}
|
2726
2788
|
```
|
2727
2789
|
|
2728
2790
|
This method may be useful for example to easily accept both symbols and strings as options. For instance `ActionView::Helpers::FormHelper` defines:
|
@@ -2759,11 +2821,14 @@ The method `symbolize_keys` returns a hash that has a symbolized version of the
|
|
2759
2821
|
|
2760
2822
|
WARNING. Note in the previous example only one key was symbolized.
|
2761
2823
|
|
2762
|
-
|
2824
|
+
In case of key collision, one of the values will be chosen. The chosen value may not always be the same given the same hash:
|
2763
2825
|
|
2764
2826
|
```ruby
|
2765
2827
|
{"a" => 1, a: 2}.symbolize_keys
|
2766
|
-
#
|
2828
|
+
# The result could either be
|
2829
|
+
# => {:a=>2}
|
2830
|
+
# or
|
2831
|
+
# => {:a=>1}
|
2767
2832
|
```
|
2768
2833
|
|
2769
2834
|
This method may be useful for example to easily accept both symbols and strings as options. For instance `ActionController::UrlRewriter` defines
|
@@ -2808,6 +2873,20 @@ Active Record does not accept unknown options when building associations, for ex
|
|
2808
2873
|
|
2809
2874
|
NOTE: Defined in `active_support/core_ext/hash/keys.rb`.
|
2810
2875
|
|
2876
|
+
### Working with Values
|
2877
|
+
|
2878
|
+
#### `transform_values` && `transform_values!`
|
2879
|
+
|
2880
|
+
The method `transform_values` accepts a block and returns a hash that has applied the block operations to each of the values in the receiver.
|
2881
|
+
|
2882
|
+
```ruby
|
2883
|
+
{ nil => nil, 1 => 1, :x => :a }.transform_values { |value| value.to_s.upcase }
|
2884
|
+
# => {nil=>"", 1=>"1", :x=>"A"}
|
2885
|
+
```
|
2886
|
+
There's also the bang variant `transform_values!` that applies the block operations to values in the very receiver.
|
2887
|
+
|
2888
|
+
NOTE: Defined in `active_support/core_text/hash/transform_values.rb`.
|
2889
|
+
|
2811
2890
|
### Slicing
|
2812
2891
|
|
2813
2892
|
Ruby has built-in support for taking slices out of strings and arrays. Active Support extends slicing to hashes:
|
@@ -2869,6 +2948,16 @@ The method `with_indifferent_access` returns an `ActiveSupport::HashWithIndiffer
|
|
2869
2948
|
|
2870
2949
|
NOTE: Defined in `active_support/core_ext/hash/indifferent_access.rb`.
|
2871
2950
|
|
2951
|
+
### Compacting
|
2952
|
+
|
2953
|
+
The methods `compact` and `compact!` return a Hash without items with `nil` value.
|
2954
|
+
|
2955
|
+
```ruby
|
2956
|
+
{a: 1, b: 2, c: nil}.compact # => {a: 1, b: 2}
|
2957
|
+
```
|
2958
|
+
|
2959
|
+
NOTE: Defined in `active_support/core_ext/hash/compact.rb`.
|
2960
|
+
|
2872
2961
|
Extensions to `Regexp`
|
2873
2962
|
----------------------
|
2874
2963
|
|
@@ -2953,53 +3042,6 @@ The method `Range#overlaps?` says whether any two given ranges have non-void int
|
|
2953
3042
|
|
2954
3043
|
NOTE: Defined in `active_support/core_ext/range/overlaps.rb`.
|
2955
3044
|
|
2956
|
-
Extensions to `Proc`
|
2957
|
-
--------------------
|
2958
|
-
|
2959
|
-
### `bind`
|
2960
|
-
|
2961
|
-
As you surely know Ruby has an `UnboundMethod` class whose instances are methods that belong to the limbo of methods without a self. The method `Module#instance_method` returns an unbound method for example:
|
2962
|
-
|
2963
|
-
```ruby
|
2964
|
-
Hash.instance_method(:delete) # => #<UnboundMethod: Hash#delete>
|
2965
|
-
```
|
2966
|
-
|
2967
|
-
An unbound method is not callable as is, you need to bind it first to an object with `bind`:
|
2968
|
-
|
2969
|
-
```ruby
|
2970
|
-
clear = Hash.instance_method(:clear)
|
2971
|
-
clear.bind({a: 1}).call # => {}
|
2972
|
-
```
|
2973
|
-
|
2974
|
-
Active Support defines `Proc#bind` with an analogous purpose:
|
2975
|
-
|
2976
|
-
```ruby
|
2977
|
-
Proc.new { size }.bind([]).call # => 0
|
2978
|
-
```
|
2979
|
-
|
2980
|
-
As you see that's callable and bound to the argument, the return value is indeed a `Method`.
|
2981
|
-
|
2982
|
-
NOTE: To do so `Proc#bind` actually creates a method under the hood. If you ever see a method with a weird name like `__bind_1256598120_237302` in a stack trace you know now where it comes from.
|
2983
|
-
|
2984
|
-
Action Pack uses this trick in `rescue_from` for example, which accepts the name of a method and also a proc as callbacks for a given rescued exception. It has to call them in either case, so a bound method is returned by `handler_for_rescue`, thus simplifying the code in the caller:
|
2985
|
-
|
2986
|
-
```ruby
|
2987
|
-
def handler_for_rescue(exception)
|
2988
|
-
_, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler|
|
2989
|
-
...
|
2990
|
-
end
|
2991
|
-
|
2992
|
-
case rescuer
|
2993
|
-
when Symbol
|
2994
|
-
method(rescuer)
|
2995
|
-
when Proc
|
2996
|
-
rescuer.bind(self)
|
2997
|
-
end
|
2998
|
-
end
|
2999
|
-
```
|
3000
|
-
|
3001
|
-
NOTE: Defined in `active_support/core_ext/proc.rb`.
|
3002
|
-
|
3003
3045
|
Extensions to `Date`
|
3004
3046
|
--------------------
|
3005
3047
|
|
@@ -3608,9 +3650,9 @@ t.advance(seconds: 1)
|
|
3608
3650
|
|
3609
3651
|
#### `Time.current`
|
3610
3652
|
|
3611
|
-
Active Support defines `Time.current` to be today in the current time zone. That's like `Time.now`, except that it honors the user time zone, if defined. It also defines
|
3653
|
+
Active Support defines `Time.current` to be today in the current time zone. That's like `Time.now`, except that it honors the user time zone, if defined. It also defines the instance predicates `past?`, `today?`, and `future?`, all of them relative to `Time.current`.
|
3612
3654
|
|
3613
|
-
When making Time comparisons using methods which honor the user time zone, make sure to use `Time.current`
|
3655
|
+
When making Time comparisons using methods which honor the user time zone, make sure to use `Time.current` instead of `Time.now`. There are cases where the user time zone might be in the future compared to the system time zone, which `Time.now` uses by default. This means `Time.now.to_date` may equal `Date.yesterday`.
|
3614
3656
|
|
3615
3657
|
#### `all_day`, `all_week`, `all_month`, `all_quarter` and `all_year`
|
3616
3658
|
|
@@ -3774,7 +3816,7 @@ The name may be given as a symbol or string. A symbol is tested against the bare
|
|
3774
3816
|
|
3775
3817
|
TIP: A symbol can represent a fully-qualified constant name as in `:"ActiveRecord::Base"`, so the behavior for symbols is defined for convenience, not because it has to be that way technically.
|
3776
3818
|
|
3777
|
-
For example, when an action of `
|
3819
|
+
For example, when an action of `ArticlesController` is called Rails tries optimistically to use `ArticlesHelper`. It is OK that the helper module does not exist, so if an exception for that constant name is raised it should be silenced. But it could be the case that `articles_helper.rb` raises a `NameError` due to an actual unknown constant. That should be reraised. The method `missing_name?` provides a way to distinguish both cases:
|
3778
3820
|
|
3779
3821
|
```ruby
|
3780
3822
|
def default_helper_module!
|
@@ -3782,7 +3824,7 @@ def default_helper_module!
|
|
3782
3824
|
module_path = module_name.underscore
|
3783
3825
|
helper module_path
|
3784
3826
|
rescue MissingSourceFile => e
|
3785
|
-
raise e unless e.is_missing? "
|
3827
|
+
raise e unless e.is_missing? "helpers/#{module_path}_helper"
|
3786
3828
|
rescue NameError => e
|
3787
3829
|
raise e unless e.missing_name? "#{module_name}Helper"
|
3788
3830
|
end
|
@@ -3797,7 +3839,7 @@ Active Support adds `is_missing?` to `LoadError`, and also assigns that class to
|
|
3797
3839
|
|
3798
3840
|
Given a path name `is_missing?` tests whether the exception was raised due to that particular file (except perhaps for the ".rb" extension).
|
3799
3841
|
|
3800
|
-
For example, when an action of `
|
3842
|
+
For example, when an action of `ArticlesController` is called Rails tries to load `articles_helper.rb`, but that file may not exist. That's fine, the helper module is not mandatory so Rails silences a load error. But it could be the case that the helper module does exist and in turn requires another library that is missing. In that case Rails must reraise the exception. The method `is_missing?` provides a way to distinguish both cases:
|
3801
3843
|
|
3802
3844
|
```ruby
|
3803
3845
|
def default_helper_module!
|