railties 3.0.0.rc → 3.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +80 -75
- data/README.rdoc +1 -1
- data/guides/assets/stylesheets/main.css +14 -14
- data/guides/rails_guides.rb +20 -1
- data/guides/rails_guides/generator.rb +7 -7
- data/guides/source/2_3_release_notes.textile +5 -5
- data/guides/source/3_0_release_notes.textile +4 -3
- data/guides/source/action_controller_overview.textile +32 -17
- data/guides/source/action_view_overview.textile +44 -44
- data/guides/source/active_record_basics.textile +2 -2
- data/guides/source/active_record_querying.textile +7 -7
- data/guides/source/active_record_validations_callbacks.textile +20 -20
- data/guides/source/active_support_core_extensions.textile +370 -198
- data/guides/source/ajax_on_rails.textile +17 -17
- data/guides/source/api_documentation_guidelines.textile +3 -3
- data/guides/source/association_basics.textile +2 -2
- data/guides/source/caching_with_rails.textile +5 -5
- data/guides/source/command_line.textile +8 -8
- data/guides/source/configuring.textile +6 -6
- data/guides/source/contributing_to_rails.textile +14 -11
- data/guides/source/debugging_rails_applications.textile +8 -6
- data/guides/source/form_helpers.textile +1 -1
- data/guides/source/generators.textile +34 -30
- data/guides/source/getting_started.textile +13 -13
- data/guides/source/i18n.textile +12 -1
- data/guides/source/index.html.erb +4 -0
- data/guides/source/initialization.textile +67 -72
- data/guides/source/layout.html.erb +1 -0
- data/guides/source/layouts_and_rendering.textile +9 -9
- data/guides/source/nested_model_forms.textile +7 -7
- data/guides/source/plugins.textile +1 -1
- data/guides/source/rails_application_templates.textile +2 -2
- data/guides/source/routing.textile +27 -5
- data/guides/source/security.textile +6 -6
- data/guides/w3c_validator.rb +9 -9
- data/lib/rails/application.rb +1 -0
- data/lib/rails/application/configuration.rb +1 -1
- data/lib/rails/code_statistics.rb +4 -4
- data/lib/rails/commands.rb +1 -1
- data/lib/rails/commands/dbconsole.rb +1 -1
- data/lib/rails/commands/plugin.rb +1 -1
- data/lib/rails/commands/runner.rb +1 -1
- data/lib/rails/deprecation.rb +31 -52
- data/lib/rails/engine.rb +1 -1
- data/lib/rails/engine/configuration.rb +28 -1
- data/lib/rails/generators.rb +2 -2
- data/lib/rails/generators/actions.rb +3 -3
- data/lib/rails/generators/active_model.rb +3 -3
- data/lib/rails/generators/base.rb +1 -1
- data/lib/rails/generators/rails/app/app_generator.rb +9 -3
- data/lib/rails/generators/rails/app/templates/Gemfile +2 -2
- data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml +4 -13
- data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +1 -1
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/config/routes.rb +4 -4
- data/lib/rails/generators/rails/app/templates/public/index.html +0 -23
- data/lib/rails/generators/rails/app/templates/public/javascripts/effects.js +1 -1
- data/lib/rails/generators/rails/generator/USAGE +3 -2
- data/lib/rails/generators/rails/migration/USAGE +4 -4
- data/lib/rails/generators/rails/plugin/USAGE +1 -1
- data/lib/rails/generators/rails/resource/resource_generator.rb +2 -2
- data/lib/rails/generators/test_case.rb +1 -1
- data/lib/rails/info_controller.rb +1 -1
- data/lib/rails/plugin.rb +1 -1
- data/lib/rails/rack/log_tailer.rb +2 -5
- data/lib/rails/railtie.rb +22 -22
- data/lib/rails/script_rails_loader.rb +2 -2
- data/lib/rails/tasks/documentation.rake +5 -5
- data/lib/rails/tasks/framework.rake +1 -1
- data/lib/rails/tasks/routes.rake +23 -9
- data/lib/rails/test_unit/testing.rake +3 -2
- data/lib/rails/version.rb +1 -1
- metadata +10 -10
@@ -16,7 +16,7 @@ Active Record is the M in "MVC":getting_started.html#the-mvc-architecture - the
|
|
16
16
|
|
17
17
|
h4. The Active Record Pattern
|
18
18
|
|
19
|
-
Active Record was described by Martin Fowler in his book _Patterns of Enterprise Application Architecture_. In Active Record, objects carry both persistent data and behavior which operates on that data. Active Record takes the opinion that ensuring data access logic is part of the object will educate users of that object on how to write to and read from the database.
|
19
|
+
Active Record was described by Martin Fowler in his book _Patterns of Enterprise Application Architecture_. In Active Record, objects carry both persistent data and behavior which operates on that data. Active Record takes the opinion that ensuring data access logic is part of the object will educate users of that object on how to write to and read from the database.
|
20
20
|
|
21
21
|
h4. Object Relational Mapping
|
22
22
|
|
@@ -132,7 +132,7 @@ CRUD is an acronym for the four verbs we use to operate on data: *C*reate, *R*ea
|
|
132
132
|
|
133
133
|
h4. Create
|
134
134
|
|
135
|
-
Active Record objects can be created from a hash, a block or have its attributes manually set after creation. The _new_ method will return a new object while _create_ will return the object and save it to the database.
|
135
|
+
Active Record objects can be created from a hash, a block or have its attributes manually set after creation. The _new_ method will return a new object while _create_ will return the object and save it to the database.
|
136
136
|
|
137
137
|
For example, given a model +User+ with attributes of +name+ and +occupation+, the _create_ method call will create and save a new record into the database:
|
138
138
|
|
@@ -153,7 +153,7 @@ SELECT * FROM clients WHERE (clients.id IN (1,10))
|
|
153
153
|
|
154
154
|
h4. Retrieving Multiple Objects in Batches
|
155
155
|
|
156
|
-
Sometimes you need to iterate over a large set of records. For example to send a newsletter to all users, to export some data, etc.
|
156
|
+
Sometimes you need to iterate over a large set of records. For example to send a newsletter to all users, to export some data, etc.
|
157
157
|
|
158
158
|
The following may seem very straight forward at first:
|
159
159
|
|
@@ -674,7 +674,7 @@ Post.joins(:category, :comments)
|
|
674
674
|
This produces:
|
675
675
|
|
676
676
|
<sql>
|
677
|
-
SELECT posts.* FROM posts
|
677
|
+
SELECT posts.* FROM posts
|
678
678
|
INNER JOIN categories ON posts.category_id = categories.id
|
679
679
|
INNER JOIN comments ON comments.post_id = posts.id
|
680
680
|
</sql>
|
@@ -753,7 +753,7 @@ h4. Eager Loading Multiple Associations
|
|
753
753
|
|
754
754
|
Active Record lets you eager load any number of associations with a single +Model.find+ call by using an array, hash, or a nested hash of array/hash with the +includes+ method.
|
755
755
|
|
756
|
-
h5. Array of Multiple Associations
|
756
|
+
h5. Array of Multiple Associations
|
757
757
|
|
758
758
|
<ruby>
|
759
759
|
Post.includes(:category, :comments)
|
@@ -764,14 +764,14 @@ This loads all the posts and the associated category and comments for each post.
|
|
764
764
|
h5. Nested Associations Hash
|
765
765
|
|
766
766
|
<ruby>
|
767
|
-
Category.
|
767
|
+
Category.includes(:posts => [{:comments => :guest}, :tags]).find(1)
|
768
768
|
</ruby>
|
769
769
|
|
770
770
|
This will find the category with id 1 and eager load all of the associated posts, the associated posts' tags and comments, and every comment's guest association.
|
771
771
|
|
772
772
|
h4. Specifying Conditions on Eager Loaded Associations
|
773
773
|
|
774
|
-
Even though Active Record lets you specify conditions on the eager loaded associations just like +joins+, the recommended way is to use "joins":#joining-tables instead.
|
774
|
+
Even though Active Record lets you specify conditions on the eager loaded associations just like +joins+, the recommended way is to use "joins":#joining-tables instead.
|
775
775
|
|
776
776
|
h3. Dynamic Finders
|
777
777
|
|
@@ -807,8 +807,8 @@ h3. Finding by SQL
|
|
807
807
|
If you'd like to use your own SQL to find records in a table you can use +find_by_sql+. The +find_by_sql+ method will return an array of objects even if the underlying query returns just a single record. For example you could run this query:
|
808
808
|
|
809
809
|
<ruby>
|
810
|
-
Client.find_by_sql("SELECT * FROM clients
|
811
|
-
INNER JOIN orders ON clients.id = orders.client_id
|
810
|
+
Client.find_by_sql("SELECT * FROM clients
|
811
|
+
INNER JOIN orders ON clients.id = orders.client_id
|
812
812
|
ORDER clients.created_at desc")
|
813
813
|
</ruby>
|
814
814
|
|
@@ -16,7 +16,7 @@ endprologue.
|
|
16
16
|
|
17
17
|
h3. The Object Life Cycle
|
18
18
|
|
19
|
-
During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this <em>object life cycle</em> so that you can control your application and its data.
|
19
|
+
During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this <em>object life cycle</em> so that you can control your application and its data.
|
20
20
|
|
21
21
|
Validations allow you to ensure that only valid data is stored in your database. Callbacks and observers allow you to trigger logic before or after an alteration of an object's state.
|
22
22
|
|
@@ -33,7 +33,7 @@ There are several ways to validate data before it is saved into your database, i
|
|
33
33
|
* Database constraints and/or stored procedures make the validation mechanisms database-dependent and can make testing and maintenance more difficult. However, if your database is used by other applications, it may be a good idea to use some constraints at the database level. Additionally, database-level validations can safely handle some things (such as uniqueness in heavily-used tables) that can be difficult to implement otherwise.
|
34
34
|
* Client-side validations can be useful, but are generally unreliable if used alone. If they are implemented using JavaScript, they may be bypassed if JavaScript is turned off in the user's browser. However, if combined with other techniques, client-side validation can be a convenient way to provide users with immediate feedback as they use your site.
|
35
35
|
* Controller-level validations can be tempting to use, but often become unwieldy and difficult to test and maintain. Whenever possible, it's a good idea to "keep your controllers skinny":http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model, as it will make your application a pleasure to work with in the long run.
|
36
|
-
* Model-level validations are the best way to ensure that only valid data is saved into your database. They are database agnostic, cannot be bypassed by end users, and are convenient to test and maintain. Rails makes them easy to use, provides built-in helpers for common needs, and allows you to create your own validation methods as well.
|
36
|
+
* Model-level validations are the best way to ensure that only valid data is saved into your database. They are database agnostic, cannot be bypassed by end users, and are convenient to test and maintain. Rails makes them easy to use, provides built-in helpers for common needs, and allows you to create your own validation methods as well.
|
37
37
|
|
38
38
|
h4. When Does Validation Happen?
|
39
39
|
|
@@ -116,7 +116,7 @@ end
|
|
116
116
|
=> #<Person id: nil, name: nil>
|
117
117
|
>> p.errors
|
118
118
|
=> {}
|
119
|
-
|
119
|
+
|
120
120
|
>> p.valid?
|
121
121
|
=> false
|
122
122
|
>> p.errors
|
@@ -126,7 +126,7 @@ end
|
|
126
126
|
=> #<Person id: nil, name: nil>
|
127
127
|
>> p.errors
|
128
128
|
=> {:name=>["can't be blank"]}
|
129
|
-
|
129
|
+
|
130
130
|
>> p.save
|
131
131
|
=> false
|
132
132
|
|
@@ -368,7 +368,7 @@ class LineItem < ActiveRecord::Base
|
|
368
368
|
end
|
369
369
|
</ruby>
|
370
370
|
|
371
|
-
Since +false.blank?+ is true, if you want to validate the presence of a boolean field you should use +validates_inclusion_of :field_name, :in => [true, false]+.
|
371
|
+
Since +false.blank?+ is true, if you want to validate the presence of a boolean field you should use +validates_inclusion_of :field_name, :in => [true, false]+.
|
372
372
|
|
373
373
|
The default error message for +validates_presence_of+ is "_can't be empty_".
|
374
374
|
|
@@ -550,9 +550,9 @@ end
|
|
550
550
|
|
551
551
|
h3. Creating Custom Validation Methods
|
552
552
|
|
553
|
-
When the built-in validation helpers are not enough for your needs, you can write your own validation methods.
|
553
|
+
When the built-in validation helpers are not enough for your needs, you can write your own validation methods.
|
554
554
|
|
555
|
-
Simply create methods that verify the state of your models and add messages to the +errors+ collection when they are invalid. You must then register these methods by using one or more of the +validate+, +validate_on_create+ or +validate_on_update+ class methods, passing in the symbols for the validation methods' names.
|
555
|
+
Simply create methods that verify the state of your models and add messages to the +errors+ collection when they are invalid. You must then register these methods by using one or more of the +validate+, +validate_on_create+ or +validate_on_update+ class methods, passing in the symbols for the validation methods' names.
|
556
556
|
|
557
557
|
You can pass more than one symbol for each class method and the respective validations will be run in the same order as they were registered.
|
558
558
|
|
@@ -593,7 +593,7 @@ end
|
|
593
593
|
|
594
594
|
h3. Working with Validation Errors
|
595
595
|
|
596
|
-
In addition to the +valid?+ and +invalid?+ methods covered earlier, Rails provides a number of methods for working with the +errors+ collection and inquiring about the validity of objects.
|
596
|
+
In addition to the +valid?+ and +invalid?+ methods covered earlier, Rails provides a number of methods for working with the +errors+ collection and inquiring about the validity of objects.
|
597
597
|
|
598
598
|
The following is a list of the most commonly used methods. Please refer to the +ActiveRecord::Errors+ documentation for a list of all the available methods.
|
599
599
|
|
@@ -611,7 +611,7 @@ person = Person.new
|
|
611
611
|
person.valid? # => false
|
612
612
|
person.errors
|
613
613
|
# => {:name => ["can't be blank", "is too short (minimum is 3 characters)"]}
|
614
|
-
|
614
|
+
|
615
615
|
person = Person.new(:name => "John Doe")
|
616
616
|
person.valid? # => true
|
617
617
|
person.errors # => []
|
@@ -660,7 +660,7 @@ person.errors[:name]
|
|
660
660
|
person.errors.full_messages
|
661
661
|
# => ["Name cannot contain the characters !@#%*()_-+="]
|
662
662
|
</ruby>
|
663
|
-
|
663
|
+
|
664
664
|
Another way to do this is using +[]=+ setter
|
665
665
|
|
666
666
|
<ruby>
|
@@ -739,7 +739,7 @@ person.errors.size # => 0
|
|
739
739
|
|
740
740
|
h3. Displaying Validation Errors in the View
|
741
741
|
|
742
|
-
Rails provides built-in helpers to display the error messages of your models in your view templates.
|
742
|
+
Rails provides built-in helpers to display the error messages of your models in your view templates.
|
743
743
|
|
744
744
|
h4. +error_messages+ and +error_messages_for+
|
745
745
|
|
@@ -811,7 +811,7 @@ The name of the class and the id can be changed with the +:class+ and +:id+ opti
|
|
811
811
|
|
812
812
|
h4. Customizing the Error Messages HTML
|
813
813
|
|
814
|
-
By default, form fields with errors are displayed enclosed by a +div+ element with the +field_with_errors+ CSS class. However, it's possible to override that.
|
814
|
+
By default, form fields with errors are displayed enclosed by a +div+ element with the +field_with_errors+ CSS class. However, it's possible to override that.
|
815
815
|
|
816
816
|
The way form fields with errors are treated is defined by +ActionView::Base.field_error_proc+. This is a +Proc+ that receives two parameters:
|
817
817
|
|
@@ -865,7 +865,7 @@ The macro-style class methods can also receive a block. Consider using this styl
|
|
865
865
|
class User < ActiveRecord::Base
|
866
866
|
validates_presence_of :login, :email
|
867
867
|
|
868
|
-
before_create {|user| user.name = user.login.capitalize
|
868
|
+
before_create {|user| user.name = user.login.capitalize
|
869
869
|
if user.name.blank?}
|
870
870
|
end
|
871
871
|
</ruby>
|
@@ -967,7 +967,7 @@ The +after_initialize+ callback is triggered every time a new object of the clas
|
|
967
967
|
|
968
968
|
h3. Skipping Callbacks
|
969
969
|
|
970
|
-
Just as with validations, it's also possible to skip callbacks. These methods should be used with caution, however, because important business rules and application logic may be kept in callbacks. Bypassing them without understanding the potential implications may lead to invalid data.
|
970
|
+
Just as with validations, it's also possible to skip callbacks. These methods should be used with caution, however, because important business rules and application logic may be kept in callbacks. Bypassing them without understanding the potential implications may lead to invalid data.
|
971
971
|
|
972
972
|
* +decrement+
|
973
973
|
* +decrement_counter+
|
@@ -982,7 +982,7 @@ Just as with validations, it's also possible to skip callbacks. These methods sh
|
|
982
982
|
|
983
983
|
h3. Halting Execution
|
984
984
|
|
985
|
-
As you start registering new callbacks for your models, they will be queued for execution. This queue will include all your model's validations, the registered callbacks, and the database operation to be executed.
|
985
|
+
As you start registering new callbacks for your models, they will be queued for execution. This queue will include all your model's validations, the registered callbacks, and the database operation to be executed.
|
986
986
|
|
987
987
|
The whole callback chain is wrapped in a transaction. If any <em>before</em> callback method returns exactly +false+ or raises an exception the execution chain gets halted and a ROLLBACK is issued; <em>after</em> callbacks can only accomplish that by raising an exception.
|
988
988
|
|
@@ -990,11 +990,11 @@ WARNING. Raising an arbitrary exception may break code that expects +save+ and f
|
|
990
990
|
|
991
991
|
h3. Relational Callbacks
|
992
992
|
|
993
|
-
Callbacks work through model relationships, and can even be defined by them. Let's take an example where a user has many posts. In our example, a user's posts should be destroyed if the user is destroyed. So, we'll add an +after_destroy+ callback to the +User+ model by way of its relationship to the +Post+ model.
|
993
|
+
Callbacks work through model relationships, and can even be defined by them. Let's take an example where a user has many posts. In our example, a user's posts should be destroyed if the user is destroyed. So, we'll add an +after_destroy+ callback to the +User+ model by way of its relationship to the +Post+ model.
|
994
994
|
|
995
995
|
<ruby>
|
996
996
|
class User < ActiveRecord::Base
|
997
|
-
has_many :posts, :dependent => :destroy
|
997
|
+
has_many :posts, :dependent => :destroy
|
998
998
|
end
|
999
999
|
|
1000
1000
|
class Post < ActiveRecord::Base
|
@@ -1069,7 +1069,7 @@ Here's an example where we create a class with an +after_destroy+ callback for a
|
|
1069
1069
|
<ruby>
|
1070
1070
|
class PictureFileCallbacks
|
1071
1071
|
def after_destroy(picture_file)
|
1072
|
-
File.delete(picture_file.filepath)
|
1072
|
+
File.delete(picture_file.filepath)
|
1073
1073
|
if File.exists?(picture_file.filepath)
|
1074
1074
|
end
|
1075
1075
|
end
|
@@ -1088,7 +1088,7 @@ Note that we needed to instantiate a new +PictureFileCallbacks+ object, since we
|
|
1088
1088
|
<ruby>
|
1089
1089
|
class PictureFileCallbacks
|
1090
1090
|
def self.after_destroy(picture_file)
|
1091
|
-
File.delete(picture_file.filepath)
|
1091
|
+
File.delete(picture_file.filepath)
|
1092
1092
|
if File.exists?(picture_file.filepath)
|
1093
1093
|
end
|
1094
1094
|
end
|
@@ -1144,7 +1144,7 @@ By default, Rails will simply strip "Observer" from an observer's name to find t
|
|
1144
1144
|
<ruby>
|
1145
1145
|
class MailerObserver < ActiveRecord::Observer
|
1146
1146
|
observe :registration, :user
|
1147
|
-
|
1147
|
+
|
1148
1148
|
def after_create(model)
|
1149
1149
|
# code to send confirmation email...
|
1150
1150
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
h2. Active Support Core Extensions
|
2
2
|
|
3
|
-
Active Support is the Rails component responsible for providing Ruby language extensions, utilities, and other transversal stuff.
|
3
|
+
Active Support is the Ruby on Rails component responsible for providing Ruby language extensions, utilities, and other transversal stuff.
|
4
4
|
|
5
|
-
|
5
|
+
It offers a richer bottom-line at the language level, targeted both at the development of Rails applications, and at the development of Ruby on Rails itself.
|
6
|
+
|
7
|
+
By referring to this guide you will learn the extensions to the Ruby core classes and modules provided by Active Support.
|
6
8
|
|
7
9
|
endprologue.
|
8
10
|
|
@@ -84,32 +86,25 @@ The following values are considered to be blank in a Rails application:
|
|
84
86
|
|
85
87
|
WARNING: Note that numbers are not mentioned, in particular 0 and 0.0 are *not* blank.
|
86
88
|
|
87
|
-
For example, this method from +ActionDispatch::
|
89
|
+
For example, this method from +ActionDispatch::Session::AbstractStore+ uses +blank?+ for checking whether a session key is present:
|
88
90
|
|
89
91
|
<ruby>
|
90
|
-
def
|
91
|
-
|
92
|
-
|
92
|
+
def ensure_session_key!
|
93
|
+
if @key.blank?
|
94
|
+
raise ArgumentError, 'A key is required...'
|
95
|
+
end
|
93
96
|
end
|
94
97
|
</ruby>
|
95
98
|
|
96
|
-
|
97
|
-
|
98
|
-
Here, the method Rails runs to instantiate observers upon initialization has nothing to do if there are none:
|
99
|
+
The method +present?+ is equivalent to +!blank?+. This example is taken from +ActionDispatch::Http::Cache::Response+:
|
99
100
|
|
100
101
|
<ruby>
|
101
|
-
def
|
102
|
-
return if
|
103
|
-
|
102
|
+
def set_conditional_cache_control!
|
103
|
+
return if self["Cache-Control"].present?
|
104
|
+
...
|
104
105
|
end
|
105
106
|
</ruby>
|
106
107
|
|
107
|
-
The method +present?+ is equivalent to +!blank?+:
|
108
|
-
|
109
|
-
<ruby>
|
110
|
-
assert @response.body.present? # same as !@response.body.blank?
|
111
|
-
</ruby>
|
112
|
-
|
113
108
|
NOTE: Defined in +active_support/core_ext/object/blank.rb+.
|
114
109
|
|
115
110
|
h4. +presence+
|
@@ -151,28 +146,17 @@ Active Support provides +duplicable?+ to programmatically query an object about
|
|
151
146
|
false.duplicable? # => false
|
152
147
|
</ruby>
|
153
148
|
|
154
|
-
By definition all objects are +duplicable?+ except +nil+, +false+, +true+, symbols, numbers, and class objects.
|
149
|
+
By definition all objects are +duplicable?+ except +nil+, +false+, +true+, symbols, numbers, and class and module objects.
|
155
150
|
|
156
|
-
WARNING.
|
151
|
+
WARNING. Any class can disallow duplication removing +dup+ and +clone+ or raising exceptions from them, 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.
|
157
152
|
|
158
153
|
NOTE: Defined in +active_support/core_ext/object/duplicable.rb+.
|
159
154
|
|
160
155
|
h4. +try+
|
161
156
|
|
162
|
-
Sometimes you want to call a method provided the receiver object is not +nil+, which is something you usually check first.
|
163
|
-
|
164
|
-
For instance, note how this method of +ActiveRecord::ConnectionAdapters::AbstractAdapter+ checks if there's a +@logger+:
|
157
|
+
Sometimes you want to call a method provided the receiver object is not +nil+, which is something you usually check first. +try+ is like +Object#send+ except that it returns +nil+ if sent to +nil+.
|
165
158
|
|
166
|
-
|
167
|
-
def log_info(sql, name, ms)
|
168
|
-
if @logger && @logger.debug?
|
169
|
-
name = '%s (%.1fms)' % [name || 'SQL', ms]
|
170
|
-
@logger.debug(format_log_entry(name, sql.squeeze(' ')))
|
171
|
-
end
|
172
|
-
end
|
173
|
-
</ruby>
|
174
|
-
|
175
|
-
You can shorten that using +Object#try+. This method is a synonym for +Object#send+ except that it returns +nil+ if sent to +nil+. The previous example could then be rewritten as:
|
159
|
+
For instance, in this code from +ActiveRecord::ConnectionAdapters::AbstractAdapter+ +@logger+ could be +nil+, but you save the check and write in an optimistic style:
|
176
160
|
|
177
161
|
<ruby>
|
178
162
|
def log_info(sql, name, ms)
|
@@ -364,7 +348,7 @@ That idiom may convey _grouping_ to the reader as well. For example, say you wan
|
|
364
348
|
<ruby>
|
365
349
|
I18n.with_options :locale => user.locale, :scope => "newsletter" do |i18n|
|
366
350
|
subject i18n.t :subject
|
367
|
-
body i18n.t :body, :user_name => user.name
|
351
|
+
body i18n.t :body, :user_name => user.name
|
368
352
|
end
|
369
353
|
</ruby>
|
370
354
|
|
@@ -667,129 +651,6 @@ end
|
|
667
651
|
|
668
652
|
NOTE: Defined in +active_support/core_ext/module/attribute_accessors.rb+.
|
669
653
|
|
670
|
-
h4. Method Delegation
|
671
|
-
|
672
|
-
The class method +delegate+ offers an easy way to forward methods.
|
673
|
-
|
674
|
-
For example, if +User+ has some details like the age factored out to +Profile+, it could be handy to still be able to access such attributes directly, <tt>user.age</tt>, instead of having to explicit the chain <tt>user.profile.age</tt>.
|
675
|
-
|
676
|
-
That can be accomplished by hand:
|
677
|
-
|
678
|
-
<ruby>
|
679
|
-
class User
|
680
|
-
has_one :profile
|
681
|
-
|
682
|
-
def age
|
683
|
-
profile.age
|
684
|
-
end
|
685
|
-
end
|
686
|
-
</ruby>
|
687
|
-
|
688
|
-
But with +delegate+ you can make that shorter and the intention even more obvious:
|
689
|
-
|
690
|
-
<ruby>
|
691
|
-
class User
|
692
|
-
has_one :profile
|
693
|
-
|
694
|
-
delegate :age, to => :profile
|
695
|
-
end
|
696
|
-
</ruby>
|
697
|
-
|
698
|
-
The macro accepts more than one method:
|
699
|
-
|
700
|
-
<ruby>
|
701
|
-
class User
|
702
|
-
has_one :profile
|
703
|
-
|
704
|
-
delegate :age, :avatar, :twitter_username, to => :profile
|
705
|
-
end
|
706
|
-
</ruby>
|
707
|
-
|
708
|
-
Methods can be delegated to objects returned by methods, as in the examples above, but also to instance variables, class variables, and constants. Just pass their names as symbols or strings, including the at signs in the last cases.
|
709
|
-
|
710
|
-
For example, +ActionView::Base+ delegates +erb_trim_mode=+:
|
711
|
-
|
712
|
-
<ruby>
|
713
|
-
module ActionView
|
714
|
-
class Base
|
715
|
-
delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB'
|
716
|
-
end
|
717
|
-
end
|
718
|
-
</ruby>
|
719
|
-
|
720
|
-
In fact, you can delegate to any expression passed as a string. It will be evaluated in the context of the receiver. Controllers for example delegate alerts and notices to the current flash:
|
721
|
-
|
722
|
-
<ruby>
|
723
|
-
delegate :alert, :notice, :to => "request.flash"
|
724
|
-
</ruby>
|
725
|
-
|
726
|
-
If the target is +nil+ calling any delegated method will raise an exception even if +nil+ responds to such method. You can override this behavior setting the option +:allow_nil+ to true, in which case the forwarded call will simply return +nil+.
|
727
|
-
|
728
|
-
If the target is a method, the name of delegated methods can also be prefixed. If the +:prefix+ option is set to (exactly) the +true+ object, the value of the +:to+ option is prefixed:
|
729
|
-
|
730
|
-
<ruby>
|
731
|
-
class Invoice
|
732
|
-
belongs_to :customer
|
733
|
-
|
734
|
-
# defines a method called customer_name
|
735
|
-
delegate :name, :to => :customer, :prefix => true
|
736
|
-
end
|
737
|
-
</ruby>
|
738
|
-
|
739
|
-
And a custom prefix can be set as well, in that case it does not matter wheter the target is a method or not:
|
740
|
-
|
741
|
-
<ruby>
|
742
|
-
class Account
|
743
|
-
belongs_to :user
|
744
|
-
|
745
|
-
# defines a method called admin_email
|
746
|
-
delegate :email, :to => :user, :prefix => 'admin'
|
747
|
-
end
|
748
|
-
</ruby>
|
749
|
-
|
750
|
-
NOTE: Defined in +active_support/core_ext/module/delegation.rb+.
|
751
|
-
|
752
|
-
h4. Method Removal
|
753
|
-
|
754
|
-
h5. +remove_possible_method+
|
755
|
-
|
756
|
-
The method +remove_possible_method+ is like the standard +remove_method+, except it silently returns on failure:
|
757
|
-
|
758
|
-
<ruby>
|
759
|
-
class A; end
|
760
|
-
|
761
|
-
A.class_eval do
|
762
|
-
remove_method(:nonexistent) # raises NameError
|
763
|
-
remove_possible_method(:nonexistent) # no problem, continue
|
764
|
-
end
|
765
|
-
</ruby>
|
766
|
-
|
767
|
-
This may come in handy if you need to define a method that may already exist, since redefining a method issues a warning "method redefined; discarding old redefined_method_name".
|
768
|
-
|
769
|
-
h5. +redefine_method(method_name, &block)+
|
770
|
-
|
771
|
-
The method first removes method with given name (using +remove_possible_method+) and then defines new one.
|
772
|
-
|
773
|
-
<ruby>
|
774
|
-
class A; end
|
775
|
-
|
776
|
-
A.class_eval do
|
777
|
-
redefine_method(:foobar) do |foo|
|
778
|
-
#do something here
|
779
|
-
end
|
780
|
-
|
781
|
-
#Code above does the same as this:
|
782
|
-
|
783
|
-
method_name = :foobar
|
784
|
-
remove_possible_method(method_name)
|
785
|
-
define_method(method_name) do |foo|
|
786
|
-
#do something here
|
787
|
-
end
|
788
|
-
end
|
789
|
-
</ruby>
|
790
|
-
|
791
|
-
NOTE: Defined in +active_support/core_ext/module/remove_method.rb+.
|
792
|
-
|
793
654
|
h4. Parents
|
794
655
|
|
795
656
|
h5. +parent+
|
@@ -901,7 +762,7 @@ class Counter
|
|
901
762
|
end
|
902
763
|
</ruby>
|
903
764
|
|
904
|
-
The method receives the name of an action, and a +:with+ option with code. The code is evaluated in the context of the receiver each time the method is invoked, and it should evaluate to a +Mutex+ instance or any other object that responds to +synchronize+ and accepts a block.
|
765
|
+
The method receives the name of an action, and a +:with+ option with code. The code is evaluated in the context of the receiver each time the method is invoked, and it should evaluate to a +Mutex+ instance or any other object that responds to +synchronize+ and accepts a block.
|
905
766
|
|
906
767
|
NOTE: Defined in +active_support/core_ext/module/synchronization.rb+.
|
907
768
|
|
@@ -984,6 +845,121 @@ though an anonymous module is unreachable by definition.
|
|
984
845
|
|
985
846
|
NOTE: Defined in +active_support/core_ext/module/anonymous.rb+.
|
986
847
|
|
848
|
+
h4. Method Delegation
|
849
|
+
|
850
|
+
The macro +delegate+ offers an easy way to forward methods.
|
851
|
+
|
852
|
+
Let's imagine that users in some application have login information in the +User+ model but name and other data in a separate +Profile+ model:
|
853
|
+
|
854
|
+
<ruby>
|
855
|
+
class User < ActiveRecord::Base
|
856
|
+
has_one :profile
|
857
|
+
end
|
858
|
+
</ruby>
|
859
|
+
|
860
|
+
With that configuration you get a user's name via his profile, +user.profile.name+, but it could be handy to still be able to access such attribute directly:
|
861
|
+
|
862
|
+
<ruby>
|
863
|
+
class User < ActiveRecord::Base
|
864
|
+
has_one :profile
|
865
|
+
|
866
|
+
def name
|
867
|
+
profile.name
|
868
|
+
end
|
869
|
+
end
|
870
|
+
</ruby>
|
871
|
+
|
872
|
+
That is what +delegate+ does for you:
|
873
|
+
|
874
|
+
<ruby>
|
875
|
+
class User < ActiveRecord::Base
|
876
|
+
has_one :profile
|
877
|
+
|
878
|
+
delegate :name, :to => :profile
|
879
|
+
end
|
880
|
+
</ruby>
|
881
|
+
|
882
|
+
It is shorter, and the intention more obvious.
|
883
|
+
|
884
|
+
The macro accepts several methods:
|
885
|
+
|
886
|
+
<ruby>
|
887
|
+
delegate :name, :age, :address, :twitter, :to => :profile
|
888
|
+
</ruby>
|
889
|
+
|
890
|
+
When interpolated into a string, the +:to+ option should become an expression that evaluates to the object the method is delegated to. Typically a string or symbol. Such a expression is evaluated in the context of the receiver:
|
891
|
+
|
892
|
+
<ruby>
|
893
|
+
# delegates to the Rails constant
|
894
|
+
delegate :logger, :to => :Rails
|
895
|
+
|
896
|
+
# delegates to the receiver's class
|
897
|
+
delegate :table_name, :to => 'self.class'
|
898
|
+
</ruby>
|
899
|
+
|
900
|
+
WARNING: If the +:prefix+ option is +true+ this is less generic, see below.
|
901
|
+
|
902
|
+
By default, if the delegation raises +NoMethodError+ and the target is +nil+ the exception is propagated. You can ask that +nil+ is returned instead with the +:allow_nil+ option:
|
903
|
+
|
904
|
+
<ruby>
|
905
|
+
delegate :name, :to => :profile, :allow_nil => true
|
906
|
+
</ruby>
|
907
|
+
|
908
|
+
With +:allow_nil+ the call +user.name+ returns +nil+ if the user has no profile.
|
909
|
+
|
910
|
+
The option +:prefix+ adds a prefix to the name of the generated method. This may be handy for example to get a better name:
|
911
|
+
|
912
|
+
<ruby>
|
913
|
+
delegate :street, :to => :address, :prefix => true
|
914
|
+
</ruby>
|
915
|
+
|
916
|
+
The previous example generates +address_street+ rather than +street+.
|
917
|
+
|
918
|
+
WARNING: Since in this case the name of the generated method is composed of the target object and target method names, the +:to+ option must be a method name.
|
919
|
+
|
920
|
+
A custom prefix may also be configured:
|
921
|
+
|
922
|
+
<ruby>
|
923
|
+
delegate :size, :to => :attachment, :prefix => :avatar
|
924
|
+
</ruby>
|
925
|
+
|
926
|
+
In the previous example the macro generates +avatar_size+ rather than +size+.
|
927
|
+
|
928
|
+
NOTE: Defined in +active_support/core_ext/module/delegation.rb+
|
929
|
+
|
930
|
+
h4. Method Names
|
931
|
+
|
932
|
+
The builtin methods +instance_methods+ and +methods+ return method names as strings or symbols depending on the Ruby version. Active Support defines +instance_method_names+ and +method_names+ to be equivalent to them, respectively, but always getting strings back.
|
933
|
+
|
934
|
+
For example, +ActionView::Helpers::FormBuilder+ knows this array difference is going to work no matter the Ruby version:
|
935
|
+
|
936
|
+
<ruby>
|
937
|
+
self.field_helpers = (FormHelper.instance_method_names - ['form_for'])
|
938
|
+
</ruby>
|
939
|
+
|
940
|
+
NOTE: Defined in +active_support/core_ext/module/method_names.rb+
|
941
|
+
|
942
|
+
h4. Redefining Methods
|
943
|
+
|
944
|
+
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.
|
945
|
+
|
946
|
+
The method +redefine_method+ prevents such a potential warning, removing the existing method before if needed. Rails uses it in a few places, for instance when it generates an association's API:
|
947
|
+
|
948
|
+
<ruby>
|
949
|
+
redefine_method("#{reflection.name}=") do |new_value|
|
950
|
+
association = association_instance_get(reflection.name)
|
951
|
+
|
952
|
+
if association.nil? || association.target != new_value
|
953
|
+
association = association_proxy_class.new(self, reflection)
|
954
|
+
end
|
955
|
+
|
956
|
+
association.replace(new_value)
|
957
|
+
association_instance_set(reflection.name, new_value.nil? ? nil : association)
|
958
|
+
end
|
959
|
+
</ruby>
|
960
|
+
|
961
|
+
NOTE: Defined in +active_support/core_ext/module/remove_method.rb+
|
962
|
+
|
987
963
|
h3. Extensions to +Class+
|
988
964
|
|
989
965
|
h4. Class Attributes
|
@@ -1131,25 +1107,10 @@ module ActiveRecord
|
|
1131
1107
|
end
|
1132
1108
|
</ruby>
|
1133
1109
|
|
1134
|
-
Since values are copied when a subclass is defined, if the base class changes the attribute after that, the subclass does not see the new value. That's the point.
|
1110
|
+
Since values are copied when a subclass is defined, if the base class changes the attribute after that, the subclass does not see the new value. That's the point.
|
1135
1111
|
|
1136
1112
|
NOTE: Defined in +active_support/core_ext/class/inheritable_attributes.rb+.
|
1137
1113
|
|
1138
|
-
There's a related macro called +superclass_delegating_accessor+, however, that does not copy the value when the base class is subclassed. Instead, it delegates reading to the superclass as long as the attribute is not set via its own writer. For example, +ActionMailer::Base+ defines +delivery_method+ this way:
|
1139
|
-
|
1140
|
-
<ruby>
|
1141
|
-
module ActionMailer
|
1142
|
-
class Base
|
1143
|
-
superclass_delegating_accessor :delivery_method
|
1144
|
-
self.delivery_method = :smtp
|
1145
|
-
end
|
1146
|
-
end
|
1147
|
-
</ruby>
|
1148
|
-
|
1149
|
-
If for whatever reason an application loads the definition of a mailer class and after that sets +ActionMailer::Base.delivery_method+, the mailer class will still see the new value. In addition, the mailer class is able to change the +delivery_method+ without affecting the value in the parent using its own inherited class attribute writer.
|
1150
|
-
|
1151
|
-
NOTE: Defined in +active_support/core_ext/class/delegating_attributes.rb+.
|
1152
|
-
|
1153
1114
|
h4. Subclasses & Descendants
|
1154
1115
|
|
1155
1116
|
h5. +subclasses+
|
@@ -1178,7 +1139,7 @@ NOTE: Defined in +active_support/core_ext/class/subclasses.rb+.
|
|
1178
1139
|
|
1179
1140
|
h5. +descendants+
|
1180
1141
|
|
1181
|
-
The +descendants+ method returns all classes that are <tt><</tt> than its receiver:
|
1142
|
+
The +descendants+ method returns all classes that are <tt><</tt> than its receiver:
|
1182
1143
|
|
1183
1144
|
<ruby>
|
1184
1145
|
class C; end
|
@@ -1299,7 +1260,7 @@ Pass a +:separator+ to truncate the string at a natural break:
|
|
1299
1260
|
|
1300
1261
|
<ruby>
|
1301
1262
|
"Oh dear! Oh dear! I shall be late!".truncate(18)
|
1302
|
-
# => "Oh dear! Oh dea..."
|
1263
|
+
# => "Oh dear! Oh dea..."
|
1303
1264
|
"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => ' ')
|
1304
1265
|
# => "Oh dear! Oh..."
|
1305
1266
|
</ruby>
|
@@ -1790,7 +1751,7 @@ The methods +to_date+, +to_time+, and +to_datetime+ are basically convenience wr
|
|
1790
1751
|
<ruby>
|
1791
1752
|
"2010-07-27".to_date # => Tue, 27 Jul 2010
|
1792
1753
|
"2010-07-27 23:37:00".to_time # => Tue Jul 27 23:37:00 UTC 2010
|
1793
|
-
"2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000
|
1754
|
+
"2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000
|
1794
1755
|
</ruby>
|
1795
1756
|
|
1796
1757
|
+to_time+ receives an optional argument +:utc+ or +:local+, to indicate which time zone you want the time in:
|
@@ -2229,7 +2190,27 @@ NOTE: Defined in +active_support/core_ext/array/conversions.rb+.
|
|
2229
2190
|
|
2230
2191
|
h4. Wrapping
|
2231
2192
|
|
2232
|
-
The
|
2193
|
+
The method +Array.wrap+ wraps its argument in an array unless it is already an array (or array-like).
|
2194
|
+
|
2195
|
+
Specifically:
|
2196
|
+
|
2197
|
+
* If the argument is +nil+ an empty list is returned.
|
2198
|
+
* Otherwise, if the argument responds to +to_ary+ it is invoked, and its result returned.
|
2199
|
+
* Otherwise, returns an array with the argument as its single element.
|
2200
|
+
|
2201
|
+
<ruby>
|
2202
|
+
Array.wrap(nil) # => []
|
2203
|
+
Array.wrap([1, 2, 3]) # => [1, 2, 3]
|
2204
|
+
Array.wrap(0) # => [0]
|
2205
|
+
</ruby>
|
2206
|
+
|
2207
|
+
This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
|
2208
|
+
|
2209
|
+
* If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt> moves on to try +to_a+ if the returned value is +nil+, but <tt>Arraw.wrap</tt> returns such a +nil+ right away.
|
2210
|
+
* If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt> raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
|
2211
|
+
* It does not call +to_a+ on the argument, though special-cases +nil+ to return an empty array.
|
2212
|
+
|
2213
|
+
The last point is particularly worth comparing for some enumerables:
|
2233
2214
|
|
2234
2215
|
<ruby>
|
2235
2216
|
Array.wrap(:foo => :bar) # => [{:foo => :bar}]
|
@@ -2239,6 +2220,16 @@ Array.wrap("foo\nbar") # => ["foo\nbar"]
|
|
2239
2220
|
Array("foo\nbar") # => ["foo\n", "bar"], in Ruby 1.8
|
2240
2221
|
</ruby>
|
2241
2222
|
|
2223
|
+
There's also a related idiom that uses the splat operator:
|
2224
|
+
|
2225
|
+
<ruby>
|
2226
|
+
[*object]
|
2227
|
+
</ruby>
|
2228
|
+
|
2229
|
+
which returns +[nil]+ for +nil+, and calls to <tt>Array(object)</tt> otherwise
|
2230
|
+
|
2231
|
+
Thus, in this case the behavior is different for +nil+, and the differences with <tt>Kernel#Array</tt> explained above apply to the rest of +object+s.
|
2232
|
+
|
2242
2233
|
NOTE: Defined in +active_support/core_ext/array/wrap.rb+.
|
2243
2234
|
|
2244
2235
|
h4. Grouping
|
@@ -2964,11 +2955,11 @@ Note in the previous example that increments may be negative.
|
|
2964
2955
|
|
2965
2956
|
To perform the computation the method first increments years, then months, then weeks, and finally days. This order is important towards the end of months. Say for example we are at the end of February of 2010, and we want to move one month and one day forward.
|
2966
2957
|
|
2967
|
-
The method +advance+ advances first one month, and
|
2958
|
+
The method +advance+ advances first one month, and then one day, the result is:
|
2968
2959
|
|
2969
2960
|
<ruby>
|
2970
|
-
Date.new(2010, 2, 28).advance(:months => 1, :
|
2971
|
-
# => Sun,
|
2961
|
+
Date.new(2010, 2, 28).advance(:months => 1, :days => 1)
|
2962
|
+
# => Sun, 29 Mar 2010
|
2972
2963
|
</ruby>
|
2973
2964
|
|
2974
2965
|
While if it did it the other way around the result would be different:
|
@@ -2994,6 +2985,26 @@ Date.new(2010, 1, 31).change(:month => 2)
|
|
2994
2985
|
# => ArgumentError: invalid date
|
2995
2986
|
</ruby>
|
2996
2987
|
|
2988
|
+
h5. Durations
|
2989
|
+
|
2990
|
+
Durations can be added and substracted to dates:
|
2991
|
+
|
2992
|
+
<ruby>
|
2993
|
+
d = Date.current
|
2994
|
+
# => Mon, 09 Aug 2010
|
2995
|
+
d + 1.year
|
2996
|
+
# => Tue, 09 Aug 2011
|
2997
|
+
d - 3.hours
|
2998
|
+
# => Sun, 08 Aug 2010 21:00:00 UTC +00:00
|
2999
|
+
</ruby>
|
3000
|
+
|
3001
|
+
They translate to calls to +since+ or +advance+. For example here we get the correct jump in the calendar reform:
|
3002
|
+
|
3003
|
+
<ruby>
|
3004
|
+
Date.new(1582, 10, 4) + 1.day
|
3005
|
+
# => Fri, 15 Oct 1582
|
3006
|
+
</ruby>
|
3007
|
+
|
2997
3008
|
h5. Timestamps
|
2998
3009
|
|
2999
3010
|
INFO: The following methods return a +Time+ object if possible, otherwise a +DateTime+. If set, they honor the user time zone.
|
@@ -3021,14 +3032,14 @@ h6. +ago+, +since+
|
|
3021
3032
|
The method +ago+ receives a number of seconds as argument and returns a timestamp those many seconds ago from midnight:
|
3022
3033
|
|
3023
3034
|
<ruby>
|
3024
|
-
date = Date.current # => Fri, 11 Jun 2010
|
3035
|
+
date = Date.current # => Fri, 11 Jun 2010
|
3025
3036
|
date.ago(1) # => Thu, 10 Jun 2010 23:59:59 EDT -04:00
|
3026
3037
|
</ruby>
|
3027
3038
|
|
3028
3039
|
Similarly, +since+ moves forward:
|
3029
3040
|
|
3030
3041
|
<ruby>
|
3031
|
-
date = Date.current # => Fri, 11 Jun 2010
|
3042
|
+
date = Date.current # => Fri, 11 Jun 2010
|
3032
3043
|
date.since(1) # => Fri, 11 Jun 2010 00:00:01 EDT -04:00
|
3033
3044
|
</ruby>
|
3034
3045
|
|
@@ -3038,30 +3049,30 @@ h4(#date-conversions). Conversions
|
|
3038
3049
|
|
3039
3050
|
h3. Extensions to +DateTime+
|
3040
3051
|
|
3041
|
-
NOTE: All the following methods are defined in +active_support/core_ext/date_time/calculations.rb+.
|
3042
|
-
|
3043
3052
|
WARNING: +DateTime+ is not aware of DST rules and so some of these methods have edge cases when a DST change is going on. For example +seconds_since_midnight+ might not return the real amount in such a day.
|
3044
3053
|
|
3045
3054
|
h4(#calculations-datetime). Calculations
|
3046
3055
|
|
3056
|
+
NOTE: All the following methods are defined in +active_support/core_ext/date_time/calculations.rb+.
|
3057
|
+
|
3047
3058
|
The class +DateTime+ is a subclass of +Date+ so by loading +active_support/core_ext/date/calculations.rb+ you inherit these methods and their aliases, except that they will always return datetimes:
|
3048
3059
|
|
3049
3060
|
<ruby>
|
3050
3061
|
yesterday
|
3051
3062
|
tomorrow
|
3052
|
-
beginning_of_week
|
3053
|
-
end_on_week
|
3063
|
+
beginning_of_week (monday, at_beginning_of_week)
|
3064
|
+
end_on_week (at_end_of_week)
|
3054
3065
|
next_week
|
3055
3066
|
months_ago
|
3056
3067
|
months_since
|
3057
|
-
beginning_of_month
|
3058
|
-
end_of_month
|
3068
|
+
beginning_of_month (at_beginning_of_month)
|
3069
|
+
end_of_month (at_end_of_month)
|
3059
3070
|
prev_month
|
3060
3071
|
next_month
|
3061
|
-
beginning_of_quarter
|
3062
|
-
end_of_quarter
|
3063
|
-
beginning_of_year
|
3064
|
-
end_of_year
|
3072
|
+
beginning_of_quarter (at_beginning_of_quarter)
|
3073
|
+
end_of_quarter (at_end_of_quarter)
|
3074
|
+
beginning_of_year (at_beginning_of_year)
|
3075
|
+
end_of_year (at_end_of_year)
|
3065
3076
|
years_ago
|
3066
3077
|
years_since
|
3067
3078
|
prev_year
|
@@ -3071,10 +3082,10 @@ next_year
|
|
3071
3082
|
The following methods are reimplemented so you do *not* need to load +active_support/core_ext/date/calculations.rb+ for these ones:
|
3072
3083
|
|
3073
3084
|
<ruby>
|
3074
|
-
beginning_of_day
|
3085
|
+
beginning_of_day (midnight, at_midnight, at_beginning_of_day)
|
3075
3086
|
end_of_day
|
3076
3087
|
ago
|
3077
|
-
since
|
3088
|
+
since (in)
|
3078
3089
|
</ruby>
|
3079
3090
|
|
3080
3091
|
On the other hand, +advance+ and +change+ are also defined and support more options, they are documented below.
|
@@ -3117,6 +3128,37 @@ now.utc? # => false
|
|
3117
3128
|
now.utc.utc? # => true
|
3118
3129
|
</ruby>
|
3119
3130
|
|
3131
|
+
h6(#datetime-advance). +advance+
|
3132
|
+
|
3133
|
+
The most generic way to jump to another datetime is +advance+. This method receives a hash with keys +:years+, +:months+, +:weeks+, +:days+, +:hours+, +:minutes+, and +:seconds+, and returns a datetime advanced as much as the present keys indicate.
|
3134
|
+
|
3135
|
+
<ruby>
|
3136
|
+
d = DateTime.current
|
3137
|
+
# => Thu, 05 Aug 2010 11:33:31 +0000
|
3138
|
+
d.advance(:years => 1, :months => 1, :days => 1, :hours => 1, :minutes => 1, :seconds => 1)
|
3139
|
+
# => Tue, 06 Sep 2011 12:34:32 +0000
|
3140
|
+
</ruby>
|
3141
|
+
|
3142
|
+
This method first computes the destination date passing +:years+, +:months+, +:weeks+, and +:days+ to +Date#advance+ documented above. After that, it adjusts the time calling +since+ with the number of seconds to advance. This order is relevant, a different ordering would give different datetimes in some edge-cases. The example in +Date#advance+ applies, and we can extend it to show order relevance related to the time bits.
|
3143
|
+
|
3144
|
+
If we first move the date bits (that have also a relative order of processing, as documented before), and then the time bits we get for example the following computation:
|
3145
|
+
|
3146
|
+
<ruby>
|
3147
|
+
d = DateTime.new(2010, 2, 28, 23, 59, 59)
|
3148
|
+
# => Sun, 28 Feb 2010 23:59:59 +0000
|
3149
|
+
d.advance(:months => 1, :seconds => 1)
|
3150
|
+
# => Mon, 29 Mar 2010 00:00:00 +0000
|
3151
|
+
</ruby>
|
3152
|
+
|
3153
|
+
but if we computed them the other way around, the result would be different:
|
3154
|
+
|
3155
|
+
<ruby>
|
3156
|
+
d.advance(:seconds => 1).advance(:months => 1)
|
3157
|
+
# => Thu, 01 Apr 2010 00:00:00 +0000
|
3158
|
+
</ruby>
|
3159
|
+
|
3160
|
+
WARNING: Since +DateTime+ is not DST-aware you can end up in a non-existing point in time with no warning or error telling you so.
|
3161
|
+
|
3120
3162
|
h5(#datetime-changing-components). Changing Components
|
3121
3163
|
|
3122
3164
|
The method +change+ allows you to get a new datetime which is the same as the receiver except for the given options, which may include +:year+, +:month+, +:day+, +:hour+, +:min+, +:sec+, +:offset+, +:start+:
|
@@ -3149,15 +3191,144 @@ DateTime.current.change(:month => 2, :day => 30)
|
|
3149
3191
|
# => ArgumentError: invalid date
|
3150
3192
|
</ruby>
|
3151
3193
|
|
3152
|
-
|
3194
|
+
h5. Durations
|
3195
|
+
|
3196
|
+
Durations can be added and substracted to datetimes:
|
3197
|
+
|
3198
|
+
<ruby>
|
3199
|
+
now = DateTime.current
|
3200
|
+
# => Mon, 09 Aug 2010 23:15:17 +0000
|
3201
|
+
now + 1.year
|
3202
|
+
# => Tue, 09 Aug 2011 23:15:17 +0000
|
3203
|
+
now - 1.week
|
3204
|
+
# => Mon, 02 Aug 2010 23:15:17 +0000
|
3205
|
+
</ruby>
|
3206
|
+
|
3207
|
+
They translate to calls to +since+ or +advance+. For example here we get the correct jump in the calendar reform:
|
3208
|
+
|
3209
|
+
<ruby>
|
3210
|
+
DateTime.new(1582, 10, 4, 23) + 1.hour
|
3211
|
+
# => Fri, 15 Oct 1582 00:00:00 +0000
|
3212
|
+
</ruby>
|
3153
3213
|
|
3154
3214
|
h3. Extensions to +Time+
|
3155
3215
|
|
3156
|
-
|
3216
|
+
h4(#time-calculations). Calculations
|
3217
|
+
|
3218
|
+
NOTE: All the following methods are defined in +active_support/core_ext/date_time/calculations.rb+.
|
3219
|
+
|
3220
|
+
Active Support adds to +Time+ many of the methods available for +DateTime+:
|
3221
|
+
|
3222
|
+
<ruby>
|
3223
|
+
past?
|
3224
|
+
today?
|
3225
|
+
future?
|
3226
|
+
yesterday
|
3227
|
+
tomorrow
|
3228
|
+
seconds_since_midnight
|
3229
|
+
change
|
3230
|
+
advance
|
3231
|
+
ago
|
3232
|
+
since (in)
|
3233
|
+
beginning_of_day (midnight, at_midnight, at_beginning_of_day)
|
3234
|
+
end_of_day
|
3235
|
+
beginning_of_week (monday, at_beginning_of_week)
|
3236
|
+
end_on_week (at_end_of_week)
|
3237
|
+
next_week
|
3238
|
+
months_ago
|
3239
|
+
months_since
|
3240
|
+
beginning_of_month (at_beginning_of_month)
|
3241
|
+
end_of_month (at_end_of_month)
|
3242
|
+
prev_month
|
3243
|
+
next_month
|
3244
|
+
beginning_of_quarter (at_beginning_of_quarter)
|
3245
|
+
end_of_quarter (at_end_of_quarter)
|
3246
|
+
beginning_of_year (at_beginning_of_year)
|
3247
|
+
end_of_year (at_end_of_year)
|
3248
|
+
years_ago
|
3249
|
+
years_since
|
3250
|
+
prev_year
|
3251
|
+
next_year
|
3252
|
+
</ruby>
|
3253
|
+
|
3254
|
+
They are analogous. Please refer to their documentation above and take into account the following differences:
|
3255
|
+
|
3256
|
+
* +change+ accepts an additional +:usec+ option.
|
3257
|
+
* +Time+ understands DST, so you get correct DST calculations as in
|
3258
|
+
|
3259
|
+
<ruby>
|
3260
|
+
Time.zone_default
|
3261
|
+
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
|
3262
|
+
|
3263
|
+
# In Barcelona, 2010/03/28 02:00 +0100 becomes 2010/03/28 03:00 +0200 due to DST.
|
3264
|
+
t = Time.local_time(2010, 3, 28, 1, 59, 59)
|
3265
|
+
# => Sun Mar 28 01:59:59 +0100 2010
|
3266
|
+
t.advance(:seconds => 1)
|
3267
|
+
# => Sun Mar 28 03:00:00 +0200 2010
|
3268
|
+
</ruby>
|
3269
|
+
|
3270
|
+
* If +since+ or +ago+ jump to a time that can't be expressed with +Time+ a +DateTime+ object is returned instead.
|
3271
|
+
|
3272
|
+
h4. Time Constructors
|
3273
|
+
|
3274
|
+
Active Support defines +Time.current+ to be +Time.zone.now+ if there's a user time zone defined, with fallback to +Time.now+:
|
3275
|
+
|
3276
|
+
<ruby>
|
3277
|
+
Time.zone_default
|
3278
|
+
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
|
3279
|
+
Time.current
|
3280
|
+
# => Fri, 06 Aug 2010 17:11:58 CEST +02:00
|
3281
|
+
</ruby>
|
3282
|
+
|
3283
|
+
Analogously to +DateTime+, the predicates +past?+, and +future?+ are relative to +Time.current+.
|
3284
|
+
|
3285
|
+
Use the +local_time+ class method to create time objects honoring the user time zone:
|
3286
|
+
|
3287
|
+
<ruby>
|
3288
|
+
Time.zone_default
|
3289
|
+
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
|
3290
|
+
Time.local_time(2010, 8, 15)
|
3291
|
+
# => Sun Aug 15 00:00:00 +0200 2010
|
3292
|
+
</ruby>
|
3293
|
+
|
3294
|
+
The +utc_time+ class method returns a time in UTC:
|
3295
|
+
|
3296
|
+
<ruby>
|
3297
|
+
Time.zone_default
|
3298
|
+
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
|
3299
|
+
Time.utc_time(2010, 8, 15)
|
3300
|
+
# => Sun Aug 15 00:00:00 UTC 2010
|
3301
|
+
</ruby>
|
3302
|
+
|
3303
|
+
Both +local_time+ and +utc_time+ accept up to seven positional arguments: year, month, day, hour, min, sec, usec. Year is mandatory, month and day default to 1, and the rest default to 0.
|
3304
|
+
|
3305
|
+
If the time to be constructed lies beyond the range supported by +Time+ in the runtime platform, usecs are discarded and a +DateTime+ object is returned instead.
|
3306
|
+
|
3307
|
+
h5. Durations
|
3308
|
+
|
3309
|
+
Durations can be added and substracted to time objects:
|
3310
|
+
|
3311
|
+
<ruby>
|
3312
|
+
now = Time.current
|
3313
|
+
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
|
3314
|
+
now + 1.year
|
3315
|
+
# => Tue, 09 Aug 2011 23:21:11 UTC +00:00
|
3316
|
+
now - 1.week
|
3317
|
+
# => Mon, 02 Aug 2010 23:21:11 UTC +00:00
|
3318
|
+
</ruby>
|
3319
|
+
|
3320
|
+
They translate to calls to +since+ or +advance+. For example here we get the correct jump in the calendar reform:
|
3321
|
+
|
3322
|
+
<ruby>
|
3323
|
+
Time.utc_time(1582, 10, 3) + 5.days
|
3324
|
+
# => Mon Oct 18 00:00:00 UTC 1582
|
3325
|
+
</ruby>
|
3157
3326
|
|
3158
3327
|
h3. Extensions to +Process+
|
3159
3328
|
|
3160
|
-
|
3329
|
+
h4. +daemon+
|
3330
|
+
|
3331
|
+
Ruby 1.9 provides +Process.daemon+, and Active Support defines it for previous versions. It accepts the same two arguments, whether it should chdir to the root directory (default, true), and whether it should inherit the standard file descriptors from the parent (default, false).
|
3161
3332
|
|
3162
3333
|
h3. Extensions to +File+
|
3163
3334
|
|
@@ -3233,4 +3404,5 @@ h3. Changelog
|
|
3233
3404
|
|
3234
3405
|
"Lighthouse ticket":https://rails.lighthouseapp.com/projects/16213/tickets/67
|
3235
3406
|
|
3407
|
+
* August 10, 2010: Starts to take shape, added to the index.
|
3236
3408
|
* April 18, 2009: Initial version by "Xavier Noria":credits.html#fxn
|