From ccf9577aee86ce1f766c5e8854e0c285dc38f8ac Mon Sep 17 00:00:00 2001 From: Evgeniy Dolzhenko Date: Fri, 11 Jun 2010 14:15:34 +0400 Subject: Fix a bunch of minor spelling mistakes --- actionmailer/lib/action_mailer/base.rb | 8 ++++---- actionmailer/lib/action_mailer/deprecated_api.rb | 2 +- actionpack/lib/abstract_controller/base.rb | 2 +- .../action_controller/metal/request_forgery_protection.rb | 2 +- actionpack/lib/action_controller/test_case.rb | 4 ++-- actionpack/lib/action_dispatch/http/mime_type.rb | 2 +- actionpack/lib/action_dispatch/http/parameters.rb | 2 +- actionpack/lib/action_dispatch/http/upload.rb | 4 ++-- actionpack/lib/action_dispatch/middleware/stack.rb | 2 +- .../lib/action_dispatch/testing/assertions/selector.rb | 2 +- actionpack/lib/action_dispatch/testing/test_response.rb | 4 ++-- actionpack/lib/action_view/helpers/form_helper.rb | 6 +++--- actionpack/lib/action_view/helpers/form_options_helper.rb | 4 ++-- actionpack/lib/action_view/helpers/form_tag_helper.rb | 2 +- actionpack/lib/action_view/helpers/number_helper.rb | 2 +- actionpack/lib/action_view/helpers/text_helper.rb | 2 +- actionpack/lib/action_view/helpers/translation_helper.rb | 4 ++-- actionpack/lib/action_view/render/layouts.rb | 2 +- activemodel/lib/active_model/attribute_methods.rb | 2 +- activemodel/lib/active_model/errors.rb | 2 +- activemodel/lib/active_model/translation.rb | 2 +- activemodel/lib/active_model/validations.rb | 4 ++-- activemodel/lib/active_model/validations/validates.rb | 2 +- activemodel/lib/active_model/validator.rb | 4 ++-- activerecord/lib/active_record/associations.rb | 10 +++++----- .../active_record/associations/through_association_scope.rb | 2 +- activerecord/lib/active_record/autosave_association.rb | 2 +- activerecord/lib/active_record/base.rb | 2 +- activerecord/lib/active_record/nested_attributes.rb | 2 +- activerecord/lib/active_record/reflection.rb | 8 ++++---- activerecord/lib/active_record/relation.rb | 2 +- activerecord/lib/active_record/schema_dumper.rb | 12 ++++++------ activeresource/lib/active_resource/base.rb | 4 ++-- activesupport/lib/active_support/cache.rb | 2 +- activesupport/lib/active_support/cache/memory_store.rb | 2 +- activesupport/lib/active_support/core_ext/array/grouping.rb | 2 +- activesupport/lib/active_support/core_ext/range/overlaps.rb | 2 +- activesupport/lib/active_support/dependencies.rb | 2 +- activesupport/lib/active_support/multibyte.rb | 2 +- activesupport/lib/active_support/notifications.rb | 2 +- activesupport/lib/active_support/time_with_zone.rb | 2 +- activesupport/lib/active_support/values/time_zone.rb | 2 +- 42 files changed, 67 insertions(+), 67 deletions(-) diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 7da033b6af..f0b2604a66 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -60,21 +60,21 @@ module ActionMailer #:nodoc: # # If you want to explicitly render only certain templates, pass a block: # - # mail(:to => user.emai) do |format| + # mail(:to => user.email) do |format| # format.text # format.html # end # # The block syntax is useful if also need to specify information specific to a part: # - # mail(:to => user.emai) do |format| + # mail(:to => user.email) do |format| # format.text(:content_transfer_encoding => "base64") # format.html # end # # Or even to render a special view: # - # mail(:to => user.emai) do |format| + # mail(:to => user.email) do |format| # format.text # format.html { render "some_other_template" } # end @@ -182,7 +182,7 @@ module ActionMailer #:nodoc: # end # # Which will (if it had both a welcome.text.plain.erb and welcome.text.html.erb - # tempalte in the view directory), send a complete multipart/mixed email with two parts, + # template in the view directory), send a complete multipart/mixed email with two parts, # the first part being a multipart/alternative with the text and HTML email parts inside, # and the second being a application/pdf with a Base64 encoded copy of the file.pdf book # with the filename +free_book.pdf+. diff --git a/actionmailer/lib/action_mailer/deprecated_api.rb b/actionmailer/lib/action_mailer/deprecated_api.rb index c08ab4164e..0070d8e016 100644 --- a/actionmailer/lib/action_mailer/deprecated_api.rb +++ b/actionmailer/lib/action_mailer/deprecated_api.rb @@ -1,7 +1,7 @@ module ActionMailer # This is the API which is deprecated and is going to be removed on Rails 3.1 release. # Part of the old API will be deprecated after 3.1, for a smoother deprecation process. - # Chech those in OldApi instead. + # Check those in OldApi instead. module DeprecatedApi #:nodoc: extend ActiveSupport::Concern diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index e1027840ef..4d7b4019d8 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -26,7 +26,7 @@ module AbstractController super end - # A list of all descendents of AbstractController::Base. This is + # A list of all descendants of AbstractController::Base. This is # useful for initializers which need to add behavior to all controllers. def descendants @descendants ||= [] diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 8c25b147ef..b632e7aab6 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -55,7 +55,7 @@ module ActionController #:nodoc: config_accessor :request_forgery_protection_token self.request_forgery_protection_token ||= :authenticity_token - # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. + # Controls whether request forgery protection is turned on or not. Turned off by default only in test mode. config_accessor :allow_forgery_protection self.allow_forgery_protection = true if allow_forgery_protection.nil? diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 21281b606e..7f9eb2cfd1 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -188,7 +188,7 @@ module ActionController # Superclass for ActionController functional tests. Functional tests allow you to # test a single controller action per test method. This should not be confused with # integration tests (see ActionController::IntegrationTest), which are more like - # "stories" that can involve multiple controllers and mutliple actions (i.e. multiple + # "stories" that can involve multiple controllers and multiple actions (i.e. multiple # different HTTP requests). # # == Basic example @@ -442,7 +442,7 @@ module ActionController end # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline - # (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular + # (skipping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular # rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else # than 0.0.0.0. # diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index d6a805bf3b..c6fc582851 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -60,7 +60,7 @@ module Mime def initialize(order, name, q=nil) @order = order @name = name.strip - q ||= 0.0 if @name == Mime::ALL # default wilcard match to end of list + q ||= 0.0 if @name == Mime::ALL # default wildcard match to end of list @q = ((q || 1.0).to_f * 100).to_i end diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb index bc43414e75..0a37bd7fc1 100644 --- a/actionpack/lib/action_dispatch/http/parameters.rb +++ b/actionpack/lib/action_dispatch/http/parameters.rb @@ -32,7 +32,7 @@ module ActionDispatch end private - # Convert nested Hashs to HashWithIndifferentAccess + # Convert nested Hash to HashWithIndifferentAccess def normalize_parameters(value) case value when Hash diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index 81d2517304..8ee4b81cdd 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -31,8 +31,8 @@ module ActionDispatch end module Upload - # Convert nested Hashs to HashWithIndifferentAccess and replace - # file upload hashs with UploadedFile objects + # Convert nested Hash to HashWithIndifferentAccess and replace + # file upload hash with UploadedFile objects def normalize_parameters(value) if Hash === value && value.has_key?(:tempfile) upload = value[:tempfile] diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 4240e7a5d5..4618f3befc 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -70,7 +70,7 @@ module ActionDispatch end def active - ActiveSupport::Deprecation.warn "All middlewares in the chaing are active since the laziness " << + ActiveSupport::Deprecation.warn "All middlewares in the chain are active since the laziness " << "was removed from the middleware stack", caller end diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index 0e82b41590..b490547da7 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -359,7 +359,7 @@ module ActionDispatch # position. Possible values are :top, :bottom, :before # and :after. # - # Use the argument :redirect follwed by a path to check that an statement + # Use the argument :redirect followed by a path to check that an statement # which redirects to the specified path is generated. # # Using the :remove statement, you will be able to pass a block, but it will diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb index 9a51a32899..44fb1bde99 100644 --- a/actionpack/lib/action_dispatch/testing/test_response.rb +++ b/actionpack/lib/action_dispatch/testing/test_response.rb @@ -53,7 +53,7 @@ module ActionDispatch # Returns the template of the file which was used to # render this response (or nil) def rendered - ActiveSupport::Deprecation.warn("response.rendered has been deprecated. Use tempate.rendered instead", caller) + ActiveSupport::Deprecation.warn("response.rendered has been deprecated. Use template.rendered instead", caller) @template.instance_variable_get(:@_rendered) end @@ -89,7 +89,7 @@ module ActionDispatch # A shortcut to the template.assigns def template_objects - ActiveSupport::Deprecation.warn("response.template_objects has been deprecated. Use tempate.assigns instead", caller) + ActiveSupport::Deprecation.warn("response.template_objects has been deprecated. Use template.assigns instead", caller) @template.assigns || {} end diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index b3db3151d3..9e2448fe97 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -92,7 +92,7 @@ module ActionView # # error handling # end # - # That's how you tipically work with resources. + # That's how you typically work with resources. module FormHelper extend ActiveSupport::Concern @@ -269,7 +269,7 @@ module ActionView # labelling_form. # # The custom FormBuilder class is automatically merged with the options - # of a nested fields_for call, unless it's explicitely set. + # of a nested fields_for call, unless it's explicitly set. # # In many cases you will want to wrap the above in another helper, so you # could do something like the following: @@ -717,7 +717,7 @@ module ActionView # # To prevent this the helper generates an auxiliary hidden field before # the very check box. The hidden field has the same name and its - # attributes mimick an unchecked check box. + # attributes mimic an unchecked check box. # # This way, the client either sends only the hidden field (representing # the check box is unchecked), or both fields. Since the HTML specification diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index fe71d2cdf7..6bf78647ec 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -412,8 +412,8 @@ module ActionView # * +selected_key+ - A value equal to the +value+ attribute for one of the tags, # which will have the +selected+ attribute set. Note: It is possible for this value to match multiple options # as you might have the same option in multiple groups. Each will then get selected="selected". - # * +prompt+ - set to true or a prompt string. When the select element doesn’t have a value yet, this - # prepends an option with a generic prompt — "Please select" — or the given prompt string. + # * +prompt+ - set to true or a prompt string. When the select element doesn't have a value yet, this + # prepends an option with a generic prompt - "Please select" - or the given prompt string. # # Sample usage (Array): # grouped_options = [ diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 796268628a..0727375fc0 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -535,7 +535,7 @@ module ActionView def extra_tags_for_form(html_options) case method = html_options.delete("method").to_s - when /^get$/i # must be case-insentive, but can't use downcase as might be nil + when /^get$/i # must be case-insensitive, but can't use downcase as might be nil html_options["method"] = "get" '' when /^post$/i, "", nil diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index c0b3804860..38e56d8bff 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -325,7 +325,7 @@ module ActionView # number_to_human_size(483989, :precision => 2) # => 470 KB # number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,2 MB # - # Unsignificant zeros after the fractional separator are stripped out by default (set + # Non-significant zeros after the fractional separator are stripped out by default (set # :strip_insignificant_zeros to +false+ to change that): # number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB" # number_to_human_size(524288000, :precision=>5) # => "500 MB" diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index a06073ce66..c8533c217b 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -48,7 +48,7 @@ module ActionView # truncate("Once upon a time in a world far far away", :length => 17) # # => "Once upon a ti..." # - # truncate("Once upon a time in a world far far away", :lenght => 17, :separator => ' ') + # truncate("Once upon a time in a world far far away", :length => 17, :separator => ' ') # # => "Once upon a..." # # truncate("And they found that many people were sleeping better.", :length => 25, :omission => '... (continued)') diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index 0d2b2aa7b1..0c8829b0b8 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -11,8 +11,8 @@ module ActionView # to translate many keys within the same partials and gives you a simple framework for scoping them consistently. If you don't # prepend the key with a period, nothing is converted. # - # Third, it’ll mark the translation as safe HTML if the key has the suffix "_html" or the last element of the key is the word - # "html". For example, calling translate("footer_html") or translate("footer.html") will return a safe HTML string that won’t + # Third, it'll mark the translation as safe HTML if the key has the suffix "_html" or the last element of the key is the word + # "html". For example, calling translate("footer_html") or translate("footer.html") will return a safe HTML string that won't # be escaped by other HTML helper methods. This naming convention helps to identify translations that include HTML tags so that # you know what kind of output to expect when you call translate in a template. diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb index a9dfc0cced..1f837b37e2 100644 --- a/actionpack/lib/action_view/render/layouts.rb +++ b/actionpack/lib/action_view/render/layouts.rb @@ -55,7 +55,7 @@ module ActionView end # This is the method which actually finds the layout using details in the lookup - # context object. If no layout is found, it checkes if at least a layout with + # context object. If no layout is found, it checks if at least a layout with # the given name exists across all details before raising the error. def find_layout(layout) begin diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 9bacc2a511..7d0cdb5251 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -45,7 +45,7 @@ module ActiveModel # end # end # - # Please notice that whenever you include ActiveModel::AtributeMethods in your class, + # Please notice that whenever you include ActiveModel::AttributeMethods in your class, # it requires you to implement a attributes methods which returns a hash with # each attribute name in your model as hash key and the attribute value as hash value. # Hash keys must be a string. diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 15d468f5d8..5c076d9d2f 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -240,7 +240,7 @@ module ActiveModel # default message (e.g. activemodel.errors.messages.MESSAGE). The translated model name, # translated attribute name and the value are available for interpolation. # - # When using inheritence in your models, it will check all the inherited models too, but only if the model itself + # When using inheritance in your models, it will check all the inherited models too, but only if the model itself # hasn't been found. Say you have class Admin < User; end and you wanted the translation for the :blank # error +message+ for the title +attribute+, it looks for these translations: # diff --git a/activemodel/lib/active_model/translation.rb b/activemodel/lib/active_model/translation.rb index 2ab342ffac..15d0c7ddb1 100644 --- a/activemodel/lib/active_model/translation.rb +++ b/activemodel/lib/active_model/translation.rb @@ -11,7 +11,7 @@ module ActiveModel # extend ActiveModel::Translation # end # - # TranslatedPerson.human_attribute_name('my_attribue') + # TranslatedPerson.human_attribute_name('my_attribute') # #=> "My attribute" # # This also provides the required class methods for hooking into the diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index d7e3544849..173891bcda 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -89,7 +89,7 @@ module ActiveModel end # Adds a validation method or block to the class. This is useful when - # overriding the +validate+ instance method becomes too unwieldly and + # overriding the +validate+ instance method becomes too unwieldy and # you're looking for more descriptive declaration of your validations. # # This can be done with a symbol pointing to a method: @@ -172,7 +172,7 @@ module ActiveModel !valid?(context) end - # Hook method defining how an attribute value should be retieved. By default this is assumed + # Hook method defining how an attribute value should be retrieved. By default this is assumed # to be an instance named after the attribute. Override this method in subclasses should you # need to retrieve the value for a given attribute differently e.g. # class MyClass diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 90b244228a..57162996c2 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -20,7 +20,7 @@ module ActiveModel # validates :username, :presence => true # validates :username, :uniqueness => true # - # The power of the +validates+ method comes when using cusom validators + # The power of the +validates+ method comes when using custom validators # and default validators in one call for a given attribute e.g. # # class EmailValidator < ActiveModel::EachValidator diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index 56179c1a6c..114e9091bc 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -106,7 +106,7 @@ module ActiveModel #:nodoc: @kind ||= name.split('::').last.underscore.sub(/_validator$/, '').to_sym unless anonymous? end - # Accepts options that will be made availible through the +options+ reader. + # Accepts options that will be made available through the +options+ reader. def initialize(options) @options = options end @@ -152,7 +152,7 @@ module ActiveModel #:nodoc: end end - # Override this method in subclasses with the validation logic, adding + # Override this method in subclasses with the validation logic, adding # errors to the records +errors+ array where necessary. def validate_each(record, attribute, value) raise NotImplementedError diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index c1e16d08cb..c1d06ff68d 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -88,8 +88,8 @@ module ActiveRecord end end - # This error is raised when trying to destroy a parent instance in a N:1, 1:1 assosications - # (has_many, has_one) when there is at least 1 child assosociated instance. + # This error is raised when trying to destroy a parent instance in a N:1, 1:1 associations + # (has_many, has_one) when there is at least 1 child associated instance. # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project class DeleteRestrictionError < ActiveRecordError #:nodoc: def initialize(reflection) @@ -890,7 +890,7 @@ module ActiveRecord # [:inverse_of] # Specifies the name of the belongs_to association on the associated object that is the inverse of this has_many # association. Does not work in combination with :through or :as options. - # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional assocations for more detail. + # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail. # # Option examples: # has_many :comments, :order => "posted_on" @@ -1005,7 +1005,7 @@ module ActiveRecord # [:inverse_of] # Specifies the name of the belongs_to association on the associated object that is the inverse of this has_one # association. Does not work in combination with :through or :as options. - # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional assocations for more detail. + # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail. # # Option examples: # has_one :credit_card, :dependent => :destroy # destroys the associated credit card @@ -1110,7 +1110,7 @@ module ActiveRecord # [:inverse_of] # Specifies the name of the has_one or has_many association on the associated object that is the inverse of this belongs_to # association. Does not work in combination with the :polymorphic options. - # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional assocations for more detail. + # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail. # # Option examples: # belongs_to :firm, :foreign_key => "client_of" diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 1d2f323112..93bd6e3185 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -91,7 +91,7 @@ module ActiveRecord # Construct attributes for :through pointing to owner and associate. def construct_join_attributes(associate) - # TODO: revist this to allow it for deletion, supposing dependent option is supported + # TODO: revisit this to allow it for deletion, supposing dependent option is supported raise ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(@owner, @reflection) if [:has_one, :has_many].include?(@reflection.source_reflection.macro) join_attributes = construct_owner_attributes(@reflection.through_reflection).merge(@reflection.source_reflection.primary_key_name => associate.id) diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 0dcadfab5f..154d6ba8e5 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -375,7 +375,7 @@ module ActiveRecord if association.updated? association_id = association.send(reflection.options[:primary_key] || :id) self[reflection.primary_key_name] = association_id - # TODO: Removing this code doesn't seem to matter… + # TODO: Removing this code doesn't seem to matter... if reflection.options[:polymorphic] self[reflection.options[:foreign_type]] = association.class.base_class.name.to_s end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 7cff6d9f1a..277ab785da 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1456,7 +1456,7 @@ module ActiveRecord #:nodoc: # For example in the test suite the topic model's after_initialize method sets the author_email_address to # test@test.com. I would have thought this would mean that all cloned models would have an author email address # of test@test.com. However the test_clone test method seems to test that this is not the case. As a result the - # after_initialize callback has to be run *before* the copying of the atrributes rather than afterwards in order + # after_initialize callback has to be run *before* the copying of the attributes rather than afterwards in order # for all tests to pass. This makes no sense to me. callback(:after_initialize) if respond_to_without_attributes?(:after_initialize) cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index eb9e792dd8..767ec85432 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -278,7 +278,7 @@ module ActiveRecord # Assigns the given attributes to the association. # # If update_only is false and the given attributes include an :id - # that matches the existing record’s id, then the existing record will be + # that matches the existing record's id, then the existing record will be # modified. If update_only is true, a new record is only created when no # object exists. Otherwise a new record will be built. # diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 0e48e229b3..d4af3d7d15 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -165,14 +165,14 @@ module ActiveRecord klass.new(*options) end - # Creates a new instance of the associated class, and immediates saves it + # Creates a new instance of the associated class, and immediately saves it # with ActiveRecord::Base#save. +options+ will be passed to the class's # creation method. Returns the newly created object. def create_association(*options) klass.create(*options) end - # Creates a new instance of the associated class, and immediates saves it + # Creates a new instance of the associated class, and immediately saves it # with ActiveRecord::Base#save!. +options+ will be passed to the class's # creation method. If the created record doesn't pass validations, then an # exception will be raised. @@ -267,10 +267,10 @@ module ActiveRecord # Returns whether or not the association should be validated as part of # the parent's validation. # - # Unless you explicitely disable validation with + # Unless you explicitly disable validation with # :validate => false, it will take place when: # - # * you explicitely enable validation; :validate => true + # * you explicitly enable validation; :validate => true # * you use autosave; :autosave => true # * the association is a +has_many+ association def validate? diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 99c914d7fc..5d99a15eda 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -67,7 +67,7 @@ module ActiveRecord preload += @includes_values unless eager_loading? preload.each {|associations| @klass.send(:preload_associations, @records, associations) } - # @readonly_value is true only if set explicity. @implicit_readonly is true if there are JOINS and no explicit SELECT. + # @readonly_value is true only if set explicitly. @implicit_readonly is true if there are JOINS and no explicit SELECT. readonly = @readonly_value.nil? ? @implicit_readonly : @readonly_value @records.each { |record| record.readonly! } if readonly diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index cd54653581..71ef249ee1 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -173,15 +173,15 @@ HEADER def indexes(table, stream) if (indexes = @connection.indexes(table)).any? add_index_statements = indexes.map do |index| - statment_parts = [ ('add_index ' + index.table.inspect) ] - statment_parts << index.columns.inspect - statment_parts << (':name => ' + index.name.inspect) - statment_parts << ':unique => true' if index.unique + statement_parts = [ ('add_index ' + index.table.inspect) ] + statement_parts << index.columns.inspect + statement_parts << (':name => ' + index.name.inspect) + statement_parts << ':unique => true' if index.unique index_lengths = index.lengths.compact if index.lengths.is_a?(Array) - statment_parts << (':length => ' + Hash[*index.columns.zip(index.lengths).flatten].inspect) if index_lengths.present? + statement_parts << (':length => ' + Hash[*index.columns.zip(index.lengths).flatten].inspect) if index_lengths.present? - ' ' + statment_parts.join(', ') + ' ' + statement_parts.join(', ') end stream.puts add_index_statements.sort.join("\n") diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index b89097ac4b..e3728c83eb 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -763,7 +763,7 @@ module ActiveResource # With any other scope, find returns nil when no data is returned. # # Person.find(1) - # # => raises ResourcenotFound + # # => raises ResourceNotFound # # Person.find(:all) # Person.find(:first) @@ -941,7 +941,7 @@ module ActiveResource end # This is a list of known attributes for this resource. Either - # gathered fromthe provided schema, or from the attributes + # gathered from the provided schema, or from the attributes # set on this instance after it has been fetched from the remote system. def known_attributes self.class.known_attributes + self.attributes.keys.map(&:to_s) diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 2605a3f2b8..f04544c0c5 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -22,7 +22,7 @@ module ActiveSupport EMPTY_OPTIONS = {}.freeze # These options mean something to all cache implementations. Individual cache - # implementations may support additional optons. + # implementations may support additional options. UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl] module Strategy diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb index b1d14a0d8f..f5c2b8af8b 100644 --- a/activesupport/lib/active_support/cache/memory_store.rb +++ b/activesupport/lib/active_support/cache/memory_store.rb @@ -10,7 +10,7 @@ module ActiveSupport # appropriate cache for you. # # This cache has a bounded size specified by the :size options to the - # initializer (default is 32Mb). When the cache exceeds the alotted size, + # initializer (default is 32Mb). When the cache exceeds the allotted size, # a cleanup will occur which tries to prune the cache down to three quarters # of the maximum size by removing the least recently used entries. # diff --git a/activesupport/lib/active_support/core_ext/array/grouping.rb b/activesupport/lib/active_support/core_ext/array/grouping.rb index ef416787a9..4cd9bfadac 100644 --- a/activesupport/lib/active_support/core_ext/array/grouping.rb +++ b/activesupport/lib/active_support/core_ext/array/grouping.rb @@ -55,7 +55,7 @@ class Array # ["6", "7"] def in_groups(number, fill_with = nil) # size / number gives minor group size; - # size % number gives how many objects need extra accomodation; + # size % number gives how many objects need extra accommodation; # each group hold either division or division + 1 items. division = size / number modulo = size % number diff --git a/activesupport/lib/active_support/core_ext/range/overlaps.rb b/activesupport/lib/active_support/core_ext/range/overlaps.rb index 0dec6e0ac4..7df653b53f 100644 --- a/activesupport/lib/active_support/core_ext/range/overlaps.rb +++ b/activesupport/lib/active_support/core_ext/range/overlaps.rb @@ -1,5 +1,5 @@ class Range - # Compare two ranges and see if they overlap eachother + # Compare two ranges and see if they overlap each other # (1..5).overlaps?(4..6) # => true # (1..5).overlaps?(7..9) # => false def overlaps?(other) diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 16c3bc1142..d48da11bf3 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -340,7 +340,7 @@ module ActiveSupport #:nodoc: if Module.method(:const_defined?).arity == 1 # Does this module define this constant? - # Wrapper to accomodate changing Module#const_defined? in Ruby 1.9 + # Wrapper to accommodate changing Module#const_defined? in Ruby 1.9 def local_const_defined?(mod, const) mod.const_defined?(const) end diff --git a/activesupport/lib/active_support/multibyte.rb b/activesupport/lib/active_support/multibyte.rb index e7a271a660..8ffdf5a1bf 100644 --- a/activesupport/lib/active_support/multibyte.rb +++ b/activesupport/lib/active_support/multibyte.rb @@ -17,7 +17,7 @@ module ActiveSupport #:nodoc: @proxy_class = klass end - # Returns the currect proxy class + # Returns the current proxy class def self.proxy_class @proxy_class ||= ActiveSupport::Multibyte::Chars end diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 3f1fe64e9b..1aec7ea60f 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -23,7 +23,7 @@ module ActiveSupport # # event = @events.first # event.name #=> :render - # event.duration #=> 10 (in miliseconds) + # event.duration #=> 10 (in milliseconds) # event.result #=> "Foo" # event.payload #=> { :extra => :information } # diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 710dce78de..62d02bdeb6 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -18,7 +18,7 @@ module ActiveSupport # # See Time and TimeZone for further documentation of these methods. # - # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangable. Examples: + # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangeable. Examples: # # t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00 # t.hour # => 13 diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 67b37785f5..7550d8909f 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -224,7 +224,7 @@ module ActiveSupport utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon) end - # Compare this time zone to the parameter. The two are comapred first on + # Compare this time zone to the parameter. The two are compared first on # their offsets, and then by name. def <=>(zone) result = (utc_offset <=> zone.utc_offset) -- cgit v1.2.3 From ed507300f05fa5e86f7f7d8988f2d25a91b37b8b Mon Sep 17 00:00:00 2001 From: Evgeniy Dolzhenko Date: Fri, 11 Jun 2010 14:20:30 +0400 Subject: Fix minor mistake in activemodel/README --- activemodel/README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/activemodel/README b/activemodel/README index 3945a6da06..6f162ef408 100644 --- a/activemodel/README +++ b/activemodel/README @@ -177,7 +177,8 @@ functionality from the following modules: end - person = Person.new(:first_name => 'zoolander') + person = Person.new + person.first_name = 'zoolander' person.valid? #=> false {Learn more}[link:classes/ActiveModel/Validations.html] -- cgit v1.2.3 From ef2798f018d98dce28566a1679b7b85cd6acf75e Mon Sep 17 00:00:00 2001 From: rspeicher Date: Mon, 14 Jun 2010 18:11:35 -0400 Subject: Active Record Basics - Style and grammar edits - "i.e." should be "e.g." in these cases, and include the comma - Newline consistency before/after Ruby blocks - Conform to the apparent guide standard of "Active Record" over "ActiveRecord" --- .../guides/source/active_record_basics.textile | 38 ++++++++++++---------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/railties/guides/source/active_record_basics.textile b/railties/guides/source/active_record_basics.textile index d81e461e63..57477b44c5 100644 --- a/railties/guides/source/active_record_basics.textile +++ b/railties/guides/source/active_record_basics.textile @@ -32,16 +32,16 @@ Active Record gives us several mechanisms, the most important being the ability * Validate models before they get persisted to the database * Perform database operations in an object-oriented fashion. -h3. Convention over Configuration in ActiveRecord +h3. Convention over Configuration in Active Record -When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating ActiveRecord models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason. +When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating Active Record models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason. h4. Naming Conventions -By default, ActiveRecord uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class +Book+, you should have a database table called *books*. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples: +By default, Active Record uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class +Book+, you should have a database table called *books*. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples: -* Database Table - Plural with underscores separating words i.e. (book_clubs) -* Model Class - Singular with the first letter of each word capitalized i.e. (BookClub) +* Database Table - Plural with underscores separating words (e.g., book_clubs) +* Model Class - Singular with the first letter of each word capitalized (e.g., BookClub) |_.Model / Class |_.Table / Schema | |Post |posts| @@ -53,12 +53,12 @@ By default, ActiveRecord uses some naming conventions to find out how the mappin h4. Schema Conventions -ActiveRecord uses naming conventions for the columns in database tables, depending on the purpose of these columns. +Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns. -* *Foreign keys* - These fields should be named following the pattern table_id i.e. (item_id, order_id). These are the fields that ActiveRecord will look for when you create associations between your models. -* *Primary keys* - By default, ActiveRecord will use an integer column named "id" as the table's primary key. When using "Rails Migrations":migrations.html to create your tables, this column will be automatically created. +* *Foreign keys* - These fields should be named following the pattern table_id (e.g., item_id, order_id). These are the fields that Active Record will look for when you create associations between your models. +* *Primary keys* - By default, Active Record will use an integer column named "id" as the table's primary key. When using "Rails Migrations":migrations.html to create your tables, this column will be automatically created. -There are also some optional column names that will create additional features to ActiveRecord instances: +There are also some optional column names that will create additional features to Active Record instances: * *created_at / created_on* - ActiveRecord will store the current date and time to this field when creating the record. * *updated_at / updated_on* - ActiveRecord will store the current date and times to this field when updating the record. @@ -66,17 +66,17 @@ There are also some optional column names that will create additional features t * *type* - Specifies that the model uses "Single Table Inheritance":http://api.rubyonrails.com/classes/ActiveRecord/Base.html * *(table_name)_count* - Used to cache the number of belonging objects on associations. For example, a +comments_count+ column in a +Post+ class that has many instances of +Comment+ will cache the number of existent comments for each post. -NOTE: While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling. +NOTE: While these column names are optional they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling. -h3. Creating ActiveRecord Models +h3. Creating Active Record Models -It's very easy to create ActiveRecord models. All you have to do is to subclass the ActiveRecord::Base class and you're good to go: +It's very easy to create Active Record models. All you have to do is to subclass the +ActiveRecord::Base+ class and you're good to go: class Product < ActiveRecord::Base; end -This will create a +Product+ model, mapped to a *products* table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the *products* table was created using a SQL sentence like: +This will create a +Product+ model, mapped to a *products* table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the *products* table was created using an SQL sentence like: CREATE TABLE products ( @@ -99,12 +99,15 @@ h3. Overriding the Naming Conventions What if you need to follow a different naming convention or need to use your Rails application with a legacy database? No problem, you can easily override the default conventions. You can use the +ActiveRecord::Base.set_table_name+ method to specify the table name that should be used: + class Product < ActiveRecord::Base set_table_name "PRODUCT" end + If you do so, you will have to define manually the class name that is hosting the fixtures (class_name.yml) using the +set_fixture_class+ method in your test definition: + class FunnyJoke < ActiveSupport::TestCase set_fixture_class :funny_jokes => 'Joke' @@ -113,7 +116,8 @@ class FunnyJoke < ActiveSupport::TestCase end -It's also possible to override the column that should be used as the table's primary key. Use the +ActiveRecord::Base.set_primary_key+ method for that: +It's also possible to override the column that should be used as the table's primary key using the +ActiveRecord::Base.set_primary_key+ method: + class Product < ActiveRecord::Base set_primary_key "product_id" @@ -122,7 +126,7 @@ end h3. Reading and Writing Data -CRUD is an acronym for the four verbs we use to operate on data: Create, Read, Update, Delete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables. +CRUD is an acronym for the four verbs we use to operate on data: *C*reate, *R*ead, *U*pdate and *D*elete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables. h4. Create @@ -155,7 +159,7 @@ Finally, passing a block to either create or new will return a new User object: h4. Read -ActiveRecord provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by ActiveRecord. +Active Record provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by Active Record. # return all records @@ -163,7 +167,7 @@ ActiveRecord provides a rich API for accessing data within a database. Below are - # return first record + # return the first record user = User.first -- cgit v1.2.3 From 6f0eb4a0984631b47f4802b29d7c611228f45b5a Mon Sep 17 00:00:00 2001 From: rspeicher Date: Mon, 14 Jun 2010 18:19:01 -0400 Subject: Active Record Basics - Separate and clarify the explanations for created_at/on and updated_at/on --- railties/guides/source/active_record_basics.textile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/active_record_basics.textile b/railties/guides/source/active_record_basics.textile index 57477b44c5..e32898129f 100644 --- a/railties/guides/source/active_record_basics.textile +++ b/railties/guides/source/active_record_basics.textile @@ -60,8 +60,10 @@ Active Record uses naming conventions for the columns in database tables, depend There are also some optional column names that will create additional features to Active Record instances: -* *created_at / created_on* - ActiveRecord will store the current date and time to this field when creating the record. -* *updated_at / updated_on* - ActiveRecord will store the current date and times to this field when updating the record. +* *created_at* - Automatically gets set to the current date and time when the record is first created. +* *created_on* - Automatically gets set to the current date when the record is first created. +* *updated_at* - Automatically gets set to the current date and time whenever the record is updated. +* *updated_on* - Automatically gets set to the current date whenever the record is updated. * *lock_version* - Adds "optimistic locking":http://api.rubyonrails.com/classes/ActiveRecord/Locking.html to a model. * *type* - Specifies that the model uses "Single Table Inheritance":http://api.rubyonrails.com/classes/ActiveRecord/Base.html * *(table_name)_count* - Used to cache the number of belonging objects on associations. For example, a +comments_count+ column in a +Post+ class that has many instances of +Comment+ will cache the number of existent comments for each post. -- cgit v1.2.3 From 1a50cc31639f35fd82a4a24821b9fc49dc7eadc9 Mon Sep 17 00:00:00 2001 From: rspeicher Date: Mon, 14 Jun 2010 18:46:30 -0400 Subject: Routing guide - Minor typo/consistency changes --- railties/guides/source/routing.textile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 54af42a03f..3f6bb66ee5 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -32,7 +32,7 @@ the request is dispatched to the +patients+ controller's +show+ action with h4. Generating URLs from Code -You can also generate routes. If your application contains this code: +You can also generate URLs. If your application contains this code: @patient = Patient.find(17) @@ -308,7 +308,7 @@ You are not limited to the seven routes that RESTful routing creates by default. h5. Adding Member Routes -To add a member route, just add +member+ block into resource block: +To add a member route, just add a +member+ block into the resource block: resources :photos do @@ -318,9 +318,9 @@ resources :photos do end -This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers. +This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers. -Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ routes, you can also passing +:on+ to a route. +Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ routes, you can also pass +:on+ to a route, eliminating the block: resources :photos do @@ -340,9 +340,9 @@ resources :photos do end -This will enable Rails to recognize URLs such as +/photos/search+ with GET, and route to the +search+ action of +PhotosController+. It will also create the +search_photos_url+ and +search_photos_path+ route helpers. +This will enable Rails to recognize URLs such as +/photos/search+ with GET, and route to the +search+ action of +PhotosController+. It will also create the +search_photos_url+ and +search_photos_path+ route helpers. -Just as with member routes, you can pass +:on+ to a route. +Just as with member routes, you can pass +:on+ to a route: resources :photos do @@ -384,7 +384,7 @@ An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of h4. Static Segments -You can specify static segments when creating a route. +You can specify static segments when creating a route: match ':controller/:action/:id/with_user/:user_id' @@ -575,7 +575,7 @@ resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/} This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, the router would no longer match +/photos/1+ to this route. Instead, +/photos/RR27+ would match. -You can specify a single constraint to a apply to a number of routes by using the block form: +You can specify a single constraint to apply to a number of routes by using the block form: constraints(:id => /[A-Z][A-Z][0-9]+/) do -- cgit v1.2.3 From 51a9703b1e80caa30d699f30615f023079874623 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 15 Jun 2010 00:46:35 -0400 Subject: removing the extra \ --- activerecord/lib/active_record/associations/association_proxy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index e88618d278..ee7dffab22 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -41,7 +41,7 @@ module ActiveRecord # though the object behind blog.posts is not an Array, but an # ActiveRecord::Associations::HasManyAssociation. # - # The @target object is not \loaded until needed. For example, + # The @target object is not loaded until needed. For example, # # blog.posts.count # -- cgit v1.2.3 From 3cc2d196c03fbc5cf21babf777dfa841f3d1012d Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 15 Jun 2010 00:48:22 -0400 Subject: Revert "removing the extra \" This reverts commit 51a9703b1e80caa30d699f30615f023079874623. --- activerecord/lib/active_record/associations/association_proxy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index ee7dffab22..e88618d278 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -41,7 +41,7 @@ module ActiveRecord # though the object behind blog.posts is not an Array, but an # ActiveRecord::Associations::HasManyAssociation. # - # The @target object is not loaded until needed. For example, + # The @target object is not \loaded until needed. For example, # # blog.posts.count # -- cgit v1.2.3 From 538b7b97bb64f56a9d8c62f280106f3916080f6d Mon Sep 17 00:00:00 2001 From: Bryan Woods Date: Tue, 15 Jun 2010 12:36:21 -0400 Subject: Active Record Associations - minor change of DeleteRestrictionError doc for clarity --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 680893a048..185e298f5c 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -88,7 +88,7 @@ module ActiveRecord end end - # This error is raised when trying to destroy a parent instance in a N:1, 1:1 associations + # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations # (has_many, has_one) when there is at least 1 child associated instance. # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project class DeleteRestrictionError < ActiveRecordError #:nodoc: -- cgit v1.2.3 From 89b96c03132156f0d08b2a65d330e50cfbe94910 Mon Sep 17 00:00:00 2001 From: Bryan Woods Date: Tue, 15 Jun 2010 13:38:22 -0400 Subject: Active Model lint - fix minor typos --- activemodel/lib/active_model/lint.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb index a5977bf3cc..fe650053d9 100644 --- a/activemodel/lib/active_model/lint.rb +++ b/activemodel/lib/active_model/lint.rb @@ -56,7 +56,7 @@ module ActiveModel # Returns a boolean that specifies whether the object has been persisted yet. # This is used when calculating the URL for an object. If the object is # not persisted, a form for that object, for instance, will be POSTed to the - # collection. If it is persisted, a form for the object will put PUTed to the + # collection. If it is persisted, a form for the object will be PUT to the # URL for the object. def test_persisted? assert model.respond_to?(:persisted?), "The model should respond to persisted?" @@ -65,7 +65,7 @@ module ActiveModel # == Naming # - # Model.model_name must returns a string with some convenience methods as + # Model.model_name must return a string with some convenience methods as # :human and :partial_path. Check ActiveModel::Naming for more information. # def test_model_naming -- cgit v1.2.3 From 6907bfe1ab9ab9397da51017eee62848a970e443 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 22:13:30 +0430 Subject: Minor doc changes to active_model/validations/acceptance.rb --- .../lib/active_model/validations/acceptance.rb | 45 ++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index 26b12b504b..77c401e0cc 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model Acceptance Validator module Validations class AcceptanceValidator < EachValidator def initialize(options) @@ -22,29 +24,42 @@ module ActiveModel end module HelperMethods - # Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example: + # Encapsulates the pattern of wanting to validate the acceptance of a + # terms of service check box (or similar agreement). Example: # # class Person < ActiveRecord::Base # validates_acceptance_of :terms_of_service # validates_acceptance_of :eula, :message => "must be abided" # end # - # If the database column does not exist, the +terms_of_service+ attribute is entirely virtual. This check is - # performed only if +terms_of_service+ is not +nil+ and by default on save. + # If the database column does not exist, the +terms_of_service+ attribute + # is entirely virtual. This check is performed only if +terms_of_service+ + # is not +nil+ and by default on save. # # Configuration options: - # * :message - A custom error message (default is: "must be accepted"). - # * :on - Specifies when this validation is active (default is :save, other options :create, :update). - # * :allow_nil - Skip validation if attribute is +nil+ (default is true). - # * :accept - Specifies value that is considered accepted. The default value is a string "1", which - # makes it easy to relate to an HTML checkbox. This should be set to +true+ if you are validating a database - # column, since the attribute is typecast from "1" to +true+ before validation. - # * :if - Specifies a method, proc or string to call to determine if the validation should - # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The - # method, proc or string should return or evaluate to a true or false value. - # * :unless - Specifies a method, proc or string to call to determine if the validation should - # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The - # method, proc or string should return or evaluate to a true or false value. + # * :message - A custom error message (default is: "must be + # accepted"). + # * :on - Specifies when this validation is active (default is + # :save, other options are :create and + # :update). + # * :allow_nil - Skip validation if attribute is +nil+ (default + # is true). + # * :accept - Specifies value that is considered accepted. + # The default value is a string "1", which makes it easy to relate to + # an HTML checkbox. This should be set to +true+ if you are validating + # a database column, since the attribute is typecast from "1" to +true+ + # before validation. + # * :if - Specifies a method, proc or string to call to determine + # if the validation should occur (e.g. :if => :allow_validation, + # or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false + # value. + # * :unless - Specifies a method, proc or string to call to + # determine if the validation should not occur (for example, + # :unless => :skip_validation, or + # :unless => Proc.new { |user| user.signup_step <= 2 }). + # The method, proc or string should return or evaluate to a true or + # false value. def validates_acceptance_of(*attr_names) validates_with AcceptanceValidator, _merge_attributes(attr_names) end -- cgit v1.2.3 From d896d8fa2085c4aea29318c97974d45626902166 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 22:17:06 +0430 Subject: Minor doc changes to active_model/validations/confirmation.rb --- .../lib/active_model/validations/confirmation.rb | 40 +++++++++++++++------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 51445343f2..5e13db7491 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model Confirmation Validator module Validations class ConfirmationValidator < EachValidator def validate_each(record, attribute, value) @@ -13,33 +15,45 @@ module ActiveModel end module HelperMethods - # Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example: + # Encapsulates the pattern of wanting to validate a password or email + # address field with a confirmation. For example: # # Model: # class Person < ActiveRecord::Base # validates_confirmation_of :user_name, :password - # validates_confirmation_of :email_address, :message => "should match confirmation" + # validates_confirmation_of :email_address, + # :message => "should match confirmation" # end # # View: # <%= password_field "person", "password" %> # <%= password_field "person", "password_confirmation" %> # - # The added +password_confirmation+ attribute is virtual; it exists only as an in-memory attribute for validating the password. - # To achieve this, the validation adds accessors to the model for the confirmation attribute. NOTE: This check is performed - # only if +password_confirmation+ is not +nil+, and by default only on save. To require confirmation, make sure to add a presence - # check for the confirmation attribute: + # The added +password_confirmation+ attribute is virtual; it exists only + # as an in-memory attribute for validating the password. To achieve this, + # the validation adds accessors to the model for the confirmation + # attribute. + # + # NOTE: This check is performed only if +password_confirmation+ is not + # +nil+, and by default only on save. To require confirmation, make sure + # to add a presence check for the confirmation attribute: # # validates_presence_of :password_confirmation, :if => :password_changed? # # Configuration options: - # * :message - A custom error message (default is: "doesn't match confirmation"). - # * :on - Specifies when this validation is active (default is :save, other options :create, :update). - # * :if - Specifies a method, proc or string to call to determine if the validation should - # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The - # method, proc or string should return or evaluate to a true or false value. - # * :unless - Specifies a method, proc or string to call to determine if the validation should - # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # * :message - A custom error message (default is: "doesn't match + # confirmation"). + # * :on - Specifies when this validation is active (default is + # :save, other options :create, :update). + # * :if - Specifies a method, proc or string to call to determine + # if the validation should occur (e.g. :if => :allow_validation, + # or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false + # value. + # * :unless - Specifies a method, proc or string to call to + # determine if the validation should not occur (e.g. + # :unless => :skip_validation, or + # :unless => Proc.new { |user| user.signup_step <= 2 }). The # method, proc or string should return or evaluate to a true or false value. def validates_confirmation_of(*attr_names) validates_with ConfirmationValidator, _merge_attributes(attr_names) -- cgit v1.2.3 From 3ae67fbebb96b7e5bf806680642345c86952959d Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 22:20:19 +0430 Subject: Add titles to the rest of the files in active_model/validations/* --- activemodel/lib/active_model/validations/exclusion.rb | 2 ++ activemodel/lib/active_model/validations/format.rb | 2 ++ activemodel/lib/active_model/validations/inclusion.rb | 2 ++ activemodel/lib/active_model/validations/length.rb | 2 ++ activemodel/lib/active_model/validations/numericality.rb | 2 ++ activemodel/lib/active_model/validations/presence.rb | 2 ++ activemodel/lib/active_model/validations/validates.rb | 2 ++ activemodel/lib/active_model/validations/with.rb | 2 ++ 8 files changed, 16 insertions(+) diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index 2ee78f5dd2..599623368f 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model Exclusion Validator module Validations class ExclusionValidator < EachValidator def check_validity! diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index c34c860d4d..3b57d4fd77 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model Format Validator module Validations class FormatValidator < EachValidator def validate_each(record, attribute, value) diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 446646d247..e9940dbbf0 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model Inclusion Validator module Validations class InclusionValidator < EachValidator def check_validity! diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index d7218f4f52..dc191d3150 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model Length Validator module Validations class LengthValidator < EachValidator MESSAGES = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }.freeze diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 062b4cd17f..c2e7223939 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model Numericality Validator module Validations class NumericalityValidator < EachValidator CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=, diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index b319f4834b..e36bee8115 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -1,6 +1,8 @@ require 'active_support/core_ext/object/blank' module ActiveModel + + # == Active Model Presence Validator module Validations class PresenceValidator < EachValidator def validate(record) diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 57162996c2..0674640925 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -1,6 +1,8 @@ require 'active_support/core_ext/hash/slice' module ActiveModel + + # == Active Model validates method module Validations module ClassMethods # This method is a shortcut to all default validators and any custom diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 6dbde5bfad..a2e870d714 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -1,4 +1,6 @@ module ActiveModel + + # == Active Model validates_with method module Validations module HelperMethods private -- cgit v1.2.3 From 4ad6103c4f42c2dd2d2cad9b6f515737e9bf9de3 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 22:41:41 +0430 Subject: Adds title and basic description where needed. --- activerecord/lib/active_record/aggregations.rb | 1 + activerecord/lib/active_record/attribute_methods.rb | 1 + activerecord/lib/active_record/autosave_association.rb | 2 ++ activerecord/lib/active_record/base.rb | 2 ++ activerecord/lib/active_record/callbacks.rb | 2 ++ activerecord/lib/active_record/counter_cache.rb | 1 + activerecord/lib/active_record/dynamic_finder_match.rb | 4 ++++ 7 files changed, 13 insertions(+) diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb index 45aaea062d..51ffc7542c 100644 --- a/activerecord/lib/active_record/aggregations.rb +++ b/activerecord/lib/active_record/aggregations.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Aggregations module Aggregations # :nodoc: extend ActiveSupport::Concern diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index c117271c71..56e18eced0 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/enumerable' module ActiveRecord + # = Active Record Attribute Methods module AttributeMethods #:nodoc: extend ActiveSupport::Concern include ActiveModel::AttributeMethods diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 154d6ba8e5..c378e19864 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -1,6 +1,8 @@ require 'active_support/core_ext/array/wrap' module ActiveRecord + # = Active Record Autosave Association + # # AutosaveAssociation is a module that takes care of automatically saving # your associations when the parent is saved. In addition to saving, it # also destroys any associations that were marked for destruction. diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index ce7259e96b..93249fc96c 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -21,6 +21,8 @@ require 'arel' require 'active_record/errors' module ActiveRecord #:nodoc: + # = Active Record + # # Active Record objects don't specify their attributes directly, but rather infer them from the table definition with # which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change # is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 44fee12001..7b7de0b070 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -1,6 +1,8 @@ require 'active_support/core_ext/array/wrap' module ActiveRecord + # = Active Record Callbacks + # # Callbacks are hooks into the lifecycle of an Active Record object that allow you to trigger logic # before or after an alteration of the object state. This can be used to make sure that associated and # dependent objects are deleted when +destroy+ is called (by overwriting +before_destroy+) or to massage attributes diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index 9601ed6afd..999322129a 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Counter Cache module CounterCache # Resets one or more counter caches to their correct value using an SQL # count query. This is useful when adding new counter caches, or if the diff --git a/activerecord/lib/active_record/dynamic_finder_match.rb b/activerecord/lib/active_record/dynamic_finder_match.rb index fa7a19487c..0b66bea391 100644 --- a/activerecord/lib/active_record/dynamic_finder_match.rb +++ b/activerecord/lib/active_record/dynamic_finder_match.rb @@ -1,4 +1,8 @@ module ActiveRecord + # = Active Record Dynamic Finder Match + # + # Provides dynamic attribute-based finders such as find_by_country if, for + # example, the Person has an attribute with that name. class DynamicFinderMatch def self.match(method) df_match = self.new(method) -- cgit v1.2.3 From de65c82bfa4fc41954750572e644fdf37bacb31e Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 22:48:10 +0430 Subject: Changes call backs to callbacks. --- actionmailer/lib/action_mailer/base.rb | 2 +- activemodel/lib/active_model/callbacks.rb | 16 ++++++++-------- activemodel/lib/active_model/dirty.rb | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index fff44e50c1..44c7382f72 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -395,7 +395,7 @@ module ActionMailer #:nodoc: end # Wraps an email delivery inside of Active Support Notifications instrumentation. This - # method is actually called by the Mail::Message object itself through a call back + # method is actually called by the Mail::Message object itself through a callback # when you call :deliver on the Mail::Message, calling +deliver_mail+ directly # and passing a Mail::Message will do nothing except tell the logger you sent the email. def deliver_mail(mail) #:nodoc: diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb index 257644b3fa..e7aad17021 100644 --- a/activemodel/lib/active_model/callbacks.rb +++ b/activemodel/lib/active_model/callbacks.rb @@ -2,11 +2,11 @@ require 'active_support/core_ext/array/wrap' require 'active_support/callbacks' module ActiveModel - # == Active Model Call Backs + # == Active Model Callbacks # # Provides an interface for any class to have Active Record like callbacks. # - # Like the Active Record methods, the call back chain is aborted as soon as + # Like the Active Record methods, the callback chain is aborted as soon as # one of the methods in the chain returns false. # # First, extend ActiveModel::Callbacks from the class you are creating: @@ -15,13 +15,13 @@ module ActiveModel # extend ActiveModel::Callbacks # end # - # Then define a list of methods that you want call backs attached to: + # Then define a list of methods that you want callbacks attached to: # # define_model_callbacks :create, :update # # This will provide all three standard callbacks (before, around and after) around # both the :create and :update methods. To implement, you need to wrap the methods - # you want call backs on in a block so that the call backs get a chance to fire: + # you want callbacks on in a block so that the callbacks get a chance to fire: # # def create # _run_create_callbacks do @@ -61,7 +61,7 @@ module ActiveModel # # define_model_callbacks :initializer, :only => :after # - # Note, the :only => hash will apply to all call backs defined on + # Note, the :only => hash will apply to all callbacks defined on # that method call. To get around this you can call the define_model_callbacks # method as many times as you need. # @@ -72,8 +72,8 @@ module ActiveModel # Would create +after_create+, +before_update+ and +around_destroy+ methods only. # # You can pass in a class to before_, after_ and around_, in which - # case the call back will call that class's _ method passing the object - # that the call back is being called on. + # case the callback will call that class's _ method passing the object + # that the callback is being called on. # # class MyModel # extend ActiveModel::Callbacks @@ -84,7 +84,7 @@ module ActiveModel # # class AnotherClass # def self.before_create( obj ) - # # obj is the MyModel instance that the call back is being called on + # # obj is the MyModel instance that the callback is being called on # end # end # diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index a82ce1bee0..4c80863e3a 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -4,7 +4,7 @@ require 'active_support/hash_with_indifferent_access' require 'active_support/core_ext/object/duplicable' module ActiveModel - # == Active Model Call Backs + # == Active Model Dirty # # Provides a way to track changes in your object in the same way as # Active Record does. -- cgit v1.2.3 From c7f78b184df5cdeee301af06472f7f14465ed7e4 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 23:02:51 +0430 Subject: Added description and title to Dynamic Scope Match --- activerecord/lib/active_record/dynamic_scope_match.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/activerecord/lib/active_record/dynamic_scope_match.rb b/activerecord/lib/active_record/dynamic_scope_match.rb index f796ba669a..15f65be6bc 100644 --- a/activerecord/lib/active_record/dynamic_scope_match.rb +++ b/activerecord/lib/active_record/dynamic_scope_match.rb @@ -1,4 +1,11 @@ module ActiveRecord + + # = Active Record Dynamic Scope Match + # + # Provides dynamic attribute-based scopes such as scoped_by_price(4.99) + # if, for example, the Product has an attribute with that name. You can + # chain more scoped_by_* methods after the other. It acts like a named + # scope except that it's dynamic. class DynamicScopeMatch def self.match(method) ds_match = self.new(method) -- cgit v1.2.3 From cef442f92c409db6aec8ec313f46eeaf93d9b733 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 23:03:54 +0430 Subject: Added typewriter tag to code. --- activerecord/lib/active_record/dynamic_finder_match.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/dynamic_finder_match.rb b/activerecord/lib/active_record/dynamic_finder_match.rb index 0b66bea391..b39b291352 100644 --- a/activerecord/lib/active_record/dynamic_finder_match.rb +++ b/activerecord/lib/active_record/dynamic_finder_match.rb @@ -1,8 +1,9 @@ module ActiveRecord + # = Active Record Dynamic Finder Match # - # Provides dynamic attribute-based finders such as find_by_country if, for - # example, the Person has an attribute with that name. + # Provides dynamic attribute-based finders such as find_by_country + # if, for example, the Person has an attribute with that name. class DynamicFinderMatch def self.match(method) df_match = self.new(method) -- cgit v1.2.3 From c86915450af4ee800ca3eba474fe6d01c865c4c3 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Tue, 15 Jun 2010 23:11:30 +0430 Subject: Adds title. --- activerecord/lib/active_record/errors.rb | 3 + activerecord/lib/active_record/migration.rb | 98 ++++++++++++++++++----------- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb index cf5ddca2ba..7aa725d095 100644 --- a/activerecord/lib/active_record/errors.rb +++ b/activerecord/lib/active_record/errors.rb @@ -1,4 +1,7 @@ module ActiveRecord + + # = Active Record Errors + # # Generic Active Record exception class. class ActiveRecordError < StandardError end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 940f825038..4a1d6ac758 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -29,11 +29,15 @@ module ActiveRecord end end - # Migrations can manage the evolution of a schema used by several physical databases. It's a solution - # to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to - # push that change to other developers and to the production server. With migrations, you can describe the transformations - # in self-contained classes that can be checked into version control systems and executed against another database that - # might be one, two, or five versions behind. + # Active Record Migrations + # + # Migrations can manage the evolution of a schema used by several physical + # databases. It's a solution to the common problem of adding a field to make + # a new feature work in your local database, but being unsure of how to + # push that change to other developers and to the production server. With + # migrations, you can describe the transformations in self-contained classes + # that can be checked into version control systems and executed against + # another database that might be one, two, or five versions behind. # # Example of a simple migration: # @@ -47,10 +51,13 @@ module ActiveRecord # end # end # - # This migration will add a boolean flag to the accounts table and remove it if you're backing out of the migration. - # It shows how all migrations have two class methods +up+ and +down+ that describes the transformations required to implement - # or remove the migration. These methods can consist of both the migration specific methods like add_column and remove_column, - # but may also contain regular Ruby code for generating data needed for the transformations. + # This migration will add a boolean flag to the accounts table and remove it + # if you're backing out of the migration. It shows how all migrations have + # two class methods +up+ and +down+ that describes the transformations + # required to implement or remove the migration. These methods can consist + # of both the migration specific methods like add_column and remove_column, + # but may also contain regular Ruby code for generating data needed for the + # transformations. # # Example of a more complex migration that also needs to initialize data: # @@ -64,7 +71,9 @@ module ActiveRecord # t.integer :position # end # - # SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1 + # SystemSetting.create :name => "notice", + # :label => "Use notice?", + # :value => 1 # end # # def self.down @@ -72,35 +81,49 @@ module ActiveRecord # end # end # - # This migration first adds the system_settings table, then creates the very first row in it using the Active Record model - # that relies on the table. It also uses the more advanced create_table syntax where you can specify a complete table schema - # in one block call. + # This migration first adds the system_settings table, then creates the very + # first row in it using the Active Record model that relies on the table. It + # also uses the more advanced create_table syntax where you can specify a + # complete table schema in one block call. # # == Available transformations # - # * create_table(name, options) Creates a table called +name+ and makes the table object available to a block - # that can then add columns to it, following the same format as add_column. See example above. The options hash is for - # fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create table definition. + # * create_table(name, options) Creates a table called +name+ and + # makes the table object available to a block that can then add columns to it, + # following the same format as add_column. See example above. The options hash + # is for fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create + # table definition. # * drop_table(name): Drops the table called +name+. - # * rename_table(old_name, new_name): Renames the table called +old_name+ to +new_name+. - # * add_column(table_name, column_name, type, options): Adds a new column to the table called +table_name+ + # * rename_table(old_name, new_name): Renames the table called +old_name+ + # to +new_name+. + # * add_column(table_name, column_name, type, options): Adds a new column + # to the table called +table_name+ # named +column_name+ specified to be one of the following types: - # :string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, - # :date, :binary, :boolean. A default value can be specified by passing an - # +options+ hash like { :default => 11 }. Other options include :limit and :null (e.g. { :limit => 50, :null => false }) - # -- see ActiveRecord::ConnectionAdapters::TableDefinition#column for details. - # * rename_column(table_name, column_name, new_column_name): Renames a column but keeps the type and content. - # * change_column(table_name, column_name, type, options): Changes the column to a different type using the same - # parameters as add_column. - # * remove_column(table_name, column_name): Removes the column named +column_name+ from the table called +table_name+. - # * add_index(table_name, column_names, options): Adds a new index with the name of the column. Other options include - # :name and :unique (e.g. { :name => "users_name_index", :unique => true }). - # * remove_index(table_name, index_name): Removes the index specified by +index_name+. + # :string, :text, :integer, :float, + # :decimal, :datetime, :timestamp, :time, + # :date, :binary, :boolean. A default value can be + # specified by passing an +options+ hash like { :default => 11 }. + # Other options include :limit and :null (e.g. + # { :limit => 50, :null => false }) -- see + # ActiveRecord::ConnectionAdapters::TableDefinition#column for details. + # * rename_column(table_name, column_name, new_column_name): Renames + # a column but keeps the type and content. + # * change_column(table_name, column_name, type, options): Changes + # the column to a different type using the same parameters as add_column. + # * remove_column(table_name, column_name): Removes the column named + # +column_name+ from the table called +table_name+. + # * add_index(table_name, column_names, options): Adds a new index + # with the name of the column. Other options include + # :name and :unique (e.g. + # { :name => "users_name_index", :unique => true }). + # * remove_index(table_name, index_name): Removes the index specified + # by +index_name+. # # == Irreversible transformations # - # Some transformations are destructive in a manner that cannot be reversed. Migrations of that kind should raise - # an ActiveRecord::IrreversibleMigration exception in their +down+ method. + # Some transformations are destructive in a manner that cannot be reversed. + # Migrations of that kind should raise an ActiveRecord::IrreversibleMigration + # exception in their +down+ method. # # == Running migrations from within Rails # @@ -110,13 +133,15 @@ module ActiveRecord # rails generate migration MyNewMigration # # where MyNewMigration is the name of your migration. The generator will - # create an empty migration file timestamp_my_new_migration.rb in the db/migrate/ - # directory where timestamp is the UTC formatted date and time that the migration was generated. + # create an empty migration file timestamp_my_new_migration.rb + # in the db/migrate/ directory where timestamp is the + # UTC formatted date and time that the migration was generated. # # You may then edit the self.up and self.down methods of # MyNewMigration. # # There is a special syntactic shortcut to generate migrations that add fields to a table. + # # rails generate migration add_fieldname_to_tablename fieldname:string # # This will generate the file timestamp_add_fieldname_to_tablename, which will look like this: @@ -191,9 +216,10 @@ module ActiveRecord # # == Using a model after changing its table # - # Sometimes you'll want to add a column in a migration and populate it immediately after. In that case, you'll need - # to make a call to Base#reset_column_information in order to ensure that the model has the latest column data from - # after the new column was added. Example: + # Sometimes you'll want to add a column in a migration and populate it + # immediately after. In that case, you'll need to make a call to + # Base#reset_column_information in order to ensure that the model has the + # latest column data from after the new column was added. Example: # # class AddPeopleSalary < ActiveRecord::Migration # def self.up -- cgit v1.2.3 From 33b46079bc34e19c4de66963317edafb6ff2c0b5 Mon Sep 17 00:00:00 2001 From: Bryan Woods Date: Tue, 15 Jun 2010 15:17:23 -0400 Subject: Fixing some minor typos, grammar, accuracy, and spacing issues in Active Record Validations Callbacks guide --- .../activerecord_validations_callbacks.textile | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile index 1f9bc1279a..cfd4ae55cc 100644 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ b/railties/guides/source/activerecord_validations_callbacks.textile @@ -16,7 +16,7 @@ endprologue. h3. The Object Lifecycle -During the normal operation of a Rails application objects may be created, updated, and destroyed. Active Record provides hooks into this object lifecycle so that you can control your application and its data. +During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this object lifecycle so that you can control your application and its data. 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. @@ -71,7 +71,7 @@ The following methods trigger validations, and will save the object to the datab * +update_attributes+ * +update_attributes!+ -The bang versions (e.g. +save!+) raise an exception if the record is invalid. The non-bang versions don't: +save+ and +update_attributes+ return +false+, +create+ and +update+ just return the object/s. +The bang versions (e.g. +save!+) raise an exception if the record is invalid. The non-bang versions don't: +save+ and +update_attributes+ return +false+, +create+ and +update+ just return the objects. h4. Skipping Validations @@ -240,9 +240,9 @@ class Account < ActiveRecord::Base end -The +validates_exclusion_of+ helper has an option +:in+ that receives the set of values that will not be accepted for the validated attributes. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. This example uses the +:message+ option to show how you can include the attribute's value. +The +validates_exclusion_of+ helper has an option +:in+ that receives the set of values that will not be accepted for the validated attributes. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. This example uses the +:message+ option to show how you can include the attribute's value. -The default error message for +validates_exclusion_of+ is "_is reserved_". +The default error message for +validates_exclusion_of+ is "_is reserved_". h4. +validates_format_of+ @@ -270,7 +270,7 @@ end The +validates_inclusion_of+ helper has an option +:in+ that receives the set of values that will be accepted. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. The previous example uses the +:message+ option to show how you can include the attribute's value. -The default error message for +validates_inclusion_of+ is "_is not included in the list_". +The default error message for +validates_inclusion_of+ is "_is not included in the list_". h4. +validates_length_of+ @@ -343,7 +343,7 @@ Besides +:only_integer+, the +validates_numericality_of+ helper also accepts the * +:greater_than_or_equal_to+ - Specifies the value must be greater than or equal to the supplied value. The default error message for this option is "_must be greater than or equal to %{count}_". * +:equal_to+ - Specifies the value must be equal to the supplied value. The default error message for this option is "_must be equal to %{count}_". * +:less_than+ - Specifies the value must be less than the supplied value. The default error message for this option is "_must be less than %{count}_". -* +:less_than_or_equal_to+ - Specifies the value must be less than or equal the supplied value. The default error message for this option is "_must be less or equal to %{count}_". +* +:less_than_or_equal_to+ - Specifies the value must be less than or equal the supplied value. The default error message for this option is "_must be less than or equal to %{count}_". * +:odd+ - Specifies the value must be an odd number if set to true. The default error message for this option is "_must be odd_". * +:even+ - Specifies the value must be an even number if set to true. The default error message for this option is "_must be even_". @@ -374,7 +374,7 @@ The default error message for +validates_presence_of+ is "_can't be empty_". h4. +validates_uniqueness_of+ -This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create an unique index in your database. +This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create a unique index in your database. class Account < ActiveRecord::Base @@ -423,14 +423,14 @@ class GoodnessValidator < ActiveRecord::Validator end -The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class. +The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class. The validator class has two attributes by default: * +record+ - the record to be validated * +options+ - the extra options that were passed to +validates_with+ -Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+: +Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+: class Person < ActiveRecord::Base @@ -494,7 +494,7 @@ As you've already seen, the +:message+ option lets you specify the message that h4. +:on+ -The +:on+ option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be ran on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use +:on => :create+ to run the validation only when a new record is created or +:on => :update+ to run the validation only when a record is updated. +The +:on+ option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use +:on => :create+ to run the validation only when a new record is created or +:on => :update+ to run the validation only when a record is updated. class Person < ActiveRecord::Base @@ -573,7 +573,7 @@ class Invoice < ActiveRecord::Base end -You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find useful to express that a certain field corresponds to a set of choices: +You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find it useful to express that a certain field corresponds to a set of choices: ActiveRecord::Base.class_eval do @@ -599,7 +599,7 @@ The following is a list of the most commonly used methods. Please refer to the + h4(#working_with_validation_errors-errors). +errors+ -Returns an OrderedHash with all errors. Each key is the attribute name and value is an array of strings with all errors. +Returns an OrderedHash with all errors. Each key is the attribute name and the value is an array of strings with all errors. class Person < ActiveRecord::Base @@ -619,7 +619,7 @@ person.errors # => [] h4(#working_with_validation_errors-errors-2). +errors[]+ -+errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute returns an empty array. ++errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute, it returns an empty array. class Person < ActiveRecord::Base @@ -681,7 +681,7 @@ Another way to do this is using +[]=+ setter h4. +errors[:base]+ -You can add errors messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since +errors[:base]+ is an array, you can simply add a string to the array and uses it as the error message. +You can add error messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since +errors[:base]+ is an array, you can simply add a string to the array and uses it as the error message. class Person < ActiveRecord::Base @@ -789,7 +789,7 @@ Both the +form.error_messages+ and the +error_messages_for+ helpers accept optio :header_tag => :h3 %> -Which results in the following content +Which results in the following content: !images/customized_error_messages.png(Customized error messages)! -- cgit v1.2.3 From f103a75b488f08dae6d3df9772bcf22b02f54777 Mon Sep 17 00:00:00 2001 From: rohit Date: Wed, 16 Jun 2010 12:48:32 +0530 Subject: Guides: AS Core Extensions, fixed a few typos. --- .../source/active_support_core_extensions.textile | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 1c17609b0a..cdd1a9ff13 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -159,7 +159,7 @@ NOTE: Defined in +active_support/core_ext/object/duplicable.rb+. h4. +returning+ -The method +returning+ yields its argument to a block and returns it. You tipically use it with a mutable object that gets modified in the block: +The method +returning+ yields its argument to a block and returns it. You typically use it with a mutable object that gets modified in the block: def html_options_for_form(url_for_options, options, *parameters_for_url) @@ -187,7 +187,7 @@ def log_info(sql, name, ms) end -You can shorten that using +Object#try+. This method is a synonim for +Object#send+ except that it returns +nil+ if sent to +nil+. The previous example could then be rewritten as: +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: def log_info(sql, name, ms) @@ -294,7 +294,7 @@ we get: user_path(@user) # => "/users/357-john-smith" -WARNING. Controllers need to be aware of any redifinition of +to_param+ because when a request like that comes in "357-john-smith" is the value of +params[:id]+. +WARNING. Controllers need to be aware of any redefinition of +to_param+ because when a request like that comes in "357-john-smith" is the value of +params[:id]+. NOTE: Defined in +active_support/core_ext/object/to_param.rb+. @@ -332,7 +332,7 @@ Arrays return the result of applying +to_query+ to each element with _key_[] # => "sample%5B%5D=3.4&sample%5B%5D=-45.6" -Hashes also respond to +to_query+ but with a different signature. If no argument is passed a call generates a sorted series of key/value assigments calling +to_query(key)+ on its values. Then it joins the result with "&": +Hashes also respond to +to_query+ but with a different signature. If no argument is passed a call generates a sorted series of key/value assignments calling +to_query(key)+ on its values. Then it joins the result with "&": {:c => 3, :b => 2, :a => 1}.to_query # => "a=1&b=2&c=3" @@ -656,9 +656,9 @@ h5. Internal Attributes When you are defining an attribute in a class that is meant to be subclassed name collisions are a risk. That's remarkably important for libraries. -Active Support defines the macros +attr_internal_reader+, +attr_internal_writer+, and +attr_internal_accessor+. They behave like their Ruby builtin +attr_*+ counterparts, except they name the unerlying instace variable in a way that makes collisions less likely. +Active Support defines the macros +attr_internal_reader+, +attr_internal_writer+, and +attr_internal_accessor+. They behave like their Ruby builtin +attr_*+ counterparts, except they name the underlying instance variable in a way that makes collisions less likely. -The macro +attr_internal+ is a synonim for +attr_internal_accessor+: +The macro +attr_internal+ is a synonym for +attr_internal_accessor+: # library @@ -721,7 +721,7 @@ h4. Method Delegation The class method +delegate+ offers an easy way to forward methods. -For example, if +User+ has some details like the age factored out to +Profile+, it could be handy to still be able to acces such attribute directly, user.age, instead of having to explicit the chain user.profile.age. +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, user.age, instead of having to explicit the chain user.profile.age. That can be accomplished by hand: @@ -773,7 +773,7 @@ In fact, you can delegate to any expression passed as a string. It will be evalu delegate :alert, :notice, :to => "request.flash" -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+. +If the target is +nil+ calling any delegated method will raise an exception even if +nil+ responds to such method. You can override this behaviour setting the option +:allow_nil+ to true, in which case the forwarded call will simply return +nil+. 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: @@ -935,7 +935,7 @@ NOTE: Defined in +active_support/core_ext/module/synchronization.rb+. h4. Reachable -A named module is reachable if it is stored in its correspoding constant. It means you can reach the module object via the constant. +A named module is reachable if it is stored in its corresponding constant. It means you can reach the module object via the constant. That is what ordinarily happens, if a module is called "M", the +M+ constant exists and holds it: @@ -1016,7 +1016,7 @@ h3. Extensions to +Class+ h4. Class Attributes -The method +Class#class_attribute+ declares one or more inheritable class attributes that can be overriden at any level down the hierarchy: +The method +Class#class_attribute+ declares one or more inheritable class attributes that can be overridden at any level down the hierarchy: class A @@ -1088,7 +1088,7 @@ NOTE: Defined in +active_support/core_ext/class/attribute_accessors.rb+. h4. Class Inheritable Attributes -Class variables are shared down the inheritance tree. Class instance variables are not shared, but they are not inherited either. The macros +class_inheritable_reader+, +class_inheritable_writer+, and +class_inheritable_accessor+ provide accesors for class-level data which is inherited but not shared with children: +Class variables are shared down the inheritance tree. Class instance variables are not shared, but they are not inherited either. The macros +class_inheritable_reader+, +class_inheritable_writer+, and +class_inheritable_accessor+ provide accessors for class-level data which is inherited but not shared with children: module ActionController @@ -1204,7 +1204,7 @@ s.html_safe? # => true s # => "" -It is your responsability to ensure calling +html_safe+ on a particular string is fine. +It is your responsibility to ensure calling +html_safe+ on a particular string is fine. NOTE: For performance reasons safe strings are implemented in a way that cannot offer an in-place +html_safe!+ variant. @@ -1377,7 +1377,7 @@ The method +pluralize+ returns the plural of its receiver: "equipment".pluralize # => "equipment" -As the previous example shows, Active Support knows some irregular plurals and uncountable nouns. Builtin rules can be extended in +config/initializers/inflections.rb+. That file is generated by the +rails+ command and has instructions in comments. +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. Active Record uses this method to compute the default table name that corresponds to a model: @@ -1760,7 +1760,7 @@ h3. Extensions to +Float+ h4. +round+ -The builtin method +Float#round+ rounds a float to the nearest integer. Active Support adds an optional parameter to let you specify a precision: +The built-in method +Float#round+ rounds a float to the nearest integer. Active Support adds an optional parameter to let you specify a precision: Math::E.round(4) # => 2.7183 @@ -1925,7 +1925,7 @@ Similarly, +from+ returns the tail from the element at the passed index on: [].from(0) # => [] -The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is builtin). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available. +The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is built-in). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available. NOTE: Defined in +active_support/core_ext/array/access.rb+. @@ -2282,7 +2282,7 @@ NOTE: Defined in +active_support/core_ext/hash/conversions.rb+. h4. Merging -Ruby has a builtin method +Hash#merge+ that merges two hashes: +Ruby has a built-in method +Hash#merge+ that merges two hashes: {:a => 1, :b => 1}.merge(:a => 0, :c => 2) @@ -2511,7 +2511,7 @@ NOTE: Defined in +active_support/core_ext/hash/keys.rb+. h4. Slicing -Ruby has builtin support for taking slices out of strings and arrays. Active Support extends slicing to hashes: +Ruby has built-in support for taking slices out of strings and arrays. Active Support extends slicing to hashes: {:a => 1, :b => 2, :c => 3}.slice(:a, :c) @@ -2625,7 +2625,7 @@ Active Support extends this method so that the argument may be another range in (1...9).include?(3..9) # => false -WARNING: The orginal +Range#include?+ is still the one aliased to +Range#===+. +WARNING: The original +Range#include?+ is still the one aliased to +Range#===+. NOTE: Defined in +active_support/core_ext/range/include_range.rb+. @@ -2693,7 +2693,7 @@ h4. Calculations NOTE: All the following methods are defined in +active_support/core_ext/date/calculations.rb+. -INFO: The following calculation methods have edge cases in October 1582, since days 5..14 just do not exist. This guide does not document their behavior around those days for brevity, but it is enough to say that they do what you would expect. That is, +Date.new(1582, 10, 4).tomorrow+ returns +Date.new(1582, 10, 15)+ and so on. Please check +test/core_ext/date_ext_test.rb+ in the Active Support test suite for expected behavior. +INFO: The following calculation methods have edge cases in October 1582, since days 5..14 just do not exist. This guide does not document their behaviour around those days for brevity, but it is enough to say that they do what you would expect. That is, +Date.new(1582, 10, 4).tomorrow+ returns +Date.new(1582, 10, 15)+ and so on. Please check +test/core_ext/date_ext_test.rb+ in the Active Support test suite for expected behaviour. h5. +Date.current+ -- cgit v1.2.3 From 746347d997da14d6c67378518a4d7162c660212d Mon Sep 17 00:00:00 2001 From: rohit Date: Wed, 16 Jun 2010 12:52:21 +0530 Subject: Guides: AS Core Extensions, behaviour => behavior --- railties/guides/source/active_support_core_extensions.textile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index cdd1a9ff13..cd7a183def 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -773,7 +773,7 @@ In fact, you can delegate to any expression passed as a string. It will be evalu delegate :alert, :notice, :to => "request.flash" -If the target is +nil+ calling any delegated method will raise an exception even if +nil+ responds to such method. You can override this behaviour setting the option +:allow_nil+ to true, in which case the forwarded call will simply return +nil+. +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+. 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: @@ -2120,7 +2120,7 @@ NOTE: Defined in +active_support/core_ext/array/conversions.rb+. h4. Wrapping -The class method +Array.wrap+ behaves like the function +Array()+ except that it does not try to call +to_a+ on its argument. That changes the behaviour for enumerables: +The class method +Array.wrap+ behaves like the function +Array()+ except that it does not try to call +to_a+ on its argument. That changes the behavior for enumerables: Array.wrap(:foo => :bar) # => [{:foo => :bar}] @@ -2693,7 +2693,7 @@ h4. Calculations NOTE: All the following methods are defined in +active_support/core_ext/date/calculations.rb+. -INFO: The following calculation methods have edge cases in October 1582, since days 5..14 just do not exist. This guide does not document their behaviour around those days for brevity, but it is enough to say that they do what you would expect. That is, +Date.new(1582, 10, 4).tomorrow+ returns +Date.new(1582, 10, 15)+ and so on. Please check +test/core_ext/date_ext_test.rb+ in the Active Support test suite for expected behaviour. +INFO: The following calculation methods have edge cases in October 1582, since days 5..14 just do not exist. This guide does not document their behavior around those days for brevity, but it is enough to say that they do what you would expect. That is, +Date.new(1582, 10, 4).tomorrow+ returns +Date.new(1582, 10, 15)+ and so on. Please check +test/core_ext/date_ext_test.rb+ in the Active Support test suite for expected behavior. h5. +Date.current+ @@ -3080,7 +3080,7 @@ Active Support adds +missing_name?+ to +NameError+, which tests whether the exce The name may be given as a symbol or string. A symbol is tested against the bare constant name, a string is against the fully-qualified constant name. -TIP: A symbol can represent a fully-qualified constant name as in +:"ActiveRecord::Base"+, so the behaviour for symbols is defined for convenience, not because it has to be that way technically. +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. For example, when an action of +PostsController+ is called Rails tries optimistically to use +PostsHelper+. 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 +posts_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: -- cgit v1.2.3 From 317a75bf5860a9ab5d5535ccb4aedfabc83644d6 Mon Sep 17 00:00:00 2001 From: kaygee Date: Wed, 16 Jun 2010 12:10:50 -0500 Subject: Fix incorrect pluralization in 'These methods allows you to pass arguments...'. --- railties/guides/source/active_record_querying.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 73f3ebafbe..fc07dd1267 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -51,7 +51,7 @@ Active Record will perform queries on the database for you and is compatible wit h3. Retrieving Objects from the Database -To retrieve objects from the database, Active Record provides several finder methods. These methods allows you to pass arguments into it to perform certain queries on your database without the need of writing raw SQL. +To retrieve objects from the database, Active Record provides several finder methods. These methods allow you to pass arguments into it to perform certain queries on your database without the need of writing raw SQL. The methods are: * +where+ -- cgit v1.2.3 From d8277804b2ad95275d21492f4d925d1148425253 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:08:14 +0430 Subject: Adds title and minor changes. --- activerecord/lib/active_record/migration.rb | 2 +- activerecord/lib/active_record/named_scope.rb | 11 +++++--- .../lib/active_record/nested_attributes.rb | 3 ++- activerecord/lib/active_record/observer.rb | 2 ++ activerecord/lib/active_record/persistence.rb | 29 ++++++++++++++-------- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 4a1d6ac758..b273c33e50 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -29,7 +29,7 @@ module ActiveRecord end end - # Active Record Migrations + # = Active Record Migrations # # Migrations can manage the evolution of a schema used by several physical # databases. It's a solution to the common problem of adding a field to make diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 3d8f4a030b..096b9da402 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -4,11 +4,12 @@ require 'active_support/core_ext/kernel/singleton_class' require 'active_support/core_ext/object/blank' module ActiveRecord + # = Active Record Named Scopes module NamedScope extend ActiveSupport::Concern module ClassMethods - # Returns an anonymous scope. + # Returns an anonymous \scope. # # posts = Post.scoped # posts.size # Fires "select count(*) from posts" and returns the count @@ -18,10 +19,12 @@ module ActiveRecord # fruits = fruits.where(:colour => 'red') if options[:red_only] # fruits = fruits.limit(10) if limited? # - # Anonymous \scopes tend to be useful when procedurally generating complex queries, where passing - # intermediate values (scopes) around as first-class objects is convenient. + # Anonymous scopes tend to be useful when procedurally generating complex + # queries, where passing intermediate values (scopes) around as first-class + # objects is convenient. # - # You can define a scope that applies to all finders using ActiveRecord::Base.default_scope. + # You can define a scope that applies to all finders using + # ActiveRecord::Base.default_scope. def scoped(options = {}, &block) if options.present? relation = scoped.apply_finder_options(options) diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 767ec85432..99f8b431c8 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -15,7 +15,7 @@ module ActiveRecord self.nested_attributes_options = {} end - # == Nested Attributes + # = Active Record Nested Attributes # # Nested attributes allow you to save attributes on associated records # through the parent. By default nested attribute updating is turned off, @@ -25,6 +25,7 @@ module ActiveRecord # # The attribute writer is named after the association, which means that # in the following example, two new methods are added to your model: + # # author_attributes=(attributes) and # pages_attributes=(attributes). # diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index 0ea7fe7365..9554dd8826 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -1,6 +1,8 @@ require 'active_support/core_ext/class/attribute' module ActiveRecord + # = Active Record Observer + # # Observer classes respond to lifecycle callbacks to implement trigger-like # behavior outside the original class. This is a great way to reduce the # clutter that normally comes when the model class is burdened with diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 10788630a5..9e28aa2a05 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -1,6 +1,8 @@ module ActiveRecord + # = Active Record Persistence module Persistence - # Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet; otherwise, returns false. + # Returns true if this object hasn't been saved yet -- that is, a record + # for the object doesn't exist in the data store yet; otherwise, returns false. def new_record? @new_record end @@ -10,7 +12,8 @@ module ActiveRecord @destroyed end - # Returns if the record is persisted, i.e. it's not a new record and it was not destroyed. + # Returns if the record is persisted, i.e. it's not a new record and it was + # not destroyed. def persisted? !(new_record? || destroyed?) end @@ -69,8 +72,8 @@ module ActiveRecord freeze end - # Deletes the record in the database and freezes this instance to reflect that no changes should - # be made (since they can't be persisted). + # Deletes the record in the database and freezes this instance to reflect + # that no changes should be made (since they can't be persisted). def destroy if persisted? self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).delete_all @@ -80,10 +83,13 @@ module ActiveRecord freeze end - # Returns an instance of the specified +klass+ with the attributes of the current record. This is mostly useful in relation to - # single-table inheritance structures where you want a subclass to appear as the superclass. This can be used along with record - # identification in Action Pack to allow, say, Client < Company to do something like render :partial => @client.becomes(Company) - # to render that instance using the companies/company partial instead of clients/client. + # Returns an instance of the specified +klass+ with the attributes of the + # current record. This is mostly useful in relation to single-table + # inheritance structures where you want a subclass to appear as the + # superclass. This can be used along with record identification in + # Action Pack to allow, say, Client < Company to do something + # like render :partial => @client.becomes(Company) to render that + # instance using the companies/company partial instead of clients/client. # # Note: The new instance will share a link to the same attributes as the original class. So any change to the attributes in either # instance will affect the other. @@ -104,14 +110,15 @@ module ActiveRecord save(:validate => false) end - # Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will - # fail and false will be returned. + # Updates all the attributes from the passed-in Hash and saves the record. + # If the object is invalid, the saving will fail and false will be returned. def update_attributes(attributes) self.attributes = attributes save end - # Updates an object just like Base.update_attributes but calls save! instead of save so an exception is raised if the record is invalid. + # Updates an object just like Base.update_attributes but calls save! instead + # of save so an exception is raised if the record is invalid. def update_attributes!(attributes) self.attributes = attributes save! -- cgit v1.2.3 From 2b7f08428c5e2a866f65ab0ba2838da5857c471b Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:15:04 +0430 Subject: Adds basic description and title. --- activerecord/lib/active_record/query_cache.rb | 1 + activerecord/lib/active_record/railtie.rb | 1 + activerecord/lib/active_record/reflection.rb | 45 ++++++++++++++++++--------- activerecord/lib/active_record/relation.rb | 8 +++-- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb index 093c6c1e55..d9f85a4e5e 100644 --- a/activerecord/lib/active_record/query_cache.rb +++ b/activerecord/lib/active_record/query_cache.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/object/blank' module ActiveRecord + # = Active Record Query Cache class QueryCache module ClassMethods # Enable the query cache within the block if Active Record is configured. diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index a32fb7d399..37f1ec11a6 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -9,6 +9,7 @@ require "active_model/railtie" require "action_controller/railtie" module ActiveRecord + # = Active Record Railtie class Railtie < Rails::Railtie config.active_record = ActiveSupport::OrderedOptions.new diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index d4af3d7d15..a82e5d7ed1 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -1,12 +1,16 @@ module ActiveRecord + # = Active Record Reflection module Reflection # :nodoc: extend ActiveSupport::Concern - # Reflection allows you to interrogate Active Record classes and objects about their associations and aggregations. - # This information can, for example, be used in a form builder that took an Active Record object and created input - # fields for all of the attributes depending on their type and displayed the associations to other objects. + # Reflection allows you to interrogate Active Record classes and objects + # about their associations and aggregations. This information can, + # for example, be used in a form builder that took an Active Record object + # and created input fields for all of the attributes depending on their type + # and displayed the associations to other objects. # - # You can find the interface for the AggregateReflection and AssociationReflection classes in the abstract MacroReflection class. + # You can find the interface for the AggregateReflection and AssociationReflection + # classes in the abstract MacroReflection class. module ClassMethods def create_reflection(macro, name, options, active_record) case macro @@ -43,8 +47,11 @@ module ActiveRecord reflections[aggregation].is_a?(AggregateReflection) ? reflections[aggregation] : nil end - # Returns an array of AssociationReflection objects for all the associations in the class. If you only want to reflect on a - # certain association type, pass in the symbol (:has_many, :has_one, :belongs_to) for that as the first parameter. + # Returns an array of AssociationReflection objects for all the + # associations in the class. If you only want to reflect on a certain + # association type, pass in the symbol (:has_many, :has_one, + # :belongs_to) for that as the first parameter. + # # Example: # # Account.reflect_on_all_associations # returns an array of all associations @@ -71,8 +78,9 @@ module ActiveRecord end - # Abstract base class for AggregateReflection and AssociationReflection that describes the interface available for both of - # those classes. Objects of AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. + # Abstract base class for AggregateReflection and AssociationReflection that + # describes the interface available for both of those classes. Objects of + # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. class MacroReflection attr_reader :active_record @@ -80,13 +88,15 @@ module ActiveRecord @macro, @name, @options, @active_record = macro, name, options, active_record end - # Returns the name of the macro. For example, composed_of :balance, :class_name => 'Money' will return - # :balance or for has_many :clients it will return :clients. + # Returns the name of the macro. For example, composed_of :balance, + # :class_name => 'Money' will return :balance or for + # has_many :clients it will return :clients. def name @name end - # Returns the macro type. For example, composed_of :balance, :class_name => 'Money' will return :composed_of + # Returns the macro type. For example, + # composed_of :balance, :class_name => 'Money' will return :composed_of # or for has_many :clients will return :has_many. def macro @macro @@ -132,11 +142,13 @@ module ActiveRecord end - # Holds all the meta-data about an aggregation as it was specified in the Active Record class. + # Holds all the meta-data about an aggregation as it was specified in the + # Active Record class. class AggregateReflection < MacroReflection #:nodoc: end - # Holds all the meta-data about an association as it was specified in the Active Record class. + # Holds all the meta-data about an association as it was specified in the + # Active Record class. class AssociationReflection < MacroReflection #:nodoc: # Returns the target association's class: # @@ -306,9 +318,12 @@ module ActiveRecord end end - # Holds all the meta-data about a :through association as it was specified in the Active Record class. + # Holds all the meta-data about a :through association as it was specified + # in the Active Record class. class ThroughReflection < AssociationReflection #:nodoc: - # Gets the source of the through reflection. It checks both a singularized and pluralized form for :belongs_to or :has_many. + # Gets the source of the through reflection. It checks both a singularized + # and pluralized form for :belongs_to or :has_many. + # # (The :tags association on Tagging below.) # # class Post < ActiveRecord::Base diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 5d99a15eda..66970a5ea1 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/object/blank' module ActiveRecord + # = Active Record Relation class Relation JoinOperation = Struct.new(:relation, :join_class, :on) ASSOCIATION_METHODS = [:includes, :eager_load, :preload] @@ -75,10 +76,12 @@ module ActiveRecord @records end + # Returns size of the records. def size loaded? ? @records.length : count end + # Returns true if there are no records. def empty? loaded? ? @records.empty? : count.zero? end @@ -240,8 +243,9 @@ module ActiveRecord # Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')") # Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else']) # - # Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent - # associations or call your before_* or +after_destroy+ callbacks, use the +destroy_all+ method instead. + # Both calls delete the affected posts all at once with a single DELETE statement. + # If you need to destroy dependent associations or call your before_* or + # +after_destroy+ callbacks, use the +destroy_all+ method instead. def delete_all(conditions = nil) conditions ? where(conditions).delete_all : arel.delete.tap { reset } end -- cgit v1.2.3 From 0ebdc26caeb755df388ad31ea004960a64ba14c3 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:17:05 +0430 Subject: Adds title where needed. --- activerecord/lib/active_record/schema.rb | 2 ++ activerecord/lib/active_record/schema_dumper.rb | 15 +++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index a833356d15..e2783087ec 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -1,6 +1,8 @@ require 'active_support/core_ext/object/blank' module ActiveRecord + # = Active Record Schema + # # Allows programmers to programmatically define a schema in a portable # DSL. This means you can define tables, indexes, etc. without using SQL # directly, so your applications can more easily support multiple diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 71ef249ee1..a4757773d8 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -2,6 +2,8 @@ require 'stringio' require 'active_support/core_ext/big_decimal' module ActiveRecord + # = Active Record Schema Dumper + # # This class is used to dump the database schema for some connection to some # output format (i.e., ActiveRecord::Schema). class SchemaDumper #:nodoc: @@ -39,13 +41,14 @@ module ActiveRecord define_params = @version ? ":version => #{@version}" : "" stream.puts <
Date: Wed, 16 Jun 2010 22:22:35 +0430 Subject: Adds title and proper formatting to docs. --- activerecord/lib/active_record/serialization.rb | 2 ++ activerecord/lib/active_record/session_store.rb | 8 ++++++++ activerecord/lib/active_record/test_case.rb | 3 +++ activerecord/lib/active_record/timestamp.rb | 18 ++++++++++++------ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb index b49471f7ab..2d8bd184f3 100644 --- a/activerecord/lib/active_record/serialization.rb +++ b/activerecord/lib/active_record/serialization.rb @@ -1,4 +1,5 @@ module ActiveRecord #:nodoc: + # = Active Record Serialization module Serialization extend ActiveSupport::Concern include ActiveModel::Serializers::JSON @@ -22,6 +23,7 @@ module ActiveRecord #:nodoc: private # Add associations specified via the :includes option. + # # Expects a block that takes as arguments: # +association+ - name of the association # +records+ - the association record(s) to be serialized diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb index 931872eded..f712a2c94f 100644 --- a/activerecord/lib/active_record/session_store.rb +++ b/activerecord/lib/active_record/session_store.rb @@ -1,4 +1,6 @@ module ActiveRecord + # = Active Record Session Store + # # A session store backed by an Active Record class. A default class is # provided, but any object duck-typing to an Active Record Session class # with text +session_id+ and +data+ attributes is sufficient. @@ -7,6 +9,7 @@ module ActiveRecord # +id+ (numeric primary key), # +session_id+ (text, or longtext if your session data exceeds 65K), and # +data+ (text or longtext; careful if your session data exceeds 65KB). + # # The +session_id+ column should always be indexed for speedy lookups. # Session data is marshaled to the +data+ column in Base64 format. # If the data you write is larger than the column's size limit, @@ -14,9 +17,11 @@ module ActiveRecord # # You may configure the table name, primary key, and data column. # For example, at the end of config/environment.rb: + # # ActiveRecord::SessionStore::Session.table_name = 'legacy_session_table' # ActiveRecord::SessionStore::Session.primary_key = 'session_id' # ActiveRecord::SessionStore::Session.data_column_name = 'legacy_session_data' + # # Note that setting the primary key to the +session_id+ frees you from # having a separate +id+ column if you don't want it. However, you must # set session.model.id = session.session_id by hand! A before filter @@ -29,8 +34,11 @@ module ActiveRecord # You may provide your own session class implementation, whether a # feature-packed Active Record or a bare-metal high-performance SQL # store, by setting + # # ActiveRecord::SessionStore.session_class = MySessionClass + # # You must implement these methods: + # # self.find_by_session_id(session_id) # initialize(hash_of_session_id_and_data) # attr_reader :session_id diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index 0a77ad5fd7..e61a378d17 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -1,4 +1,7 @@ module ActiveRecord + # = Active Record Test Case + # + # Defines some test assertions to test against SQL queries. class TestCase < ActiveSupport::TestCase #:nodoc: def assert_date_from_db(expected, actual, message = nil) # SybaseAdapter doesn't have a separate column type just for dates, diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 9fba8f0aca..ffd12d2082 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -1,11 +1,16 @@ module ActiveRecord - # Active Record automatically timestamps create and update operations if the table has fields - # named created_at/created_on or updated_at/updated_on. + # = Active Record Timestamp + # + # Active Record automatically timestamps create and update operations if the + # table has fields named created_at/created_on or + # updated_at/updated_on. + # + # Timestamping can be turned off by setting: # - # Timestamping can be turned off by setting # ActiveRecord::Base.record_timestamps = false # - # Timestamps are in the local timezone by default but you can use UTC by setting + # Timestamps are in the local timezone by default but you can use UTC by setting: + # # ActiveRecord::Base.default_timezone = :utc module Timestamp extend ActiveSupport::Concern @@ -16,8 +21,9 @@ module ActiveRecord end # Saves the record with the updated_at/on attributes set to the current time. - # If the save fails because of validation errors, an ActiveRecord::RecordInvalid exception is raised. - # If an attribute name is passed, that attribute is used for the touch instead of the updated_at/on attributes. + # If the save fails because of validation errors, an + # ActiveRecord::RecordInvalid exception is raised. If an attribute name is passed, + # that attribute is used for the touch instead of the updated_at/on attributes. # # Examples: # -- cgit v1.2.3 From 6445441253711d9131fa859115dd8224ea31eeee Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:25:15 +0430 Subject: Adds title to the rest of the files in activerecord/lib --- activerecord/lib/active_record/transactions.rb | 6 ++++-- activerecord/lib/active_record/validations.rb | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 620758f5af..b4b146994d 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -11,7 +11,8 @@ module ActiveRecord included do define_callbacks :commit, :rollback, :terminator => "result == false", :scope => [:kind, :name] end - + # = Active Record Transactions + # # Transactions are protective blocks where SQL statements are only permanent # if they can all succeed as one atomic action. The classic example is a # transfer between two accounts where you can only have a deposit if the @@ -19,7 +20,8 @@ module ActiveRecord # the database and guard the data against program errors or database # break-downs. So basically you should use transaction blocks whenever you # have a number of statements that must be executed together or not at all. - # Example: + # + # For example: # # ActiveRecord::Base.transaction do # david.withdrawal(100) diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index be64e00bd1..6b511e83db 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -1,6 +1,9 @@ module ActiveRecord + # = Active Record Validations + # # Raised by save! and create! when the record is invalid. Use the # +record+ method to retrieve the record which did not validate. + # # begin # complex_operation_that_calls_save!_internally # rescue ActiveRecord::RecordInvalid => invalid -- cgit v1.2.3 From fde95048475c1ffc89978650411b2e9034ff6a35 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:28:20 +0430 Subject: Adds title to activerecord/lib/active_record/associations/* --- activerecord/lib/active_record/associations/association_collection.rb | 2 ++ activerecord/lib/active_record/associations/association_proxy.rb | 2 ++ activerecord/lib/active_record/associations/belongs_to_association.rb | 1 + .../active_record/associations/belongs_to_polymorphic_association.rb | 1 + .../active_record/associations/has_and_belongs_to_many_association.rb | 1 + activerecord/lib/active_record/associations/has_many_association.rb | 1 + .../lib/active_record/associations/has_many_through_association.rb | 1 + activerecord/lib/active_record/associations/has_one_association.rb | 1 + .../lib/active_record/associations/has_one_through_association.rb | 1 + .../lib/active_record/associations/through_association_scope.rb | 1 + 10 files changed, 12 insertions(+) diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index d9903243ce..5b5094bcab 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -3,6 +3,8 @@ require 'active_support/core_ext/array/wrap' module ActiveRecord module Associations + # = Active Record Association Collection + # # AssociationCollection is an abstract class that provides common stuff to # ease the implementation of association proxies that represent # collections. See the class hierarchy in AssociationProxy. diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index e88618d278..f333f4d603 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -2,6 +2,8 @@ require 'active_support/core_ext/array/wrap' module ActiveRecord module Associations + # = Active Record Associations + # # This is the root class of all association proxies: # # AssociationProxy diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index d2f2267e5c..c2a6495db5 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Belongs To Associations module Associations class BelongsToAssociation < AssociationProxy #:nodoc: def create(attributes = {}) diff --git a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb index f6edd6383c..38454ec242 100644 --- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Belongs To Polymorphic Association module Associations class BelongsToPolymorphicAssociation < AssociationProxy #:nodoc: def replace(record) diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index 7f39a189e4..c989c3536d 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Has And Belongs To Many Association module Associations class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc: def create(attributes = {}) diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 0464e8ceea..92c6b3e770 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Has Many Association module Associations # This is the proxy that handles a has many association. # diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index 5338bb099d..17f850756f 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -2,6 +2,7 @@ require "active_record/associations/through_association_scope" require 'active_support/core_ext/object/blank' module ActiveRecord + # = Active Record Has Many Through Association module Associations class HasManyThroughAssociation < HasManyAssociation #:nodoc: include ThroughAssociationScope diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb index ea769fd48b..68b8b792ad 100644 --- a/activerecord/lib/active_record/associations/has_one_association.rb +++ b/activerecord/lib/active_record/associations/has_one_association.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Belongs To Has One Association module Associations class HasOneAssociation < AssociationProxy #:nodoc: def initialize(owner, reflection) diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb index a79bf943d1..fba0a2bfcc 100644 --- a/activerecord/lib/active_record/associations/has_one_through_association.rb +++ b/activerecord/lib/active_record/associations/has_one_through_association.rb @@ -1,6 +1,7 @@ require "active_record/associations/through_association_scope" module ActiveRecord + # = Active Record Has One Through Association module Associations class HasOneThroughAssociation < HasOneAssociation include ThroughAssociationScope diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 93bd6e3185..22e1033a9d 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -1,4 +1,5 @@ module ActiveRecord + # = Active Record Through Association Scope module Associations module ThroughAssociationScope -- cgit v1.2.3 From 9a4fc420711a7225ef0504baf97b22a3728b21a4 Mon Sep 17 00:00:00 2001 From: kaygee Date: Wed, 16 Jun 2010 13:06:46 -0500 Subject: Clarify language around list of finder methods. Clarify that finder methods return an instance of class ActiveRecord::Relation. --- railties/guides/source/active_record_querying.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index fc07dd1267..f5e70aef41 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -51,7 +51,7 @@ Active Record will perform queries on the database for you and is compatible wit h3. Retrieving Objects from the Database -To retrieve objects from the database, Active Record provides several finder methods. These methods allow you to pass arguments into it to perform certain queries on your database without the need of writing raw SQL. +To retrieve objects from the database, Active Record provides several finder methods. Each finder method allows you to pass arguments into it to perform certain queries on your database without writing raw SQL. The methods are: * +where+ @@ -66,7 +66,7 @@ The methods are: * +readonly+ * +from+ -All of these methods return a Relation +All of the above methods return an instance of ActiveRecord::Relation. Primary operation of Model.find(options) can be summarized as: -- cgit v1.2.3 From 5a0bc2c7bc993e8f987a99f510b7d1d2cc7cf8ba Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:47:49 +0430 Subject: Adds title and description where needed. --- actionpack/lib/action_view/base.rb | 10 ++++++---- actionpack/lib/action_view/context.rb | 21 +++++++++------------ .../lib/action_view/helpers/asset_tag_helper.rb | 1 + .../lib/action_view/helpers/atom_feed_helper.rb | 6 ++++-- actionpack/lib/action_view/helpers/cache_helper.rb | 6 ++++-- .../lib/action_view/helpers/capture_helper.rb | 2 ++ actionpack/lib/action_view/helpers/csrf_helper.rb | 4 +++- actionpack/lib/action_view/helpers/date_helper.rb | 2 ++ actionpack/lib/action_view/helpers/debug_helper.rb | 4 +++- actionpack/lib/action_view/helpers/form_helper.rb | 1 + .../lib/action_view/helpers/form_options_helper.rb | 1 + .../lib/action_view/helpers/form_tag_helper.rb | 1 + .../lib/action_view/helpers/javascript_helper.rb | 1 + .../lib/action_view/helpers/prototype_helper.rb | 1 + .../lib/action_view/helpers/raw_output_helper.rb | 9 +++++++++ 15 files changed, 48 insertions(+), 22 deletions(-) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 4d06ca0d89..a7ba9f374a 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -8,11 +8,13 @@ module ActionView #:nodoc: class NonConcattingString < ActiveSupport::SafeBuffer end + # = Action View Base + # # Action View templates can be written in three ways. If the template file has a .erb (or .rhtml) extension then it uses a mixture of ERb # (included in Ruby) and HTML. If the template file has a .builder (or .rxml) extension then Jim Weirich's Builder::XmlMarkup library is used. # If the template file has a .rjs extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator. # - # = ERb + # == ERb # # You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the # following loop for names: @@ -32,7 +34,7 @@ module ActionView #:nodoc: # # <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>. # - # == Using sub templates + # === Using sub templates # # Using sub templates allows you to sidestep tedious replication and extract common display structures in shared templates. The # classic example is the use of a header and footer (even though the Action Pack-way would be to use Layouts): @@ -54,7 +56,7 @@ module ActionView #:nodoc: # # <%= @page_title %> # - # == Passing local variables to sub templates + # === Passing local variables to sub templates # # You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values: # @@ -74,7 +76,7 @@ module ActionView #:nodoc: # # Testing using defined? headline will not work. This is an implementation restriction. # - # == Template caching + # === Template caching # # By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will # check the file's modification time and recompile it. diff --git a/actionpack/lib/action_view/context.rb b/actionpack/lib/action_view/context.rb index 88efd4b34f..39d88333e8 100644 --- a/actionpack/lib/action_view/context.rb +++ b/actionpack/lib/action_view/context.rb @@ -2,13 +2,12 @@ module ActionView module CompiledTemplates #:nodoc: # holds compiled template code end - - # Action View contexts are supplied to Action Controller - # to render template. The default Action View context - # is ActionView::Base. + # = Action View Context + # + # Action View contexts are supplied to Action Controller to render template. + # The default Action View context is ActionView::Base. # - # In order to work with ActionController, a Context - # must implement: + # In order to work with ActionController, a Context must implement: # # Context#render_partial[options] # - responsible for setting options[:_template] @@ -21,16 +20,14 @@ module ActionView # options:: See _render_template_with_layout in ActionView::Base # partial:: Whether or not the template to render is a partial # - # An Action View context can also mix in Action View's - # helpers. In order to mix in helpers, a context must - # implement: + # An Action View context can also mix in Action View's helpers. In order to + # mix in helpers, a context must implement: # # Context#controller # - Returns an instance of AbstractController # - # In any case, a context must mix in ActionView::Context, - # which stores compiled template and provides the output - # buffer. + # In any case, a context must mix in ActionView::Context, which stores compiled + # template and provides the output buffer. module Context include CompiledTemplates attr_accessor :output_buffer diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 25426a5547..d094b0d8d8 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -6,6 +6,7 @@ require 'active_support/core_ext/file' require 'active_support/core_ext/object/blank' module ActionView + # = Action View Asset Tag Helpers module Helpers #:nodoc: # This module provides methods for generating HTML that links views to assets such # as images, javascripts, stylesheets, and feeds. These methods do not verify diff --git a/actionpack/lib/action_view/helpers/atom_feed_helper.rb b/actionpack/lib/action_view/helpers/atom_feed_helper.rb index 52806f206a..cb5a1404ff 100644 --- a/actionpack/lib/action_view/helpers/atom_feed_helper.rb +++ b/actionpack/lib/action_view/helpers/atom_feed_helper.rb @@ -1,10 +1,12 @@ require 'set' -# Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERb or any other -# template languages). module ActionView + # = Action View Atom Feed Helpers module Helpers #:nodoc: module AtomFeedHelper + # Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERb or any other + # template languages). + # # Full usage example: # # config/routes.rb: diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index 8251ed18f4..f544a9d147 100644 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ b/actionpack/lib/action_view/helpers/cache_helper.rb @@ -1,8 +1,10 @@ module ActionView + # = Action View Cache Helper module Helpers - # This helper to exposes a method for caching of view fragments. - # See ActionController::Caching::Fragments for usage instructions. module CacheHelper + # This helper to exposes a method for caching of view fragments. + # See ActionController::Caching::Fragments for usage instructions. + # # A method for caching fragments of a view rather than an entire # action or page. This technique is useful caching pieces like # menus, lists of news topics, static HTML fragments, and so on. diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index edc6afc622..ea1bf14c96 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -1,9 +1,11 @@ require 'active_support/core_ext/object/blank' module ActionView + # = Action View Capture Helper module Helpers # CaptureHelper exposes methods to let you extract generated markup which # can be used in other parts of a template or layout file. + # # It provides a method to capture blocks into variables through capture and # a way to capture a block of markup for use in a layout through content_for. module CaptureHelper diff --git a/actionpack/lib/action_view/helpers/csrf_helper.rb b/actionpack/lib/action_view/helpers/csrf_helper.rb index 41c6b67f91..3d03f6aac6 100644 --- a/actionpack/lib/action_view/helpers/csrf_helper.rb +++ b/actionpack/lib/action_view/helpers/csrf_helper.rb @@ -1,7 +1,9 @@ module ActionView + # = Action View CSRF Helper module Helpers module CsrfHelper - # Returns a meta tag with the request forgery protection token for forms to use. Put this in your head. + # Returns a meta tag with the cross-site request forgery protection token + # for forms to use. Place this in your head. def csrf_meta_tag if protect_against_forgery? %(\n).html_safe diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 7d846a01dd..6f387bc95a 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -4,6 +4,8 @@ require 'active_support/core_ext/hash/slice' module ActionView module Helpers + # = Action View Date Helpers + # # The Date Helper primarily creates select/option tags for different kinds of dates and date elements. All of the # select-type methods share a number of common options that are as follows: # diff --git a/actionpack/lib/action_view/helpers/debug_helper.rb b/actionpack/lib/action_view/helpers/debug_helper.rb index e637dc1474..1491cb073f 100644 --- a/actionpack/lib/action_view/helpers/debug_helper.rb +++ b/actionpack/lib/action_view/helpers/debug_helper.rb @@ -1,6 +1,8 @@ module ActionView + # = Action View Debug Helper + # + # Provides a set of methods for making it easier to debug Rails objects. module Helpers - # Provides a set of methods for making it easier to debug Rails objects. module DebugHelper # Returns a YAML representation of +object+ wrapped with
 and 
. # If the object cannot be converted to YAML using +to_yaml+, +inspect+ will be called instead. diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 9e2448fe97..a8887a804e 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -7,6 +7,7 @@ require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/object/blank' module ActionView + # = Action View Form Helpers module Helpers # Form helpers are designed to make working with resources much easier # compared to using vanilla HTML. diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 6bf78647ec..c564d30302 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -4,6 +4,7 @@ require 'action_view/helpers/form_helper' require 'active_support/core_ext/object/blank' module ActionView + # = Action View Form Option Helpers module Helpers # Provides a number of methods for turning different kinds of containers into a set of option tags. # == Options diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 0727375fc0..ea491b2db8 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -4,6 +4,7 @@ require 'active_support/core_ext/object/returning' require 'active_support/core_ext/object/blank' module ActionView + # = Action View Form Tag Helpers module Helpers # Provides a number of methods for creating form tags that doesn't rely on an Active Record object assigned to the template like # FormHelper does. Instead, you provide the names and values manually. diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index b0a7718f22..84f53b842c 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -1,6 +1,7 @@ require 'action_view/helpers/tag_helper' module ActionView + # = Action View JavaScript Helpers module Helpers # Provides functionality for working with JavaScript in your views. # diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index a798c3eaef..3038b07143 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -4,6 +4,7 @@ require 'active_support/core_ext/object/returning' require 'active_support/core_ext/object/blank' module ActionView + # = Action View Prototype Helpers module Helpers # Prototype[http://www.prototypejs.org/] is a JavaScript library that provides # DOM[http://en.wikipedia.org/wiki/Document_Object_Model] manipulation, diff --git a/actionpack/lib/action_view/helpers/raw_output_helper.rb b/actionpack/lib/action_view/helpers/raw_output_helper.rb index 8c7f41177d..da7599fa8f 100644 --- a/actionpack/lib/action_view/helpers/raw_output_helper.rb +++ b/actionpack/lib/action_view/helpers/raw_output_helper.rb @@ -1,6 +1,15 @@ module ActionView #:nodoc: + # = Action View Raw Output Helper module Helpers #:nodoc: module RawOutputHelper + # This method outputs without escaping a string. Since escaping tags is + # now default, this can be used when you don't want Rails to automatically + # escape tags. This is not recommended if the data is coming from the user's + # input. + # + # For example: + # + # <%=raw @user.name %> def raw(stringish) stringish.to_s.html_safe end -- cgit v1.2.3 From 324de1993bf507a31025db3dc787f63b2152b4f5 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:54:53 +0430 Subject: Added titles and description. --- .../lib/action_view/helpers/record_tag_helper.rb | 1 + .../lib/action_view/helpers/sanitize_helper.rb | 16 +++++++++---- .../action_view/helpers/scriptaculous_helper.rb | 7 ++++-- actionpack/lib/action_view/helpers/tag_helper.rb | 1 + actionpack/lib/action_view/helpers/text_helper.rb | 1 + .../lib/action_view/helpers/translation_helper.rb | 27 ++++++++++++++-------- actionpack/lib/action_view/helpers/url_helper.rb | 1 + 7 files changed, 37 insertions(+), 17 deletions(-) diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb index a9cf15f418..7433f08777 100644 --- a/actionpack/lib/action_view/helpers/record_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb @@ -1,4 +1,5 @@ module ActionView + # = Action View Record Tag Helpers module Helpers module RecordTagHelper # Produces a wrapper DIV element with id and class parameters that diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb index f173523f6a..b47818a22a 100644 --- a/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -2,19 +2,25 @@ require 'action_controller/vendor/html-scanner' require 'action_view/helpers/tag_helper' module ActionView + # = Action View Sanitize Helpers module Helpers #:nodoc: # The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements. # These helper methods extend Action View making them callable within your template files. module SanitizeHelper - # This +sanitize+ helper will html encode all tags and strip all attributes that aren't specifically allowed. - # It also strips href/src tags with invalid protocols, like javascript: especially. It does its best to counter any - # tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters. Check out + # This +sanitize+ helper will html encode all tags and strip all attributes that + # aren't specifically allowed. + # + # It also strips href/src tags with invalid protocols, like javascript: especially. + # It does its best to counter any tricks that hackers may use, like throwing in + # unicode/ascii/hex values to get past the javascript: filters. Check out # the extensive test suite. # # <%= sanitize @article.body %> # - # You can add or remove tags/attributes if you want to customize it a bit. See ActionView::Base for full docs on the - # available options. You can add tags/attributes for single uses of +sanitize+ by passing either the :attributes or :tags options: + # You can add or remove tags/attributes if you want to customize it a bit. + # See ActionView::Base for full docs on the available options. You can add + # tags/attributes for single uses of +sanitize+ by passing either the + # :attributes or :tags options: # # Normal Use # diff --git a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb index 37319cca1b..7f7776e9c0 100644 --- a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb +++ b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb @@ -2,9 +2,11 @@ require 'action_view/helpers/javascript_helper' require 'active_support/json' module ActionView + # = Action View Scriptaculous Helpers module Helpers - # Provides a set of helpers for calling Scriptaculous JavaScript - # functions, including those which create Ajax controls and visual effects. + # Provides a set of helpers for calling Scriptaculous[http://script.aculo.us/] + # JavaScript functions, including those which create Ajax controls and visual + # effects. # # To be able to use these helpers, you must include the Prototype # JavaScript framework and the Scriptaculous JavaScript library in your @@ -12,6 +14,7 @@ module ActionView # for more information on including the necessary JavaScript. # # The Scriptaculous helpers' behavior can be tweaked with various options. + # # See the documentation at http://script.aculo.us for more information on # using these helpers in your application. module ScriptaculousHelper diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 66277f79fe..d4e8b3d587 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -2,6 +2,7 @@ require 'active_support/core_ext/object/blank' require 'set' module ActionView + # = Action View Tag Helpers module Helpers #:nodoc: # Provides methods to generate HTML tags programmatically when you can't use # a Builder. By default, they output XHTML compliant tags. diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index ccc9156777..9afa989453 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -3,6 +3,7 @@ require 'active_support/core_ext/string/filters' require 'action_view/helpers/tag_helper' module ActionView + # = Action View Text Helpers module Helpers #:nodoc: # The TextHelper module provides a set of methods for filtering, formatting # and transforming strings, which can reduce the amount of inline Ruby code in diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index 0c8829b0b8..dac9c28ab7 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -1,21 +1,28 @@ require 'action_view/helpers/tag_helper' module ActionView + # = Action View Translation Helpers module Helpers module TranslationHelper - # Delegates to I18n#translate but also performs three additional functions. First, it'll catch MissingTranslationData exceptions - # and turn them into inline spans that contains the missing key, such that you can see in a view what is missing where. + # Delegates to I18n#translate but also performs three additional functions. + # First, it'll catch MissingTranslationData exceptions and turn them into + # inline spans that contains the missing key, such that you can see in a + # view what is missing where. # - # Second, it'll scope the key by the current partial if the key starts with a period. So if you call translate(".foo") from the - # people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo"). This makes it less repetitive - # to translate many keys within the same partials and gives you a simple framework for scoping them consistently. If you don't - # prepend the key with a period, nothing is converted. + # Second, it'll scope the key by the current partial if the key starts + # with a period. So if you call translate(".foo") from the + # people/index.html.erb template, you'll actually be calling + # I18n.translate("people.index.foo"). This makes it less repetitive + # to translate many keys within the same partials and gives you a simple framework + # for scoping them consistently. If you don't prepend the key with a period, + # nothing is converted. # - # Third, it'll mark the translation as safe HTML if the key has the suffix "_html" or the last element of the key is the word - # "html". For example, calling translate("footer_html") or translate("footer.html") will return a safe HTML string that won't - # be escaped by other HTML helper methods. This naming convention helps to identify translations that include HTML tags so that + # Third, it'll mark the translation as safe HTML if the key has the suffix + # "_html" or the last element of the key is the word "html". For example, + # calling translate("footer_html") or translate("footer.html") will return + # a safe HTML string that won't be escaped by other HTML helper methods. This + # naming convention helps to identify translations that include HTML tags so that # you know what kind of output to expect when you call translate in a template. - def translate(key, options = {}) translation = I18n.translate(scope_key_by_partial(key), options.merge!(:raise => true)) if html_safe_translation_key?(key) && translation.respond_to?(:html_safe) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 210f148c02..bcfa6a68d7 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -4,6 +4,7 @@ require 'active_support/core_ext/hash/keys' require 'action_dispatch' module ActionView + # = Action View URL Helpers module Helpers #:nodoc: # Provides a set of methods for making links and getting URLs that # depend on the routing subsystem (see ActionDispatch::Routing). -- cgit v1.2.3 From f09736bc0f726483e9de4288b2449f3b2f3b76ab Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 22:57:50 +0430 Subject: Added title to some other files in actionpack/lib/action_view --- actionpack/lib/action_view/lookup_context.rb | 2 ++ actionpack/lib/action_view/paths.rb | 1 + actionpack/lib/action_view/railtie.rb | 1 + actionpack/lib/action_view/render/layouts.rb | 1 + actionpack/lib/action_view/render/partials.rb | 2 ++ actionpack/lib/action_view/render/rendering.rb | 1 + actionpack/lib/action_view/template.rb | 1 + 7 files changed, 9 insertions(+) diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 823226cb9c..3ea8b86af1 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -2,6 +2,8 @@ require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' module ActionView + # = Action View Lookup Context + # # LookupContext is the object responsible to hold all information required to lookup # templates, i.e. view paths and details. The LookupContext is also responsible to # generate a key, given to view paths, used in the resolver cache lookup. Since diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 7f5e5d11b8..9857d688d2 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -1,4 +1,5 @@ module ActionView #:nodoc: + # = Action View PathSet class PathSet < Array #:nodoc: %w(initialize << concat insert push unshift).each do |method| class_eval <<-METHOD, __FILE__, __LINE__ + 1 diff --git a/actionpack/lib/action_view/railtie.rb b/actionpack/lib/action_view/railtie.rb index c606a71e18..e8ea15f47c 100644 --- a/actionpack/lib/action_view/railtie.rb +++ b/actionpack/lib/action_view/railtie.rb @@ -2,6 +2,7 @@ require "action_view" require "rails" module ActionView + # = Action View Railtie class Railtie < Rails::Railtie config.action_view = ActiveSupport::OrderedOptions.new diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb index 1f837b37e2..a474783a20 100644 --- a/actionpack/lib/action_view/render/layouts.rb +++ b/actionpack/lib/action_view/render/layouts.rb @@ -1,4 +1,5 @@ module ActionView + # = Action View Layouts module Layouts # Returns the contents that are yielded to a layout, given a name or a block. # diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 85f67d4f14..a2c191c580 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -1,6 +1,8 @@ require 'active_support/core_ext/object/blank' module ActionView + # = Action View Partials + # # There's also a convenience method for rendering sub templates within the current controller that depends on a # single object (we call this kind of sub templates for partials). It relies on the fact that partials should # follow the naming convention of being prefixed with an underscore -- as to separate them from regular diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 4d35296932..cb39621d6b 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/object/try' module ActionView + # Action View Rendering module Rendering # Returns the result of a render that's dictated by the options hash. The primary options are: # diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 53ad24fdc6..c00557209b 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -3,6 +3,7 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/kernel/singleton_class' module ActionView + # = Action View Template class Template extend ActiveSupport::Autoload -- cgit v1.2.3 From 35e3f72af29a33189a46a4b5ada84768b87e0ef2 Mon Sep 17 00:00:00 2001 From: Rizwan Reza Date: Wed, 16 Jun 2010 23:53:10 +0430 Subject: Adds backslash to scope for cross-references. --- activerecord/lib/active_record/named_scope.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 096b9da402..47eef9535e 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -19,7 +19,7 @@ module ActiveRecord # fruits = fruits.where(:colour => 'red') if options[:red_only] # fruits = fruits.limit(10) if limited? # - # Anonymous scopes tend to be useful when procedurally generating complex + # Anonymous \scopes tend to be useful when procedurally generating complex # queries, where passing intermediate values (scopes) around as first-class # objects is convenient. # -- cgit v1.2.3 From c1ff781001af157c0d5ea5ac64e1fa17d47fe1f1 Mon Sep 17 00:00:00 2001 From: Bryan Woods Date: Wed, 16 Jun 2010 15:50:32 -0400 Subject: Guides: renaming to active_record_validations_callbacks for consistency and updating links to reflect new path --- .../guides/source/active_record_basics.textile | 4 +- .../active_record_validations_callbacks.textile | 1170 ++++++++++++++++++++ .../activerecord_validations_callbacks.textile | 1170 -------------------- railties/guides/source/form_helpers.textile | 2 +- railties/guides/source/index.html.erb | 2 +- railties/guides/source/layout.html.erb | 2 +- 6 files changed, 1175 insertions(+), 1175 deletions(-) create mode 100644 railties/guides/source/active_record_validations_callbacks.textile delete mode 100644 railties/guides/source/activerecord_validations_callbacks.textile diff --git a/railties/guides/source/active_record_basics.textile b/railties/guides/source/active_record_basics.textile index e32898129f..e6ef2cdd20 100644 --- a/railties/guides/source/active_record_basics.textile +++ b/railties/guides/source/active_record_basics.textile @@ -207,11 +207,11 @@ Likewise, once retrieved an Active Record object can be destroyed which removes h3. Validations -Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#validations-overview. +Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#validations-overview. h3. Callbacks -Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#callbacks-overview. +Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#callbacks-overview. h3. Migrations diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile new file mode 100644 index 0000000000..cfd4ae55cc --- /dev/null +++ b/railties/guides/source/active_record_validations_callbacks.textile @@ -0,0 +1,1170 @@ +h2. Active Record Validations and Callbacks + +This guide teaches you how to hook into the lifecycle of your Active Record objects. You will learn how to validate the state of objects before they go into the database, and how to perform custom operations at certain points in the object lifecycle. + +After reading this guide and trying out the presented concepts, we hope that you'll be able to: + +* Understand the lifecycle of Active Record objects +* Use the built-in Active Record validation helpers +* Create your own custom validation methods +* Work with the error messages generated by the validation process +* Create callback methods that respond to events in the object lifecycle +* Create special classes that encapsulate common behavior for your callbacks +* Create Observers that respond to lifecycle events outside of the original class + +endprologue. + +h3. The Object Lifecycle + +During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this object lifecycle so that you can control your application and its data. + +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. + +h3. Validations Overview + +Before you dive into the detail of validations in Rails, you should understand a bit about how validations fit into the big picture. + +h4. Why Use Validations? + +Validations are used to ensure that only valid data is saved into your database. For example, it may be important to your application to ensure that every user provides a valid email address and mailing address. + +There are several ways to validate data before it is saved into your database, including native database constraints, client-side validations, controller-level validations, and model-level validations. + +* 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. +* 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. +* 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. +* 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. + +h4. When Does Validation Happen? + +There are two kinds of Active Record objects: those that correspond to a row inside your database and those that do not. When you create a fresh object, for example using the +new+ method, that object does not belong to the database yet. Once you call +save+ upon that object it will be saved into the appropriate database table. Active Record uses the +new_record?+ instance method to determine whether an object is already in the database or not. Consider the following simple Active Record class: + + +class Person < ActiveRecord::Base +end + + +We can see how it works by looking at some +rails console+ output: + + +>> p = Person.new(:name => "John Doe") +=> # +>> p.new_record? +=> true +>> p.save +=> true +>> p.new_record? +=> false + + +Creating and saving a new record will send an SQL +INSERT+ operation to the database. Updating an existing record will send an SQL +UPDATE+ operation instead. Validations are typically run before these commands are sent to the database. If any validations fail, the object will be marked as invalid and Active Record will not perform the +INSERT+ or +UPDATE+ operation. This helps to avoid storing an invalid object in the database. You can choose to have specific validations run when an object is created, saved, or updated. + +CAUTION: There are many ways to change the state of an object in the database. Some methods will trigger validations, but some will not. This means that it's possible to save an object in the database in an invalid state if you aren't careful. + +The following methods trigger validations, and will save the object to the database only if the object is valid: + +* +create+ +* +create!+ +* +save+ +* +save!+ +* +update+ +* +update_attributes+ +* +update_attributes!+ + +The bang versions (e.g. +save!+) raise an exception if the record is invalid. The non-bang versions don't: +save+ and +update_attributes+ return +false+, +create+ and +update+ just return the objects. + +h4. Skipping Validations + +The following methods skip validations, and will save the object to the database regardless of its validity. They should be used with caution. + +* +decrement!+ +* +decrement_counter+ +* +increment!+ +* +increment_counter+ +* +toggle!+ +* +update_all+ +* +update_attribute+ +* +update_counters+ + +Note that +save+ also has the ability to skip validations if passed +false+ as argument. This technique should be used with caution. + +* +save(false)+ + +h4. +valid?+ and +invalid?+ + +To verify whether or not an object is valid, Rails uses the +valid?+ method. You can also use this method on your own. +valid?+ triggers your validations and returns true if no errors were added to the object, and false otherwise. + + +class Person < ActiveRecord::Base + validates_presence_of :name +end + +Person.create(:name => "John Doe").valid? # => true +Person.create(:name => nil).valid? # => false + + +When Active Record is performing validations, any errors found can be accessed through the +errors+ instance method. By definition an object is valid if this collection is empty after running validations. + +Note that an object instantiated with +new+ will not report errors even if it's technically invalid, because validations are not run when using +new+. + + +class Person < ActiveRecord::Base + validates_presence_of :name +end + +>> p = Person.new +=> # +>> p.errors +=> {} + +>> p.valid? +=> false +>> p.errors +=> {:name=>["can't be blank"]} + +>> p = Person.create +=> # +>> p.errors +=> {:name=>["can't be blank"]} + +>> p.save +=> false + +>> p.save! +=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank + +>> Person.create! +=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank + + ++invalid?+ is simply the inverse of +valid?+. +invalid?+ triggers your validations and returns true if any errors were added to the object, and false otherwise. + +h4(#validations_overview-errors). +errors[]+ + +To verify whether or not a particular attribute of an object is valid, you can use +errors[:attribute]+ that returns an array with all attribute errors, when there are no errors on the specified attribute, an empty array is returned. + +This method is only useful _after_ validations have been run, because it only inspects the errors collection and does not trigger validations itself. It's different from the +ActiveRecord::Base#invalid?+ method explained above because it doesn't verify the validity of the object as a whole. It only checks to see whether there are errors found on an individual attribute of the object. + + +class Person < ActiveRecord::Base + validates_presence_of :name +end + +>> Person.new.errors[:name].any? # => false +>> Person.create.errors[:name].any? # => true + + +We'll cover validation errors in greater depth in the "Working with Validation Errors":#working-with-validation-errors section. For now, let's turn to the built-in validation helpers that Rails provides by default. + +h3. Validation Helpers + +Active Record offers many pre-defined validation helpers that you can use directly inside your class definitions. These helpers provide common validation rules. Every time a validation fails, an error message is added to the object's +errors+ collection, and this message is associated with the field being validated. + +Each helper accepts an arbitrary number of attribute names, so with a single line of code you can add the same kind of validation to several attributes. + +All of them accept the +:on+ and +:message+ options, which define when the validation should be run and what message should be added to the +errors+ collection if it fails, respectively. The +:on+ option takes one of the values +:save+ (the default), +:create+ or +:update+. There is a default error message for each one of the validation helpers. These messages are used when the +:message+ option isn't specified. Let's take a look at each one of the available helpers. + +h4. +validates_acceptance_of+ + +Validates that a checkbox on the user interface was checked when a form was submitted. This is typically used when the user needs to agree to your application's terms of service, confirm reading some text, or any similar concept. This validation is very specific to web applications and this 'acceptance' does not need to be recorded anywhere in your database (if you don't have a field for it, the helper will just create a virtual attribute). + + +class Person < ActiveRecord::Base + validates_acceptance_of :terms_of_service +end + + +The default error message for +validates_acceptance_of+ is "_must be accepted_". + ++validates_acceptance_of+ can receive an +:accept+ option, which determines the value that will be considered acceptance. It defaults to "1", but you can change this. + + +class Person < ActiveRecord::Base + validates_acceptance_of :terms_of_service, :accept => 'yes' +end + + +h4. +validates_associated+ + +You should use this helper when your model has associations with other models and they also need to be validated. When you try to save your object, +valid?+ will be called upon each one of the associated objects. + + +class Library < ActiveRecord::Base + has_many :books + validates_associated :books +end + + +This validation will work with all of the association types. + +CAUTION: Don't use +validates_associated+ on both ends of your associations, they would call each other in an infinite loop. + +The default error message for +validates_associated+ is "_is invalid_". Note that each associated object will contain its own +errors+ collection; errors do not bubble up to the calling model. + +h4. +validates_confirmation_of+ + +You should use this helper when you have two text fields that should receive exactly the same content. For example, you may want to confirm an email address or a password. This validation creates a virtual attribute whose name is the name of the field that has to be confirmed with "_confirmation" appended. + + +class Person < ActiveRecord::Base + validates_confirmation_of :email +end + + +In your view template you could use something like + + +<%= text_field :person, :email %> +<%= text_field :person, :email_confirmation %> + + +This check is performed only if +email_confirmation+ is not +nil+. To require confirmation, make sure to add a presence check for the confirmation attribute (we'll take a look at +validates_presence_of+ later on this guide): + + +class Person < ActiveRecord::Base + validates_confirmation_of :email + validates_presence_of :email_confirmation +end + + +The default error message for +validates_confirmation_of+ is "_doesn't match confirmation_". + +h4. +validates_exclusion_of+ + +This helper validates that the attributes' values are not included in a given set. In fact, this set can be any enumerable object. + + +class Account < ActiveRecord::Base + validates_exclusion_of :subdomain, :in => %w(www), + :message => "Subdomain %{value} is reserved." +end + + +The +validates_exclusion_of+ helper has an option +:in+ that receives the set of values that will not be accepted for the validated attributes. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. This example uses the +:message+ option to show how you can include the attribute's value. + +The default error message for +validates_exclusion_of+ is "_is reserved_". + +h4. +validates_format_of+ + +This helper validates the attributes' values by testing whether they match a given regular expression, which is specified using the +:with+ option. + + +class Product < ActiveRecord::Base + validates_format_of :legacy_code, :with => /\A[a-zA-Z]+\z/, + :message => "Only letters allowed" +end + + +The default error message for +validates_format_of+ is "_is invalid_". + +h4. +validates_inclusion_of+ + +This helper validates that the attributes' values are included in a given set. In fact, this set can be any enumerable object. + + +class Coffee < ActiveRecord::Base + validates_inclusion_of :size, :in => %w(small medium large), + :message => "%{value} is not a valid size" +end + + +The +validates_inclusion_of+ helper has an option +:in+ that receives the set of values that will be accepted. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. The previous example uses the +:message+ option to show how you can include the attribute's value. + +The default error message for +validates_inclusion_of+ is "_is not included in the list_". + +h4. +validates_length_of+ + +This helper validates the length of the attributes' values. It provides a variety of options, so you can specify length constraints in different ways: + + +class Person < ActiveRecord::Base + validates_length_of :name, :minimum => 2 + validates_length_of :bio, :maximum => 500 + validates_length_of :password, :in => 6..20 + validates_length_of :registration_number, :is => 6 +end + + +The possible length constraint options are: + +* +:minimum+ - The attribute cannot have less than the specified length. +* +:maximum+ - The attribute cannot have more than the specified length. +* +:in+ (or +:within+) - The attribute length must be included in a given interval. The value for this option must be a range. +* +:is+ - The attribute length must be equal to the given value. + +The default error messages depend on the type of length validation being performed. You can personalize these messages using the +:wrong_length+, +:too_long+, and +:too_short+ options and %{count} as a placeholder for the number corresponding to the length constraint being used. You can still use the +:message+ option to specify an error message. + + +class Person < ActiveRecord::Base + validates_length_of :bio, :maximum => 1000, + :too_long => "%{count} characters is the maximum allowed" +end + + +This helper counts characters by default, but you can split the value in a different way using the +:tokenizer+ option: + + +class Essay < ActiveRecord::Base + validates_length_of :content, + :minimum => 300, + :maximum => 400, + :tokenizer => lambda { |str| str.scan(/\w+/) }, + :too_short => "must have at least %{count} words", + :too_long => "must have at most %{count} words" +end + + +The +validates_size_of+ helper is an alias for +validates_length_of+. + +h4. +validates_numericality_of+ + +This helper validates that your attributes have only numeric values. By default, it will match an optional sign followed by an integral or floating point number. To specify that only integral numbers are allowed set +:only_integer+ to true. + +If you set +:only_integer+ to +true+, then it will use the + + +/\A[+-]?\d+\Z/ + + +regular expression to validate the attribute's value. Otherwise, it will try to convert the value to a number using +Float+. + +WARNING. Note that the regular expression above allows a trailing newline character. + + +class Player < ActiveRecord::Base + validates_numericality_of :points + validates_numericality_of :games_played, :only_integer => true +end + + +Besides +:only_integer+, the +validates_numericality_of+ helper also accepts the following options to add constraints to acceptable values: + +* +:greater_than+ - Specifies the value must be greater than the supplied value. The default error message for this option is "_must be greater than %{count}_". +* +:greater_than_or_equal_to+ - Specifies the value must be greater than or equal to the supplied value. The default error message for this option is "_must be greater than or equal to %{count}_". +* +:equal_to+ - Specifies the value must be equal to the supplied value. The default error message for this option is "_must be equal to %{count}_". +* +:less_than+ - Specifies the value must be less than the supplied value. The default error message for this option is "_must be less than %{count}_". +* +:less_than_or_equal_to+ - Specifies the value must be less than or equal the supplied value. The default error message for this option is "_must be less than or equal to %{count}_". +* +:odd+ - Specifies the value must be an odd number if set to true. The default error message for this option is "_must be odd_". +* +:even+ - Specifies the value must be an even number if set to true. The default error message for this option is "_must be even_". + +The default error message for +validates_numericality_of+ is "_is not a number_". + +h4. +validates_presence_of+ + +This helper validates that the specified attributes are not empty. It uses the +blank?+ method to check if the value is either +nil+ or a blank string, that is, a string that is either empty or consists of whitespace. + + +class Person < ActiveRecord::Base + validates_presence_of :name, :login, :email +end + + +If you want to be sure that an association is present, you'll need to test whether the foreign key used to map the association is present, and not the associated object itself. + + +class LineItem < ActiveRecord::Base + belongs_to :order + validates_presence_of :order_id +end + + +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]+. + +The default error message for +validates_presence_of+ is "_can't be empty_". + +h4. +validates_uniqueness_of+ + +This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create a unique index in your database. + + +class Account < ActiveRecord::Base + validates_uniqueness_of :email +end + + +The validation happens by performing a SQL query into the model's table, searching for an existing record with the same value in that attribute. + +There is a +:scope+ option that you can use to specify other attributes that are used to limit the uniqueness check: + + +class Holiday < ActiveRecord::Base + validates_uniqueness_of :name, :scope => :year, + :message => "should happen once per year" +end + + +There is also a +:case_sensitive+ option that you can use to define whether the uniqueness constraint will be case sensitive or not. This option defaults to true. + + +class Person < ActiveRecord::Base + validates_uniqueness_of :name, :case_sensitive => false +end + + +WARNING. Note that some databases are configured to perform case-insensitive searches anyway. + +The default error message for +validates_uniqueness_of+ is "_has already been taken_". + +h4. +validates_with+ + +This helper passes the record to a separate class for validation. + + +class Person < ActiveRecord::Base + validates_with GoodnessValidator +end + +class GoodnessValidator < ActiveRecord::Validator + def validate + if record.first_name == "Evil" + record.errors[:base] << "This person is evil" + end + end +end + + +The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class. + +The validator class has two attributes by default: + +* +record+ - the record to be validated +* +options+ - the extra options that were passed to +validates_with+ + +Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+: + + +class Person < ActiveRecord::Base + validates_with GoodnessValidator, :fields => [:first_name, :last_name] +end + +class GoodnessValidator < ActiveRecord::Validator + def validate + if options[:fields].any?{|field| record.send(field) == "Evil" } + record.errors[:base] << "This person is evil" + end + end +end + + +h4. +validates_each+ + +This helper validates attributes against a block. It doesn't have a predefined validation function. You should create one using a block, and every attribute passed to +validates_each+ will be tested against it. In the following example, we don't want names and surnames to begin with lower case. + + +class Person < ActiveRecord::Base + validates_each :name, :surname do |model, attr, value| + model.errors.add(attr, 'must start with upper case') if value =~ /\A[a-z]/ + end +end + + +The block receives the model, the attribute's name and the attribute's value. You can do anything you like to check for valid data within the block. If your validation fails, you can add an error message to the model, therefore making it invalid. + +h3. Common Validation Options + +There are some common options that all the validation helpers can use. Here they are, except for the +:if+ and +:unless+ options, which are discussed later in "Conditional Validation":#conditional-validation. + +h4. +:allow_nil+ + +The +:allow_nil+ option skips the validation when the value being validated is +nil+. Using +:allow_nil+ with +validates_presence_of+ allows for +nil+, but any other +blank?+ value will still be rejected. + + +class Coffee < ActiveRecord::Base + validates_inclusion_of :size, :in => %w(small medium large), + :message => "%{value} is not a valid size", :allow_nil => true +end + + +h4. +:allow_blank+ + +The +:allow_blank+ option is similar to the +:allow_nil+ option. This option will let validation pass if the attribute's value is +blank?+, like +nil+ or an empty string for example. + + +class Topic < ActiveRecord::Base + validates_length_of :title, :is => 5, :allow_blank => true +end + +Topic.create("title" => "").valid? # => true +Topic.create("title" => nil).valid? # => true + + +h4. +:message+ + +As you've already seen, the +:message+ option lets you specify the message that will be added to the +errors+ collection when validation fails. When this option is not used, Active Record will use the respective default error message for each validation helper. + +h4. +:on+ + +The +:on+ option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use +:on => :create+ to run the validation only when a new record is created or +:on => :update+ to run the validation only when a record is updated. + + +class Person < ActiveRecord::Base + # it will be possible to update email with a duplicated value + validates_uniqueness_of :email, :on => :create + + # it will be possible to create the record with a non-numerical age + validates_numericality_of :age, :on => :update + + # the default (validates on both create and update) + validates_presence_of :name, :on => :save +end + + +h3. Conditional Validation + +Sometimes it will make sense to validate an object just when a given predicate is satisfied. You can do that by using the +:if+ and +:unless+ options, which can take a symbol, a string or a +Proc+. You may use the +:if+ option when you want to specify when the validation *should* happen. If you want to specify when the validation *should not* happen, then you may use the +:unless+ option. + +h4. Using a Symbol with +:if+ and +:unless+ + +You can associate the +:if+ and +:unless+ options with a symbol corresponding to the name of a method that will get called right before validation happens. This is the most commonly used option. + + +class Order < ActiveRecord::Base + validates_presence_of :card_number, :if => :paid_with_card? + + def paid_with_card? + payment_type == "card" + end +end + + +h4. Using a String with +:if+ and +:unless+ + +You can also use a string that will be evaluated using +eval+ and needs to contain valid Ruby code. You should use this option only when the string represents a really short condition. + + +class Person < ActiveRecord::Base + validates_presence_of :surname, :if => "name.nil?" +end + + +h4. Using a Proc with +:if+ and +:unless+ + +Finally, it's possible to associate +:if+ and +:unless+ with a +Proc+ object which will be called. Using a +Proc+ object gives you the ability to write an inline condition instead of a separate method. This option is best suited for one-liners. + + +class Account < ActiveRecord::Base + validates_confirmation_of :password, + :unless => Proc.new { |a| a.password.blank? } +end + + +h3. Creating Custom Validation Methods + +When the built-in validation helpers are not enough for your needs, you can write your own validation methods. + +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. + +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. + + +class Invoice < ActiveRecord::Base + validate :expiration_date_cannot_be_in_the_past, + :discount_cannot_be_greater_than_total_value + + def expiration_date_cannot_be_in_the_past + errors.add(:expiration_date, "can't be in the past") if + !expiration_date.blank? and expiration_date < Date.today + end + + def discount_cannot_be_greater_than_total_value + errors.add(:discount, "can't be greater than total value") if + discount > total_value + end +end + + +You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find it useful to express that a certain field corresponds to a set of choices: + + +ActiveRecord::Base.class_eval do + def self.validates_as_choice(attr_name, n, options={}) + validates_inclusion_of attr_name, {:in => 1..n}.merge(options) + end +end + + +Simply reopen +ActiveRecord::Base+ and define a class method like that. You'd typically put this code somewhere in +config/initializers+. You can use this helper like this: + + +class Movie < ActiveRecord::Base + validates_as_choice :rating, 5 +end + + +h3. Working with Validation Errors + +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. + +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. + +h4(#working_with_validation_errors-errors). +errors+ + +Returns an OrderedHash with all errors. Each key is the attribute name and the value is an array of strings with all errors. + + +class Person < ActiveRecord::Base + validates_presence_of :name + validates_length_of :name, :minimum => 3 +end + +person = Person.new +person.valid? # => false +person.errors + # => {:name => ["can't be blank", "is too short (minimum is 3 characters)"]} + +person = Person.new(:name => "John Doe") +person.valid? # => true +person.errors # => [] + + +h4(#working_with_validation_errors-errors-2). +errors[]+ + ++errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute, it returns an empty array. + + +class Person < ActiveRecord::Base + validates_presence_of :name + validates_length_of :name, :minimum => 3 +end + +person = Person.new(:name => "John Doe") +person.valid? # => true +person.errors[:name] # => [] + +person = Person.new(:name => "JD") +person.valid? # => false +person.errors[:name] # => ["is too short (minimum is 3 characters)"] + +person = Person.new +person.valid? # => false +person.errors[:name] + # => ["can't be blank", "is too short (minimum is 3 characters)"] + + +h4. +errors.add+ + +The +add+ method lets you manually add messages that are related to particular attributes. You can use the +errors.full_messages+ or +errors.to_a+ methods to view the messages in the form they might be displayed to a user. Those particular messages get the attribute name prepended (and capitalized). +add+ receives the name of the attribute you want to add the message to, and the message itself. + + +class Person < ActiveRecord::Base + def a_method_used_for_validation_purposes + errors.add(:name, "cannot contain the characters !@#%*()_-+=") + end +end + +person = Person.create(:name => "!@#") + +person.errors[:name] + # => ["cannot contain the characters !@#%*()_-+="] + +person.errors.full_messages + # => ["Name cannot contain the characters !@#%*()_-+="] + + +Another way to do this is using +[]=+ setter + + + class Person < ActiveRecord::Base + def a_method_used_for_validation_purposes + errors[:name] = "cannot contain the characters !@#%*()_-+=" + end + end + + person = Person.create(:name => "!@#") + + person.errors[:name] + # => ["cannot contain the characters !@#%*()_-+="] + + person.errors.to_a + # => ["Name cannot contain the characters !@#%*()_-+="] + + +h4. +errors[:base]+ + +You can add error messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since +errors[:base]+ is an array, you can simply add a string to the array and uses it as the error message. + + +class Person < ActiveRecord::Base + def a_method_used_for_validation_purposes + errors[:base] << "This person is invalid because ..." + end +end + + + + +h4. +errors.clear+ + +The +clear+ method is used when you intentionally want to clear all the messages in the +errors+ collection. Of course, calling +errors.clear+ upon an invalid object won't actually make it valid: the +errors+ collection will now be empty, but the next time you call +valid?+ or any method that tries to save this object to the database, the validations will run again. If any of the validations fail, the +errors+ collection will be filled again. + + +class Person < ActiveRecord::Base + validates_presence_of :name + validates_length_of :name, :minimum => 3 +end + +person = Person.new +person.valid? # => false +person.errors[:name] + # => ["can't be blank", "is too short (minimum is 3 characters)"] + +person.errors.clear +person.errors.empty? # => true + +p.save # => false + +p.errors[:name] + # => ["can't be blank", "is too short (minimum is 3 characters)"] + + +h4. +errors.size+ + +The +size+ method returns the total number of error messages for the object. + + +class Person < ActiveRecord::Base + validates_presence_of :name + validates_length_of :name, :minimum => 3 + validates_presence_of :email +end + +person = Person.new +person.valid? # => false +person.errors.size # => 3 + +person = Person.new(:name => "Andrea", :email => "andrea@example.com") +person.valid? # => true +person.errors.size # => 0 + + +h3. Displaying Validation Errors in the View + +Rails provides built-in helpers to display the error messages of your models in your view templates. + +h4. +error_messages+ and +error_messages_for+ + +When creating a form with the +form_for+ helper, you can use the +error_messages+ method on the form builder to render all failed validation messages for the current model instance. + + +class Product < ActiveRecord::Base + validates_presence_of :description, :value + validates_numericality_of :value, :allow_nil => true +end + + + +<%= form_for(@product) do |f| %> + <%= f.error_messages %> +

+ <%= f.label :description %>
+ <%= f.text_field :description %> +

+

+ <%= f.label :value %>
+ <%= f.text_field :value %> +

+

+ <%= f.submit "Create" %> +

+<% end %> +
+ +To get the idea, if you submit the form with empty fields you typically get this back, though styles are indeed missing by default: + +!images/error_messages.png(Error messages)! + +You can also use the +error_messages_for+ helper to display the error messages of a model assigned to a view template. It's very similar to the previous example and will achieve exactly the same result. + + +<%= error_messages_for :product %> + + +The displayed text for each error message will always be formed by the capitalized name of the attribute that holds the error, followed by the error message itself. + +Both the +form.error_messages+ and the +error_messages_for+ helpers accept options that let you customize the +div+ element that holds the messages, changing the header text, the message below the header text and the tag used for the element that defines the header. + + +<%= f.error_messages :header_message => "Invalid product!", + :message => "You'll need to fix the following fields:", + :header_tag => :h3 %> + + +Which results in the following content: + +!images/customized_error_messages.png(Customized error messages)! + +If you pass +nil+ to any of these options, it will get rid of the respective section of the +div+. + +h4. Customizing the Error Messages CSS + +The selectors to customize the style of error messages are: + +* +.fieldWithErrors+ - Style for the form fields and labels with errors. +* +#errorExplanation+ - Style for the +div+ element with the error messages. +* +#errorExplanation h2+ - Style for the header of the +div+ element. +* +#errorExplanation p+ - Style for the paragraph that holds the message that appears right below the header of the +div+ element. +* +#errorExplanation ul li+ - Style for the list items with individual error messages. + +Scaffolding for example generates +public/stylesheets/scaffold.css+, which defines the red-based style you saw above. + +The name of the class and the id can be changed with the +:class+ and +:id+ options, accepted by both helpers. + +h4. Customizing the Error Messages HTML + +By default, form fields with errors are displayed enclosed by a +div+ element with the +fieldWithErrors+ CSS class. However, it's possible to override that. + +The way form fields with errors are treated is defined by +ActionView::Base.field_error_proc+. This is a +Proc+ that receives two parameters: + +* A string with the HTML tag +* An instance of +ActionView::Helpers::InstanceTag+. + +Here is a simple example where we change the Rails behaviour to always display the error messages in front of each of the form fields with errors. The error messages will be enclosed by a +span+ element with a +validation-error+ CSS class. There will be no +div+ element enclosing the +input+ element, so we get rid of that red border around the text field. You can use the +validation-error+ CSS class to style it anyway you want. + + +ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| + if instance.error_message.kind_of?(Array) + %(#{html_tag}  + #{instance.error_message.join(',')}) + else + %(#{html_tag}  + #{instance.error_message}) + end +end + + +This will result in something like the following: + +!images/validation_error_messages.png(Validation error messages)! + +h3. Callbacks Overview + +Callbacks are methods that get called at certain moments of an object's lifecycle. With callbacks it's possible to write code that will run whenever an Active Record object is created, saved, updated, deleted, validated, or loaded from the database. + +h4. Callback Registration + +In order to use the available callbacks, you need to register them. You can do that by implementing them as ordinary methods, and then using a macro-style class method to register them as callbacks. + + +class User < ActiveRecord::Base + validates_presence_of :login, :email + + before_validation :ensure_login_has_a_value + + protected + def ensure_login_has_a_value + if login.nil? + self.login = email unless email.blank? + end + end +end + + +The macro-style class methods can also receive a block. Consider using this style if the code inside your block is so short that it fits in just one line. + + +class User < ActiveRecord::Base + validates_presence_of :login, :email + + before_create {|user| user.name = user.login.capitalize + if user.name.blank?} +end + + +It's considered good practice to declare callback methods as being protected or private. If left public, they can be called from outside of the model and violate the principle of object encapsulation. + +h3. Available Callbacks + +Here is a list with all the available Active Record callbacks, listed in the same order in which they will get called during the respective operations: + +h4. Creating an Object + +* +before_validation+ +* +after_validation+ +* +before_save+ +* +after_save+ +* +before_create+ +* +around_create+ +* +after_create+ + +h4. Updating an Object + +* +before_validation+ +* +after_validation+ +* +before_save+ +* +after_save+ +* +before_update+ +* +around_update+ +* +after_update+ + +h4. Destroying an Object + +* +before_destroy+ +* +after_destroy+ +* +around_destroy+ + +WARNING. +after_save+ runs both on create and update, but always _after_ the more specific callbacks +after_create+ and +after_update+, no matter the order in which the macro calls were executed. + +h4. +after_initialize+ and +after_find+ + +The +after_initialize+ callback will be called whenever an Active Record object is instantiated, either by directly using +new+ or when a record is loaded from the database. It can be useful to avoid the need to directly override your Active Record +initialize+ method. + +The +after_find+ callback will be called whenever Active Record loads a record from the database. +after_find+ is called before +after_initialize+ if both are defined. + +The +after_initialize+ and +after_find+ callbacks are a bit different from the others. They have no +before_*+ counterparts, and the only way to register them is by defining them as regular methods. If you try to register +after_initialize+ or +after_find+ using macro-style class methods, they will just be ignored. This behaviour is due to performance reasons, since +after_initialize+ and +after_find+ will both be called for each record found in the database, significantly slowing down the queries. + + +class User < ActiveRecord::Base + def after_initialize + puts "You have initialized an object!" + end + + def after_find + puts "You have found an object!" + end +end + +>> User.new +You have initialized an object! +=> # + +>> User.first +You have found an object! +You have initialized an object! +=> # + + +h3. Running Callbacks + +The following methods trigger callbacks: + +* +create+ +* +create!+ +* +decrement!+ +* +destroy+ +* +destroy_all+ +* +increment!+ +* +save+ +* +save!+ +* +save(false)+ +* +toggle!+ +* +update+ +* +update_attribute+ +* +update_attributes+ +* +update_attributes!+ +* +valid?+ + +Additionally, the +after_find+ callback is triggered by the following finder methods: + +* +all+ +* +first+ +* +find+ +* +find_all_by_attribute+ +* +find_by_attribute+ +* +find_by_attribute!+ +* +last+ + +The +after_initialize+ callback is triggered every time a new object of the class is initialized. + +h3. Skipping Callbacks + +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. + +* +decrement+ +* +decrement_counter+ +* +delete+ +* +delete_all+ +* +find_by_sql+ +* +increment+ +* +increment_counter+ +* +toggle+ +* +update_all+ +* +update_counters+ + +h3. Halting Execution + +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. + +The whole callback chain is wrapped in a transaction. If any before callback method returns exactly +false+ or raises an exception the execution chain gets halted and a ROLLBACK is issued. After callbacks can only accomplish that by raising an exception. + +WARNING. Raising an arbitrary exception may break code that expects +save+ and friends not to fail like that. The +ActiveRecord::Rollback+ exception is thought precisely to tell Active Record a rollback is going on. That one is internally captured but not reraised. + +h3. Relational Callbacks + +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. + + +class User < ActiveRecord::Base + has_many :posts, :dependent => :destroy +end + +class Post < ActiveRecord::Base + after_destroy :log_destroy_action + + def log_destroy_action + puts 'Post destroyed' + end +end + +>> user = User.first +=> # +>> user.posts.create! +=> # +>> user.destroy +Post destroyed +=> # + + +h3. Conditional Callbacks + +Like in validations, we can also make our callbacks conditional, calling them only when a given predicate is satisfied. You can do that by using the +:if+ and +:unless+ options, which can take a symbol, a string or a +Proc+. You may use the +:if+ option when you want to specify when the callback *should* get called. If you want to specify when the callback *should not* be called, then you may use the +:unless+ option. + +h4. Using +:if+ and +:unless+ with a Symbol + +You can associate the +:if+ and +:unless+ options with a symbol corresponding to the name of a method that will get called right before the callback. If this method returns +false+ the callback won't be executed. This is the most common option. Using this form of registration it's also possible to register several different methods that should be called to check if the callback should be executed. + + +class Order < ActiveRecord::Base + before_save :normalize_card_number, :if => :paid_with_card? +end + + +h4. Using +:if+ and +:unless+ with a String + +You can also use a string that will be evaluated using +eval+ and needs to contain valid Ruby code. You should use this option only when the string represents a really short condition. + + +class Order < ActiveRecord::Base + before_save :normalize_card_number, :if => "paid_with_card?" +end + + +h4. Using +:if+ and +:unless+ with a Proc + +Finally, it's possible to associate +:if+ and +:unless+ with a +Proc+ object. This option is best suited when writing short validation methods, usually one-liners. + + +class Order < ActiveRecord::Base + before_save :normalize_card_number, + :if => Proc.new { |order| order.paid_with_card? } +end + + +h4. Multiple Conditions for Callbacks + +When writing conditional callbacks, it's possible to mix both +:if+ and +:unless+ in the same callback declaration. + + +class Comment < ActiveRecord::Base + after_create :send_email_to_author, :if => :author_wants_emails?, + :unless => Proc.new { |comment| comment.post.ignore_comments? } +end + + +h3. Callback Classes + +Sometimes the callback methods that you'll write will be useful enough to be reused by other models. Active Record makes it possible to create classes that encapsulate the callback methods, so it becomes very easy to reuse them. + +Here's an example where we create a class with an +after_destroy+ callback for a +PictureFile+ model. + + +class PictureFileCallbacks + def after_destroy(picture_file) + File.delete(picture_file.filepath) + if File.exists?(picture_file.filepath) + end +end + + +When declared inside a class the callback method will receive the model object as a parameter. We can now use it this way: + + +class PictureFile < ActiveRecord::Base + after_destroy PictureFileCallbacks.new +end + + +Note that we needed to instantiate a new +PictureFileCallbacks+ object, since we declared our callback as an instance method. Sometimes it will make more sense to have it as a class method. + + +class PictureFileCallbacks + def self.after_destroy(picture_file) + File.delete(picture_file.filepath) + if File.exists?(picture_file.filepath) + end +end + + +If the callback method is declared this way, it won't be necessary to instantiate a +PictureFileCallbacks+ object. + + +class PictureFile < ActiveRecord::Base + after_destroy PictureFileCallbacks +end + + +You can declare as many callbacks as you want inside your callback classes. + +h3. Observers + +Observers are similar to callbacks, but with important differences. Whereas callbacks can pollute a model with code that isn't directly related to its purpose, observers allow you to add the same functionality outside of a model. For example, it could be argued that a +User+ model should not include code to send registration confirmation emails. Whenever you use callbacks with code that isn't directly related to your model, you may want to consider creating an observer instead. + +h4. Creating Observers + +For example, imagine a +User+ model where we want to send an email every time a new user is created. Because sending emails is not directly related to our model's purpose, we could create an observer to contain this functionality. + + +rails generate observer User + + + +class UserObserver < ActiveRecord::Observer + def after_create(model) + # code to send confirmation email... + end +end + + +As with callback classes, the observer's methods receive the observed model as a parameter. + +h4. Registering Observers + +Observers are conventionally placed inside of your +app/models+ directory and registered in your application's +config/environment.rb+ file. For example, the +UserObserver+ above would be saved as +app/models/user_observer.rb+ and registered in +config/environment.rb+ this way: + + +# Activate observers that should always be running +config.active_record.observers = :user_observer + + +As usual, settings in +config/environments+ take precedence over those in +config/environment.rb+. So, if you prefer that an observer not run in all environments, you can simply register it in a specific environment instead. + +h4. Sharing Observers + +By default, Rails will simply strip "Observer" from an observer's name to find the model it should observe. However, observers can also be used to add behaviour to more than one model, and so it's possible to manually specify the models that our observer should observe. + + +class MailerObserver < ActiveRecord::Observer + observe :registration, :user + + def after_create(model) + # code to send confirmation email... + end +end + + +In this example, the +after_create+ method would be called whenever a +Registration+ or +User+ was created. Note that this new +MailerObserver+ would also need to be registered in +config/environment.rb+ in order to take effect. + + +# Activate observers that should always be running +config.active_record.observers = :mailer_observer + + +h3. Changelog + +"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks + +* May 24, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com +* May 15, 2010: Validation Errors section updated by "Emili Parreño":http://www.eparreno.com +* March 7, 2009: Callbacks revision by Trevor Turk +* February 10, 2009: Observers revision by Trevor Turk +* February 5, 2009: Initial revision by Trevor Turk +* January 9, 2009: Initial version by "Cássio Marques":credits.html#cmarques diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile deleted file mode 100644 index cfd4ae55cc..0000000000 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ /dev/null @@ -1,1170 +0,0 @@ -h2. Active Record Validations and Callbacks - -This guide teaches you how to hook into the lifecycle of your Active Record objects. You will learn how to validate the state of objects before they go into the database, and how to perform custom operations at certain points in the object lifecycle. - -After reading this guide and trying out the presented concepts, we hope that you'll be able to: - -* Understand the lifecycle of Active Record objects -* Use the built-in Active Record validation helpers -* Create your own custom validation methods -* Work with the error messages generated by the validation process -* Create callback methods that respond to events in the object lifecycle -* Create special classes that encapsulate common behavior for your callbacks -* Create Observers that respond to lifecycle events outside of the original class - -endprologue. - -h3. The Object Lifecycle - -During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this object lifecycle so that you can control your application and its data. - -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. - -h3. Validations Overview - -Before you dive into the detail of validations in Rails, you should understand a bit about how validations fit into the big picture. - -h4. Why Use Validations? - -Validations are used to ensure that only valid data is saved into your database. For example, it may be important to your application to ensure that every user provides a valid email address and mailing address. - -There are several ways to validate data before it is saved into your database, including native database constraints, client-side validations, controller-level validations, and model-level validations. - -* 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. -* 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. -* 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. -* 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. - -h4. When Does Validation Happen? - -There are two kinds of Active Record objects: those that correspond to a row inside your database and those that do not. When you create a fresh object, for example using the +new+ method, that object does not belong to the database yet. Once you call +save+ upon that object it will be saved into the appropriate database table. Active Record uses the +new_record?+ instance method to determine whether an object is already in the database or not. Consider the following simple Active Record class: - - -class Person < ActiveRecord::Base -end - - -We can see how it works by looking at some +rails console+ output: - - ->> p = Person.new(:name => "John Doe") -=> # ->> p.new_record? -=> true ->> p.save -=> true ->> p.new_record? -=> false - - -Creating and saving a new record will send an SQL +INSERT+ operation to the database. Updating an existing record will send an SQL +UPDATE+ operation instead. Validations are typically run before these commands are sent to the database. If any validations fail, the object will be marked as invalid and Active Record will not perform the +INSERT+ or +UPDATE+ operation. This helps to avoid storing an invalid object in the database. You can choose to have specific validations run when an object is created, saved, or updated. - -CAUTION: There are many ways to change the state of an object in the database. Some methods will trigger validations, but some will not. This means that it's possible to save an object in the database in an invalid state if you aren't careful. - -The following methods trigger validations, and will save the object to the database only if the object is valid: - -* +create+ -* +create!+ -* +save+ -* +save!+ -* +update+ -* +update_attributes+ -* +update_attributes!+ - -The bang versions (e.g. +save!+) raise an exception if the record is invalid. The non-bang versions don't: +save+ and +update_attributes+ return +false+, +create+ and +update+ just return the objects. - -h4. Skipping Validations - -The following methods skip validations, and will save the object to the database regardless of its validity. They should be used with caution. - -* +decrement!+ -* +decrement_counter+ -* +increment!+ -* +increment_counter+ -* +toggle!+ -* +update_all+ -* +update_attribute+ -* +update_counters+ - -Note that +save+ also has the ability to skip validations if passed +false+ as argument. This technique should be used with caution. - -* +save(false)+ - -h4. +valid?+ and +invalid?+ - -To verify whether or not an object is valid, Rails uses the +valid?+ method. You can also use this method on your own. +valid?+ triggers your validations and returns true if no errors were added to the object, and false otherwise. - - -class Person < ActiveRecord::Base - validates_presence_of :name -end - -Person.create(:name => "John Doe").valid? # => true -Person.create(:name => nil).valid? # => false - - -When Active Record is performing validations, any errors found can be accessed through the +errors+ instance method. By definition an object is valid if this collection is empty after running validations. - -Note that an object instantiated with +new+ will not report errors even if it's technically invalid, because validations are not run when using +new+. - - -class Person < ActiveRecord::Base - validates_presence_of :name -end - ->> p = Person.new -=> # ->> p.errors -=> {} - ->> p.valid? -=> false ->> p.errors -=> {:name=>["can't be blank"]} - ->> p = Person.create -=> # ->> p.errors -=> {:name=>["can't be blank"]} - ->> p.save -=> false - ->> p.save! -=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank - ->> Person.create! -=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank - - -+invalid?+ is simply the inverse of +valid?+. +invalid?+ triggers your validations and returns true if any errors were added to the object, and false otherwise. - -h4(#validations_overview-errors). +errors[]+ - -To verify whether or not a particular attribute of an object is valid, you can use +errors[:attribute]+ that returns an array with all attribute errors, when there are no errors on the specified attribute, an empty array is returned. - -This method is only useful _after_ validations have been run, because it only inspects the errors collection and does not trigger validations itself. It's different from the +ActiveRecord::Base#invalid?+ method explained above because it doesn't verify the validity of the object as a whole. It only checks to see whether there are errors found on an individual attribute of the object. - - -class Person < ActiveRecord::Base - validates_presence_of :name -end - ->> Person.new.errors[:name].any? # => false ->> Person.create.errors[:name].any? # => true - - -We'll cover validation errors in greater depth in the "Working with Validation Errors":#working-with-validation-errors section. For now, let's turn to the built-in validation helpers that Rails provides by default. - -h3. Validation Helpers - -Active Record offers many pre-defined validation helpers that you can use directly inside your class definitions. These helpers provide common validation rules. Every time a validation fails, an error message is added to the object's +errors+ collection, and this message is associated with the field being validated. - -Each helper accepts an arbitrary number of attribute names, so with a single line of code you can add the same kind of validation to several attributes. - -All of them accept the +:on+ and +:message+ options, which define when the validation should be run and what message should be added to the +errors+ collection if it fails, respectively. The +:on+ option takes one of the values +:save+ (the default), +:create+ or +:update+. There is a default error message for each one of the validation helpers. These messages are used when the +:message+ option isn't specified. Let's take a look at each one of the available helpers. - -h4. +validates_acceptance_of+ - -Validates that a checkbox on the user interface was checked when a form was submitted. This is typically used when the user needs to agree to your application's terms of service, confirm reading some text, or any similar concept. This validation is very specific to web applications and this 'acceptance' does not need to be recorded anywhere in your database (if you don't have a field for it, the helper will just create a virtual attribute). - - -class Person < ActiveRecord::Base - validates_acceptance_of :terms_of_service -end - - -The default error message for +validates_acceptance_of+ is "_must be accepted_". - -+validates_acceptance_of+ can receive an +:accept+ option, which determines the value that will be considered acceptance. It defaults to "1", but you can change this. - - -class Person < ActiveRecord::Base - validates_acceptance_of :terms_of_service, :accept => 'yes' -end - - -h4. +validates_associated+ - -You should use this helper when your model has associations with other models and they also need to be validated. When you try to save your object, +valid?+ will be called upon each one of the associated objects. - - -class Library < ActiveRecord::Base - has_many :books - validates_associated :books -end - - -This validation will work with all of the association types. - -CAUTION: Don't use +validates_associated+ on both ends of your associations, they would call each other in an infinite loop. - -The default error message for +validates_associated+ is "_is invalid_". Note that each associated object will contain its own +errors+ collection; errors do not bubble up to the calling model. - -h4. +validates_confirmation_of+ - -You should use this helper when you have two text fields that should receive exactly the same content. For example, you may want to confirm an email address or a password. This validation creates a virtual attribute whose name is the name of the field that has to be confirmed with "_confirmation" appended. - - -class Person < ActiveRecord::Base - validates_confirmation_of :email -end - - -In your view template you could use something like - - -<%= text_field :person, :email %> -<%= text_field :person, :email_confirmation %> - - -This check is performed only if +email_confirmation+ is not +nil+. To require confirmation, make sure to add a presence check for the confirmation attribute (we'll take a look at +validates_presence_of+ later on this guide): - - -class Person < ActiveRecord::Base - validates_confirmation_of :email - validates_presence_of :email_confirmation -end - - -The default error message for +validates_confirmation_of+ is "_doesn't match confirmation_". - -h4. +validates_exclusion_of+ - -This helper validates that the attributes' values are not included in a given set. In fact, this set can be any enumerable object. - - -class Account < ActiveRecord::Base - validates_exclusion_of :subdomain, :in => %w(www), - :message => "Subdomain %{value} is reserved." -end - - -The +validates_exclusion_of+ helper has an option +:in+ that receives the set of values that will not be accepted for the validated attributes. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. This example uses the +:message+ option to show how you can include the attribute's value. - -The default error message for +validates_exclusion_of+ is "_is reserved_". - -h4. +validates_format_of+ - -This helper validates the attributes' values by testing whether they match a given regular expression, which is specified using the +:with+ option. - - -class Product < ActiveRecord::Base - validates_format_of :legacy_code, :with => /\A[a-zA-Z]+\z/, - :message => "Only letters allowed" -end - - -The default error message for +validates_format_of+ is "_is invalid_". - -h4. +validates_inclusion_of+ - -This helper validates that the attributes' values are included in a given set. In fact, this set can be any enumerable object. - - -class Coffee < ActiveRecord::Base - validates_inclusion_of :size, :in => %w(small medium large), - :message => "%{value} is not a valid size" -end - - -The +validates_inclusion_of+ helper has an option +:in+ that receives the set of values that will be accepted. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. The previous example uses the +:message+ option to show how you can include the attribute's value. - -The default error message for +validates_inclusion_of+ is "_is not included in the list_". - -h4. +validates_length_of+ - -This helper validates the length of the attributes' values. It provides a variety of options, so you can specify length constraints in different ways: - - -class Person < ActiveRecord::Base - validates_length_of :name, :minimum => 2 - validates_length_of :bio, :maximum => 500 - validates_length_of :password, :in => 6..20 - validates_length_of :registration_number, :is => 6 -end - - -The possible length constraint options are: - -* +:minimum+ - The attribute cannot have less than the specified length. -* +:maximum+ - The attribute cannot have more than the specified length. -* +:in+ (or +:within+) - The attribute length must be included in a given interval. The value for this option must be a range. -* +:is+ - The attribute length must be equal to the given value. - -The default error messages depend on the type of length validation being performed. You can personalize these messages using the +:wrong_length+, +:too_long+, and +:too_short+ options and %{count} as a placeholder for the number corresponding to the length constraint being used. You can still use the +:message+ option to specify an error message. - - -class Person < ActiveRecord::Base - validates_length_of :bio, :maximum => 1000, - :too_long => "%{count} characters is the maximum allowed" -end - - -This helper counts characters by default, but you can split the value in a different way using the +:tokenizer+ option: - - -class Essay < ActiveRecord::Base - validates_length_of :content, - :minimum => 300, - :maximum => 400, - :tokenizer => lambda { |str| str.scan(/\w+/) }, - :too_short => "must have at least %{count} words", - :too_long => "must have at most %{count} words" -end - - -The +validates_size_of+ helper is an alias for +validates_length_of+. - -h4. +validates_numericality_of+ - -This helper validates that your attributes have only numeric values. By default, it will match an optional sign followed by an integral or floating point number. To specify that only integral numbers are allowed set +:only_integer+ to true. - -If you set +:only_integer+ to +true+, then it will use the - - -/\A[+-]?\d+\Z/ - - -regular expression to validate the attribute's value. Otherwise, it will try to convert the value to a number using +Float+. - -WARNING. Note that the regular expression above allows a trailing newline character. - - -class Player < ActiveRecord::Base - validates_numericality_of :points - validates_numericality_of :games_played, :only_integer => true -end - - -Besides +:only_integer+, the +validates_numericality_of+ helper also accepts the following options to add constraints to acceptable values: - -* +:greater_than+ - Specifies the value must be greater than the supplied value. The default error message for this option is "_must be greater than %{count}_". -* +:greater_than_or_equal_to+ - Specifies the value must be greater than or equal to the supplied value. The default error message for this option is "_must be greater than or equal to %{count}_". -* +:equal_to+ - Specifies the value must be equal to the supplied value. The default error message for this option is "_must be equal to %{count}_". -* +:less_than+ - Specifies the value must be less than the supplied value. The default error message for this option is "_must be less than %{count}_". -* +:less_than_or_equal_to+ - Specifies the value must be less than or equal the supplied value. The default error message for this option is "_must be less than or equal to %{count}_". -* +:odd+ - Specifies the value must be an odd number if set to true. The default error message for this option is "_must be odd_". -* +:even+ - Specifies the value must be an even number if set to true. The default error message for this option is "_must be even_". - -The default error message for +validates_numericality_of+ is "_is not a number_". - -h4. +validates_presence_of+ - -This helper validates that the specified attributes are not empty. It uses the +blank?+ method to check if the value is either +nil+ or a blank string, that is, a string that is either empty or consists of whitespace. - - -class Person < ActiveRecord::Base - validates_presence_of :name, :login, :email -end - - -If you want to be sure that an association is present, you'll need to test whether the foreign key used to map the association is present, and not the associated object itself. - - -class LineItem < ActiveRecord::Base - belongs_to :order - validates_presence_of :order_id -end - - -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]+. - -The default error message for +validates_presence_of+ is "_can't be empty_". - -h4. +validates_uniqueness_of+ - -This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create a unique index in your database. - - -class Account < ActiveRecord::Base - validates_uniqueness_of :email -end - - -The validation happens by performing a SQL query into the model's table, searching for an existing record with the same value in that attribute. - -There is a +:scope+ option that you can use to specify other attributes that are used to limit the uniqueness check: - - -class Holiday < ActiveRecord::Base - validates_uniqueness_of :name, :scope => :year, - :message => "should happen once per year" -end - - -There is also a +:case_sensitive+ option that you can use to define whether the uniqueness constraint will be case sensitive or not. This option defaults to true. - - -class Person < ActiveRecord::Base - validates_uniqueness_of :name, :case_sensitive => false -end - - -WARNING. Note that some databases are configured to perform case-insensitive searches anyway. - -The default error message for +validates_uniqueness_of+ is "_has already been taken_". - -h4. +validates_with+ - -This helper passes the record to a separate class for validation. - - -class Person < ActiveRecord::Base - validates_with GoodnessValidator -end - -class GoodnessValidator < ActiveRecord::Validator - def validate - if record.first_name == "Evil" - record.errors[:base] << "This person is evil" - end - end -end - - -The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class. - -The validator class has two attributes by default: - -* +record+ - the record to be validated -* +options+ - the extra options that were passed to +validates_with+ - -Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+: - - -class Person < ActiveRecord::Base - validates_with GoodnessValidator, :fields => [:first_name, :last_name] -end - -class GoodnessValidator < ActiveRecord::Validator - def validate - if options[:fields].any?{|field| record.send(field) == "Evil" } - record.errors[:base] << "This person is evil" - end - end -end - - -h4. +validates_each+ - -This helper validates attributes against a block. It doesn't have a predefined validation function. You should create one using a block, and every attribute passed to +validates_each+ will be tested against it. In the following example, we don't want names and surnames to begin with lower case. - - -class Person < ActiveRecord::Base - validates_each :name, :surname do |model, attr, value| - model.errors.add(attr, 'must start with upper case') if value =~ /\A[a-z]/ - end -end - - -The block receives the model, the attribute's name and the attribute's value. You can do anything you like to check for valid data within the block. If your validation fails, you can add an error message to the model, therefore making it invalid. - -h3. Common Validation Options - -There are some common options that all the validation helpers can use. Here they are, except for the +:if+ and +:unless+ options, which are discussed later in "Conditional Validation":#conditional-validation. - -h4. +:allow_nil+ - -The +:allow_nil+ option skips the validation when the value being validated is +nil+. Using +:allow_nil+ with +validates_presence_of+ allows for +nil+, but any other +blank?+ value will still be rejected. - - -class Coffee < ActiveRecord::Base - validates_inclusion_of :size, :in => %w(small medium large), - :message => "%{value} is not a valid size", :allow_nil => true -end - - -h4. +:allow_blank+ - -The +:allow_blank+ option is similar to the +:allow_nil+ option. This option will let validation pass if the attribute's value is +blank?+, like +nil+ or an empty string for example. - - -class Topic < ActiveRecord::Base - validates_length_of :title, :is => 5, :allow_blank => true -end - -Topic.create("title" => "").valid? # => true -Topic.create("title" => nil).valid? # => true - - -h4. +:message+ - -As you've already seen, the +:message+ option lets you specify the message that will be added to the +errors+ collection when validation fails. When this option is not used, Active Record will use the respective default error message for each validation helper. - -h4. +:on+ - -The +:on+ option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use +:on => :create+ to run the validation only when a new record is created or +:on => :update+ to run the validation only when a record is updated. - - -class Person < ActiveRecord::Base - # it will be possible to update email with a duplicated value - validates_uniqueness_of :email, :on => :create - - # it will be possible to create the record with a non-numerical age - validates_numericality_of :age, :on => :update - - # the default (validates on both create and update) - validates_presence_of :name, :on => :save -end - - -h3. Conditional Validation - -Sometimes it will make sense to validate an object just when a given predicate is satisfied. You can do that by using the +:if+ and +:unless+ options, which can take a symbol, a string or a +Proc+. You may use the +:if+ option when you want to specify when the validation *should* happen. If you want to specify when the validation *should not* happen, then you may use the +:unless+ option. - -h4. Using a Symbol with +:if+ and +:unless+ - -You can associate the +:if+ and +:unless+ options with a symbol corresponding to the name of a method that will get called right before validation happens. This is the most commonly used option. - - -class Order < ActiveRecord::Base - validates_presence_of :card_number, :if => :paid_with_card? - - def paid_with_card? - payment_type == "card" - end -end - - -h4. Using a String with +:if+ and +:unless+ - -You can also use a string that will be evaluated using +eval+ and needs to contain valid Ruby code. You should use this option only when the string represents a really short condition. - - -class Person < ActiveRecord::Base - validates_presence_of :surname, :if => "name.nil?" -end - - -h4. Using a Proc with +:if+ and +:unless+ - -Finally, it's possible to associate +:if+ and +:unless+ with a +Proc+ object which will be called. Using a +Proc+ object gives you the ability to write an inline condition instead of a separate method. This option is best suited for one-liners. - - -class Account < ActiveRecord::Base - validates_confirmation_of :password, - :unless => Proc.new { |a| a.password.blank? } -end - - -h3. Creating Custom Validation Methods - -When the built-in validation helpers are not enough for your needs, you can write your own validation methods. - -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. - -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. - - -class Invoice < ActiveRecord::Base - validate :expiration_date_cannot_be_in_the_past, - :discount_cannot_be_greater_than_total_value - - def expiration_date_cannot_be_in_the_past - errors.add(:expiration_date, "can't be in the past") if - !expiration_date.blank? and expiration_date < Date.today - end - - def discount_cannot_be_greater_than_total_value - errors.add(:discount, "can't be greater than total value") if - discount > total_value - end -end - - -You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find it useful to express that a certain field corresponds to a set of choices: - - -ActiveRecord::Base.class_eval do - def self.validates_as_choice(attr_name, n, options={}) - validates_inclusion_of attr_name, {:in => 1..n}.merge(options) - end -end - - -Simply reopen +ActiveRecord::Base+ and define a class method like that. You'd typically put this code somewhere in +config/initializers+. You can use this helper like this: - - -class Movie < ActiveRecord::Base - validates_as_choice :rating, 5 -end - - -h3. Working with Validation Errors - -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. - -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. - -h4(#working_with_validation_errors-errors). +errors+ - -Returns an OrderedHash with all errors. Each key is the attribute name and the value is an array of strings with all errors. - - -class Person < ActiveRecord::Base - validates_presence_of :name - validates_length_of :name, :minimum => 3 -end - -person = Person.new -person.valid? # => false -person.errors - # => {:name => ["can't be blank", "is too short (minimum is 3 characters)"]} - -person = Person.new(:name => "John Doe") -person.valid? # => true -person.errors # => [] - - -h4(#working_with_validation_errors-errors-2). +errors[]+ - -+errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute, it returns an empty array. - - -class Person < ActiveRecord::Base - validates_presence_of :name - validates_length_of :name, :minimum => 3 -end - -person = Person.new(:name => "John Doe") -person.valid? # => true -person.errors[:name] # => [] - -person = Person.new(:name => "JD") -person.valid? # => false -person.errors[:name] # => ["is too short (minimum is 3 characters)"] - -person = Person.new -person.valid? # => false -person.errors[:name] - # => ["can't be blank", "is too short (minimum is 3 characters)"] - - -h4. +errors.add+ - -The +add+ method lets you manually add messages that are related to particular attributes. You can use the +errors.full_messages+ or +errors.to_a+ methods to view the messages in the form they might be displayed to a user. Those particular messages get the attribute name prepended (and capitalized). +add+ receives the name of the attribute you want to add the message to, and the message itself. - - -class Person < ActiveRecord::Base - def a_method_used_for_validation_purposes - errors.add(:name, "cannot contain the characters !@#%*()_-+=") - end -end - -person = Person.create(:name => "!@#") - -person.errors[:name] - # => ["cannot contain the characters !@#%*()_-+="] - -person.errors.full_messages - # => ["Name cannot contain the characters !@#%*()_-+="] - - -Another way to do this is using +[]=+ setter - - - class Person < ActiveRecord::Base - def a_method_used_for_validation_purposes - errors[:name] = "cannot contain the characters !@#%*()_-+=" - end - end - - person = Person.create(:name => "!@#") - - person.errors[:name] - # => ["cannot contain the characters !@#%*()_-+="] - - person.errors.to_a - # => ["Name cannot contain the characters !@#%*()_-+="] - - -h4. +errors[:base]+ - -You can add error messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since +errors[:base]+ is an array, you can simply add a string to the array and uses it as the error message. - - -class Person < ActiveRecord::Base - def a_method_used_for_validation_purposes - errors[:base] << "This person is invalid because ..." - end -end - - - - -h4. +errors.clear+ - -The +clear+ method is used when you intentionally want to clear all the messages in the +errors+ collection. Of course, calling +errors.clear+ upon an invalid object won't actually make it valid: the +errors+ collection will now be empty, but the next time you call +valid?+ or any method that tries to save this object to the database, the validations will run again. If any of the validations fail, the +errors+ collection will be filled again. - - -class Person < ActiveRecord::Base - validates_presence_of :name - validates_length_of :name, :minimum => 3 -end - -person = Person.new -person.valid? # => false -person.errors[:name] - # => ["can't be blank", "is too short (minimum is 3 characters)"] - -person.errors.clear -person.errors.empty? # => true - -p.save # => false - -p.errors[:name] - # => ["can't be blank", "is too short (minimum is 3 characters)"] - - -h4. +errors.size+ - -The +size+ method returns the total number of error messages for the object. - - -class Person < ActiveRecord::Base - validates_presence_of :name - validates_length_of :name, :minimum => 3 - validates_presence_of :email -end - -person = Person.new -person.valid? # => false -person.errors.size # => 3 - -person = Person.new(:name => "Andrea", :email => "andrea@example.com") -person.valid? # => true -person.errors.size # => 0 - - -h3. Displaying Validation Errors in the View - -Rails provides built-in helpers to display the error messages of your models in your view templates. - -h4. +error_messages+ and +error_messages_for+ - -When creating a form with the +form_for+ helper, you can use the +error_messages+ method on the form builder to render all failed validation messages for the current model instance. - - -class Product < ActiveRecord::Base - validates_presence_of :description, :value - validates_numericality_of :value, :allow_nil => true -end - - - -<%= form_for(@product) do |f| %> - <%= f.error_messages %> -

- <%= f.label :description %>
- <%= f.text_field :description %> -

-

- <%= f.label :value %>
- <%= f.text_field :value %> -

-

- <%= f.submit "Create" %> -

-<% end %> -
- -To get the idea, if you submit the form with empty fields you typically get this back, though styles are indeed missing by default: - -!images/error_messages.png(Error messages)! - -You can also use the +error_messages_for+ helper to display the error messages of a model assigned to a view template. It's very similar to the previous example and will achieve exactly the same result. - - -<%= error_messages_for :product %> - - -The displayed text for each error message will always be formed by the capitalized name of the attribute that holds the error, followed by the error message itself. - -Both the +form.error_messages+ and the +error_messages_for+ helpers accept options that let you customize the +div+ element that holds the messages, changing the header text, the message below the header text and the tag used for the element that defines the header. - - -<%= f.error_messages :header_message => "Invalid product!", - :message => "You'll need to fix the following fields:", - :header_tag => :h3 %> - - -Which results in the following content: - -!images/customized_error_messages.png(Customized error messages)! - -If you pass +nil+ to any of these options, it will get rid of the respective section of the +div+. - -h4. Customizing the Error Messages CSS - -The selectors to customize the style of error messages are: - -* +.fieldWithErrors+ - Style for the form fields and labels with errors. -* +#errorExplanation+ - Style for the +div+ element with the error messages. -* +#errorExplanation h2+ - Style for the header of the +div+ element. -* +#errorExplanation p+ - Style for the paragraph that holds the message that appears right below the header of the +div+ element. -* +#errorExplanation ul li+ - Style for the list items with individual error messages. - -Scaffolding for example generates +public/stylesheets/scaffold.css+, which defines the red-based style you saw above. - -The name of the class and the id can be changed with the +:class+ and +:id+ options, accepted by both helpers. - -h4. Customizing the Error Messages HTML - -By default, form fields with errors are displayed enclosed by a +div+ element with the +fieldWithErrors+ CSS class. However, it's possible to override that. - -The way form fields with errors are treated is defined by +ActionView::Base.field_error_proc+. This is a +Proc+ that receives two parameters: - -* A string with the HTML tag -* An instance of +ActionView::Helpers::InstanceTag+. - -Here is a simple example where we change the Rails behaviour to always display the error messages in front of each of the form fields with errors. The error messages will be enclosed by a +span+ element with a +validation-error+ CSS class. There will be no +div+ element enclosing the +input+ element, so we get rid of that red border around the text field. You can use the +validation-error+ CSS class to style it anyway you want. - - -ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| - if instance.error_message.kind_of?(Array) - %(#{html_tag}  - #{instance.error_message.join(',')}) - else - %(#{html_tag}  - #{instance.error_message}) - end -end - - -This will result in something like the following: - -!images/validation_error_messages.png(Validation error messages)! - -h3. Callbacks Overview - -Callbacks are methods that get called at certain moments of an object's lifecycle. With callbacks it's possible to write code that will run whenever an Active Record object is created, saved, updated, deleted, validated, or loaded from the database. - -h4. Callback Registration - -In order to use the available callbacks, you need to register them. You can do that by implementing them as ordinary methods, and then using a macro-style class method to register them as callbacks. - - -class User < ActiveRecord::Base - validates_presence_of :login, :email - - before_validation :ensure_login_has_a_value - - protected - def ensure_login_has_a_value - if login.nil? - self.login = email unless email.blank? - end - end -end - - -The macro-style class methods can also receive a block. Consider using this style if the code inside your block is so short that it fits in just one line. - - -class User < ActiveRecord::Base - validates_presence_of :login, :email - - before_create {|user| user.name = user.login.capitalize - if user.name.blank?} -end - - -It's considered good practice to declare callback methods as being protected or private. If left public, they can be called from outside of the model and violate the principle of object encapsulation. - -h3. Available Callbacks - -Here is a list with all the available Active Record callbacks, listed in the same order in which they will get called during the respective operations: - -h4. Creating an Object - -* +before_validation+ -* +after_validation+ -* +before_save+ -* +after_save+ -* +before_create+ -* +around_create+ -* +after_create+ - -h4. Updating an Object - -* +before_validation+ -* +after_validation+ -* +before_save+ -* +after_save+ -* +before_update+ -* +around_update+ -* +after_update+ - -h4. Destroying an Object - -* +before_destroy+ -* +after_destroy+ -* +around_destroy+ - -WARNING. +after_save+ runs both on create and update, but always _after_ the more specific callbacks +after_create+ and +after_update+, no matter the order in which the macro calls were executed. - -h4. +after_initialize+ and +after_find+ - -The +after_initialize+ callback will be called whenever an Active Record object is instantiated, either by directly using +new+ or when a record is loaded from the database. It can be useful to avoid the need to directly override your Active Record +initialize+ method. - -The +after_find+ callback will be called whenever Active Record loads a record from the database. +after_find+ is called before +after_initialize+ if both are defined. - -The +after_initialize+ and +after_find+ callbacks are a bit different from the others. They have no +before_*+ counterparts, and the only way to register them is by defining them as regular methods. If you try to register +after_initialize+ or +after_find+ using macro-style class methods, they will just be ignored. This behaviour is due to performance reasons, since +after_initialize+ and +after_find+ will both be called for each record found in the database, significantly slowing down the queries. - - -class User < ActiveRecord::Base - def after_initialize - puts "You have initialized an object!" - end - - def after_find - puts "You have found an object!" - end -end - ->> User.new -You have initialized an object! -=> # - ->> User.first -You have found an object! -You have initialized an object! -=> # - - -h3. Running Callbacks - -The following methods trigger callbacks: - -* +create+ -* +create!+ -* +decrement!+ -* +destroy+ -* +destroy_all+ -* +increment!+ -* +save+ -* +save!+ -* +save(false)+ -* +toggle!+ -* +update+ -* +update_attribute+ -* +update_attributes+ -* +update_attributes!+ -* +valid?+ - -Additionally, the +after_find+ callback is triggered by the following finder methods: - -* +all+ -* +first+ -* +find+ -* +find_all_by_attribute+ -* +find_by_attribute+ -* +find_by_attribute!+ -* +last+ - -The +after_initialize+ callback is triggered every time a new object of the class is initialized. - -h3. Skipping Callbacks - -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. - -* +decrement+ -* +decrement_counter+ -* +delete+ -* +delete_all+ -* +find_by_sql+ -* +increment+ -* +increment_counter+ -* +toggle+ -* +update_all+ -* +update_counters+ - -h3. Halting Execution - -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. - -The whole callback chain is wrapped in a transaction. If any before callback method returns exactly +false+ or raises an exception the execution chain gets halted and a ROLLBACK is issued. After callbacks can only accomplish that by raising an exception. - -WARNING. Raising an arbitrary exception may break code that expects +save+ and friends not to fail like that. The +ActiveRecord::Rollback+ exception is thought precisely to tell Active Record a rollback is going on. That one is internally captured but not reraised. - -h3. Relational Callbacks - -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. - - -class User < ActiveRecord::Base - has_many :posts, :dependent => :destroy -end - -class Post < ActiveRecord::Base - after_destroy :log_destroy_action - - def log_destroy_action - puts 'Post destroyed' - end -end - ->> user = User.first -=> # ->> user.posts.create! -=> # ->> user.destroy -Post destroyed -=> # - - -h3. Conditional Callbacks - -Like in validations, we can also make our callbacks conditional, calling them only when a given predicate is satisfied. You can do that by using the +:if+ and +:unless+ options, which can take a symbol, a string or a +Proc+. You may use the +:if+ option when you want to specify when the callback *should* get called. If you want to specify when the callback *should not* be called, then you may use the +:unless+ option. - -h4. Using +:if+ and +:unless+ with a Symbol - -You can associate the +:if+ and +:unless+ options with a symbol corresponding to the name of a method that will get called right before the callback. If this method returns +false+ the callback won't be executed. This is the most common option. Using this form of registration it's also possible to register several different methods that should be called to check if the callback should be executed. - - -class Order < ActiveRecord::Base - before_save :normalize_card_number, :if => :paid_with_card? -end - - -h4. Using +:if+ and +:unless+ with a String - -You can also use a string that will be evaluated using +eval+ and needs to contain valid Ruby code. You should use this option only when the string represents a really short condition. - - -class Order < ActiveRecord::Base - before_save :normalize_card_number, :if => "paid_with_card?" -end - - -h4. Using +:if+ and +:unless+ with a Proc - -Finally, it's possible to associate +:if+ and +:unless+ with a +Proc+ object. This option is best suited when writing short validation methods, usually one-liners. - - -class Order < ActiveRecord::Base - before_save :normalize_card_number, - :if => Proc.new { |order| order.paid_with_card? } -end - - -h4. Multiple Conditions for Callbacks - -When writing conditional callbacks, it's possible to mix both +:if+ and +:unless+ in the same callback declaration. - - -class Comment < ActiveRecord::Base - after_create :send_email_to_author, :if => :author_wants_emails?, - :unless => Proc.new { |comment| comment.post.ignore_comments? } -end - - -h3. Callback Classes - -Sometimes the callback methods that you'll write will be useful enough to be reused by other models. Active Record makes it possible to create classes that encapsulate the callback methods, so it becomes very easy to reuse them. - -Here's an example where we create a class with an +after_destroy+ callback for a +PictureFile+ model. - - -class PictureFileCallbacks - def after_destroy(picture_file) - File.delete(picture_file.filepath) - if File.exists?(picture_file.filepath) - end -end - - -When declared inside a class the callback method will receive the model object as a parameter. We can now use it this way: - - -class PictureFile < ActiveRecord::Base - after_destroy PictureFileCallbacks.new -end - - -Note that we needed to instantiate a new +PictureFileCallbacks+ object, since we declared our callback as an instance method. Sometimes it will make more sense to have it as a class method. - - -class PictureFileCallbacks - def self.after_destroy(picture_file) - File.delete(picture_file.filepath) - if File.exists?(picture_file.filepath) - end -end - - -If the callback method is declared this way, it won't be necessary to instantiate a +PictureFileCallbacks+ object. - - -class PictureFile < ActiveRecord::Base - after_destroy PictureFileCallbacks -end - - -You can declare as many callbacks as you want inside your callback classes. - -h3. Observers - -Observers are similar to callbacks, but with important differences. Whereas callbacks can pollute a model with code that isn't directly related to its purpose, observers allow you to add the same functionality outside of a model. For example, it could be argued that a +User+ model should not include code to send registration confirmation emails. Whenever you use callbacks with code that isn't directly related to your model, you may want to consider creating an observer instead. - -h4. Creating Observers - -For example, imagine a +User+ model where we want to send an email every time a new user is created. Because sending emails is not directly related to our model's purpose, we could create an observer to contain this functionality. - - -rails generate observer User - - - -class UserObserver < ActiveRecord::Observer - def after_create(model) - # code to send confirmation email... - end -end - - -As with callback classes, the observer's methods receive the observed model as a parameter. - -h4. Registering Observers - -Observers are conventionally placed inside of your +app/models+ directory and registered in your application's +config/environment.rb+ file. For example, the +UserObserver+ above would be saved as +app/models/user_observer.rb+ and registered in +config/environment.rb+ this way: - - -# Activate observers that should always be running -config.active_record.observers = :user_observer - - -As usual, settings in +config/environments+ take precedence over those in +config/environment.rb+. So, if you prefer that an observer not run in all environments, you can simply register it in a specific environment instead. - -h4. Sharing Observers - -By default, Rails will simply strip "Observer" from an observer's name to find the model it should observe. However, observers can also be used to add behaviour to more than one model, and so it's possible to manually specify the models that our observer should observe. - - -class MailerObserver < ActiveRecord::Observer - observe :registration, :user - - def after_create(model) - # code to send confirmation email... - end -end - - -In this example, the +after_create+ method would be called whenever a +Registration+ or +User+ was created. Note that this new +MailerObserver+ would also need to be registered in +config/environment.rb+ in order to take effect. - - -# Activate observers that should always be running -config.active_record.observers = :mailer_observer - - -h3. Changelog - -"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks - -* May 24, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com -* May 15, 2010: Validation Errors section updated by "Emili Parreño":http://www.eparreno.com -* March 7, 2009: Callbacks revision by Trevor Turk -* February 10, 2009: Observers revision by Trevor Turk -* February 5, 2009: Initial revision by Trevor Turk -* January 9, 2009: Initial version by "Cássio Marques":credits.html#cmarques diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index 515b3aad39..1f1b7d076e 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -205,7 +205,7 @@ Upon form submission the value entered by the user will be stored in +params[:pe WARNING: You must pass the name of an instance variable, i.e. +:person+ or +"person"+, not an actual instance of your model object. -Rails provides helpers for displaying the validation errors associated with a model object. These are covered in detail by the "Active Record Validations and Callbacks":./activerecord_validations_callbacks.html#displaying-validation-errors-in-the-view guide. +Rails provides helpers for displaying the validation errors associated with a model object. These are covered in detail by the "Active Record Validations and Callbacks":./active_record_validations_callbacks.html#displaying-validation-errors-in-the-view guide. h4. Binding a Form to an Object diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb index 5a715cf9f7..be077fcd2f 100644 --- a/railties/guides/source/index.html.erb +++ b/railties/guides/source/index.html.erb @@ -47,7 +47,7 @@ Ruby on Rails Guides

This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.

<% end %> -<%= guide("Active Record Validations and Callbacks", 'activerecord_validations_callbacks.html') do %> +<%= guide("Active Record Validations and Callbacks", 'active_record_validations_callbacks.html') do %>

This guide covers how you can use Active Record validations and callbacks.

<% end %> diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index f1727166ba..501d8fef6d 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -50,7 +50,7 @@
Getting Started with Rails
Models
Rails Database Migrations
-
Active Record Validations and Callbacks
+
Active Record Validations and Callbacks
Active Record Associations
Active Record Query Interface
Views
-- cgit v1.2.3 From 1910c9239531ae98af523da81c53eded14e2909f Mon Sep 17 00:00:00 2001 From: Malcolm Locke Date: Thu, 17 Jun 2010 14:26:13 +1200 Subject: Missing quote and indentation wrong --- activerecord/lib/active_record/nested_attributes.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 99f8b431c8..12a75f5d16 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -133,7 +133,7 @@ module ActiveRecord # member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!' # member.posts.second.title # => 'The egalitarian assumption of the modern citizen' # - # Alternatively, :reject_if also accepts a symbol for using methods: + # Alternatively, :reject_if also accepts a symbol for using methods: # # class Member < ActiveRecord::Base # has_many :posts @@ -145,7 +145,7 @@ module ActiveRecord # accepts_nested_attributes_for :posts, :reject_if => :reject_posts # # def reject_posts(attributed) - # attributed['title].blank? + # attributed['title'].blank? # end # end # -- cgit v1.2.3 From 6f5fb13928ee1bb0d6c619415d6b723cd9d38c73 Mon Sep 17 00:00:00 2001 From: "Hongli Lai (Phusion)" Date: Thu, 17 Jun 2010 15:47:37 +0200 Subject: Remove documentation reference to AS::Notifications::Event#result because it has been removed. --- activesupport/lib/active_support/notifications.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 1aec7ea60f..1444fc1609 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -24,7 +24,6 @@ module ActiveSupport # event = @events.first # event.name #=> :render # event.duration #=> 10 (in milliseconds) - # event.result #=> "Foo" # event.payload #=> { :extra => :information } # # When subscribing to Notifications, you can pass a pattern, to only consume -- cgit v1.2.3 From 6d222cb94e5fdb403f9f1f75147ad42e19c5d75b Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Fri, 18 Jun 2010 15:26:07 +0200 Subject: cleaner output for rake validate_guides: dot-style, brief summary and detailed description below --- railties/guides/w3c_validator.rb | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/railties/guides/w3c_validator.rb b/railties/guides/w3c_validator.rb index b55645a7a9..49cfb984cf 100644 --- a/railties/guides/w3c_validator.rb +++ b/railties/guides/w3c_validator.rb @@ -35,18 +35,21 @@ module RailsGuides def validate validator = MarkupValidator.new + STDOUT.sync = true + errors_on_guides = {} guides_to_validate.each do |f| - puts "Validating #{f}" results = validator.validate_file(f) - if !results.validity - puts "#{f} FAILED W3C validation with #{results.errors.size} error(s):" - results.errors.each do |error| - puts error.to_s - end + if results.validity + print "." + else + print "E" + errors_on_guides[f] = results.errors end end + + show_results(errors_on_guides) end private @@ -61,6 +64,26 @@ module RailsGuides prefixes.any? {|p| guide.start_with?("./guides/output/#{p}")} end end + + def show_results(error_list) + if error_list.size == 0 + puts "\n\nAll checked guides validate OK!" + else + error_summary = error_detail = "" + + error_list.each_pair do |name, errors| + error_summary += "\n #{name}" + error_detail += "\n\n #{name} has #{errors.size} validation error(s):\n" + errors.each do |error| + error_detail += "\n "+error.to_s.gsub("\n", "") + end + end + + puts "\n\nThere are #{error_list.size} guides with validation errors:\n" + error_summary + puts "\nHere are the detailed errors for each guide:" + error_detail + end + end + end end -- cgit v1.2.3 From 9d3eeb905341aaad942ceb0e47bd04cced34d031 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Fri, 18 Jun 2010 18:25:07 +0200 Subject: fix for :shallow in router not generating helpers for create, update, and destroy actions when :only or :except are used [#4900 state:committed] Signed-off-by: Jeremy Kemper --- actionpack/lib/action_dispatch/routing/mapper.rb | 7 ++--- actionpack/test/dispatch/routing_test.rb | 40 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 46304b0336..95e56566a3 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -536,6 +536,7 @@ module ActionDispatch def member_name name end + alias_method :collection_name, :member_name def nested_path path @@ -874,9 +875,9 @@ module ActionDispatch shallow_prefix = @scope[:module].blank? ? "" : "#{@scope[:module].tr('/', '_')}_" case action - when :index + when :index, :create "#{name_prefix}#{parent_resource.collection_name}" - when :show + when :show, :update, :destroy if parent_resource.shallow? "#{shallow_prefix}#{parent_resource.member_name}" else @@ -890,8 +891,6 @@ module ActionDispatch end when :new "new_#{name_prefix}#{parent_resource.member_name}" - when :update, :create, :destroy - nil else case @scope[:scope_level] when :collection diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index e294703e72..0b3bbcc86b 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -142,6 +142,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :comments, :except => :destroy end + resource :past, :only => :destroy + resource :present, :only => :update + resource :future, :only => :create + resources :relationships, :only => [:create, :destroy] + resources :friendships, :only => [:update] + shallow do namespace :api do resources :teams do @@ -729,6 +735,38 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_resource_routes_only_create_update_destroy + with_test_routes do + delete '/past' + assert_equal 'pasts#destroy', @response.body + assert_equal '/past', past_path + + put '/present' + assert_equal 'presents#update', @response.body + assert_equal '/present', present_path + + post '/future' + assert_equal 'futures#create', @response.body + assert_equal '/future', future_path + end + end + + def test_resources_routes_only_create_update_destroy + with_test_routes do + post '/relationships' + assert_equal 'relationships#create', @response.body + assert_equal '/relationships', relationships_path + + delete '/relationships/1' + assert_equal 'relationships#destroy', @response.body + assert_equal '/relationships/1', relationship_path(1) + + put '/friendships/1' + assert_equal 'friendships#update', @response.body + assert_equal '/friendships/1', friendship_path(1) + end + end + def test_resource_with_slugs_in_ids with_test_routes do get '/posts/rails-rocks' @@ -843,7 +881,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/account/admin/subscription', account_admin_subscription_path end end - + def test_namespace_nested_in_resources with_test_routes do get '/clients/1/google/account' -- cgit v1.2.3 From a186431414de8a0f0db9f60254f421a3536cee12 Mon Sep 17 00:00:00 2001 From: David Genord II Date: Fri, 18 Jun 2010 15:40:20 -0400 Subject: form_for without :html and with :remote should not error [#4902 state:committed] Signed-off-by: Jeremy Kemper --- actionpack/lib/action_view/helpers/form_helper.rb | 2 +- actionpack/test/template/form_helper_test.rb | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index b3db3151d3..a49daab98b 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -302,7 +302,7 @@ module ActionView args.unshift object end - options[:html][:remote] = true if options.delete(:remote) + (options[:html] ||= {})[:remote] = true if options.delete(:remote) output = form_tag(options.delete(:url) || {}, options.delete(:html) || {}) output << fields_for(object_name, *(args << options), &proc) diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 2f3869994c..8de1e782c0 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -644,6 +644,26 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_remote_without_html + assert_deprecated do + form_for(:post, @post, :remote => true) do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end + end + + expected = + "
" + + "" + + "" + + "" + + "" + + "
" + + assert_dom_equal expected, output_buffer + end + def test_form_for_without_object form_for(:post, :html => { :id => 'create-post' }) do |f| concat f.text_field(:title) -- cgit v1.2.3 From 237165feb3e5f7b117b05353bd64d756b9f18f74 Mon Sep 17 00:00:00 2001 From: Brian Durand Date: Fri, 18 Jun 2010 16:59:33 -0500 Subject: Fix bug with rolling back frozen attributes. [#2991] Signed-off-by: Jeremy Kemper --- .../connection_adapters/abstract/database_statements.rb | 4 ++-- activerecord/lib/active_record/transactions.rb | 1 + activerecord/test/cases/autosave_association_test.rb | 1 - activerecord/test/cases/transaction_callbacks_test.rb | 14 +++++++++++--- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index b9fb452eee..25432e9985 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -304,7 +304,7 @@ module ActiveRecord begin record.rolledback!(rollback) rescue Exception => e - record.logger.error(e) if record.respond_to?(:logger) + record.logger.error(e) if record.respond_to?(:logger) && record.logger end end end @@ -319,7 +319,7 @@ module ActiveRecord begin record.committed! rescue Exception => e - record.logger.error(e) if record.respond_to?(:logger) + record.logger.error(e) if record.respond_to?(:logger) && record.logger end end end diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 620758f5af..775d9f0fb8 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -320,6 +320,7 @@ module ActiveRecord if @_start_transaction_state[:level] < 1 restore_state = remove_instance_variable(:@_start_transaction_state) if restore_state + @attributes = @attributes.dup if @attributes.frozen? @new_record = restore_state[:new_record] @destroyed = restore_state[:destroyed] if restore_state[:id] diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 4e4f9c385c..3b89c12a3f 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -712,7 +712,6 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase end assert_raise(RuntimeError) { assert !@pirate.save } - assert before.first.frozen? # the first child was indeed destroyed assert_equal before, @pirate.reload.send(association_name) end diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index ebc16653cb..df123c9de8 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -221,20 +221,28 @@ class TransactionCallbacksTest < ActiveRecord::TestCase assert_equal 2, @first.rollbacks end - def test_after_transaction_callbacks_should_not_raise_errors + def test_after_transaction_callbacks_should_prevent_callbacks_from_being_called def @first.last_after_transaction_error=(e); @last_transaction_error = e; end def @first.last_after_transaction_error; @last_transaction_error; end @first.after_commit_block{|r| r.last_after_transaction_error = :commit; raise "fail!";} @first.after_rollback_block{|r| r.last_after_transaction_error = :rollback; raise "fail!";} + @second.after_commit_block{|r| r.history << :after_commit} + @second.after_rollback_block{|r| r.history << :after_rollback} - @first.save! + Topic.transaction do + @first.save! + @second.save! + end assert_equal :commit, @first.last_after_transaction_error + assert_equal [:after_commit], @second.history + @second.history.clear Topic.transaction do @first.save! + @second.save! raise ActiveRecord::Rollback end - assert_equal :rollback, @first.last_after_transaction_error + assert_equal [:after_rollback], @second.history end end -- cgit v1.2.3 From bfc05e244cf9ca81c7fc7d6ee90a9c8b688bf86c Mon Sep 17 00:00:00 2001 From: Antonio Cangiano Date: Fri, 28 May 2010 16:27:14 -0400 Subject: Adds a few connection parameters for IBM databases. [#3852] Signed-off-by: Jeremy Kemper --- .../app/templates/config/databases/ibm_db.yml | 60 +++++++++++++--------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml index 2784a949fb..df5ef33064 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml @@ -32,40 +32,52 @@ # please refer to the latest documents at http://rubyforge.org/docman/?group_id=2361 development: - adapter: ibm_db - username: db2inst1 + adapter: ibm_db + username: db2inst1 password: - database: <%= app_name[0,4] %>_dev - #schema: db2inst1 - #host: localhost - #port: 50000 - #account: my_account - #app_user: my_app_user + database: <%= app_name[0,4] %>_dev + #schema: db2inst1 + #host: localhost + #port: 50000 + #account: my_account + #app_user: my_app_user #application: my_application #workstation: my_workstation + #security: SSL + #timeout: 10 + #authentication: SERVER + #parameterized: false test: - adapter: ibm_db - username: db2inst1 + adapter: ibm_db + username: db2inst1 password: - database: <%= app_name[0,4] %>_tst - #schema: db2inst1 - #host: localhost - #port: 50000 - #account: my_account - #app_user: my_app_user + database: <%= app_name[0,4] %>_tst + #schema: db2inst1 + #host: localhost + #port: 50000 + #account: my_account + #app_user: my_app_user #application: my_application #workstation: my_workstation + #security: SSL + #timeout: 10 + #authentication: SERVER + #parameterized: false production: - adapter: ibm_db - username: db2inst1 + adapter: ibm_db + username: db2inst1 password: - database: <%= app_name[0,8] %> - #schema: db2inst1 - #host: localhost - #port: 50000 - #account: my_account - #app_user: my_app_user + database: <%= app_name[0,8] %> + #schema: db2inst1 + #host: localhost + #port: 50000 + #account: my_account + #app_user: my_app_user #application: my_application #workstation: my_workstation + #security: SSL + #timeout: 10 + #authentication: SERVER + #parameterized: false \ No newline at end of file -- cgit v1.2.3 From a7cae64104008b124c834b839887bbbbe148219b Mon Sep 17 00:00:00 2001 From: Master Lambaster Date: Tue, 25 May 2010 16:11:23 +0300 Subject: Fix test which prevents connection reset on failing and remove hardcoded connection [#4689 state:committed] Signed-off-by: Jeremy Kemper --- activerecord/test/cases/adapter_test.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index fc08c2178a..646aa88d80 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -65,15 +65,14 @@ class AdapterTest < ActiveRecord::TestCase end def test_not_specifying_database_name_for_cross_database_selects - assert_nothing_raised do - ActiveRecord::Base.establish_connection({ - :adapter => 'mysql', - :username => 'rails' - }) - ActiveRecord::Base.connection.execute "SELECT activerecord_unittest.pirates.*, activerecord_unittest2.courses.* FROM activerecord_unittest.pirates, activerecord_unittest2.courses" + begin + assert_nothing_raised do + ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database)) + ActiveRecord::Base.connection.execute "SELECT activerecord_unittest.pirates.*, activerecord_unittest2.courses.* FROM activerecord_unittest.pirates, activerecord_unittest2.courses" + end + ensure + ActiveRecord::Base.establish_connection 'arunit' end - - ActiveRecord::Base.establish_connection 'arunit' end end -- cgit v1.2.3 From 2c2a5fe8299402f9bce4f163b0fd4187bb8f41a5 Mon Sep 17 00:00:00 2001 From: Maxime RETY Date: Fri, 18 Jun 2010 12:16:40 +0200 Subject: Fix Yajl backend discovery in ActiveSupport::JSON [#4897 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/json/backends/yajl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/json/backends/yajl.rb b/activesupport/lib/active_support/json/backends/yajl.rb index d76f8b03e4..64e50e0d87 100644 --- a/activesupport/lib/active_support/json/backends/yajl.rb +++ b/activesupport/lib/active_support/json/backends/yajl.rb @@ -1,4 +1,4 @@ -require 'yajl-ruby' unless defined?(Yajl) +require 'yajl' unless defined?(Yajl) module ActiveSupport module JSON -- cgit v1.2.3 From bf59717b43fc7c186f9acebac27ba9ac7d59dd93 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sat, 19 Jun 2010 07:23:57 +0100 Subject: Custom resource routes should be scoped [#3765] Signed-off-by: Jeremy Kemper --- actionpack/lib/action_dispatch/routing/mapper.rb | 43 ++++++++++++++++++---- actionpack/test/dispatch/routing_test.rb | 47 ++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 95e56566a3..0018b6485b 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -647,7 +647,9 @@ module ActionDispatch with_scope_level(:new) do scope(*parent_resource.new_scope) do - yield + scope(action_path(:new)) do + yield + end end end end @@ -723,7 +725,17 @@ module ActionDispatch options = options_for_action(args.first, options) with_exclusive_scope do - return match(path, options) + return super(path, options) + end + elsif resource_method_scope? + path = path_for_custom_action + options[:as] = name_for_action(options[:as]) if options[:as] + args.push(options) + + with_exclusive_scope do + scope(path) do + return super + end end end @@ -737,7 +749,7 @@ module ActionDispatch def root(options={}) if @scope[:scope_level] == :resources - with_scope_level(:collection) do + with_scope_level(:nested) do scope(parent_resource.path, :name_prefix => parent_resource.collection_name) do super(options) end @@ -780,12 +792,18 @@ module ActionDispatch [:resource, :resources].include?(@scope[:scope_level]) end + def resource_method_scope? + [:collection, :member, :new].include?(@scope[:scope_level]) + end + def with_exclusive_scope begin old_name_prefix, old_path = @scope[:name_prefix], @scope[:path] @scope[:name_prefix], @scope[:path] = nil, nil - yield + with_scope_level(:exclusive) do + yield + end ensure @scope[:name_prefix], @scope[:path] = old_name_prefix, old_path end @@ -844,10 +862,8 @@ module ActionDispatch end else case @scope[:scope_level] - when :collection + when :collection, :new "#{@scope[:path]}/#{action_path(action)}(.:format)" - when :new - "#{@scope[:path]}/#{action_path(:new)}/#{action_path(action)}(.:format)" else if parent_resource.shallow? "#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)" @@ -858,6 +874,19 @@ module ActionDispatch end end + def path_for_custom_action + case @scope[:scope_level] + when :collection, :new + @scope[:path] + else + if parent_resource.shallow? + "#{@scope[:module]}/#{parent_resource.path}/:id" + else + @scope[:path] + end + end + end + def action_path(name, path_names = nil) path_names ||= @scope[:path_names] path_names[name.to_sym] || name.to_s diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 0b3bbcc86b..899990c69d 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -180,6 +180,33 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + resources :customers do + get "recent" => "customers#recent", :as => :recent, :on => :collection + get "profile" => "customers#profile", :as => :profile, :on => :member + post "preview" => "customers#preview", :as => :preview, :on => :new + resource :avatar do + get "thumbnail(.:format)" => "avatars#thumbnail", :as => :thumbnail, :on => :member + end + resources :invoices do + get "outstanding" => "invoices#outstanding", :as => :outstanding, :on => :collection + get "overdue", :to => :overdue, :on => :collection + get "print" => "invoices#print", :as => :print, :on => :member + post "preview" => "invoices#preview", :as => :preview, :on => :new + end + resources :notes, :shallow => true do + get "preview" => "notes#preview", :as => :preview, :on => :new + get "print" => "notes#print", :as => :print, :on => :member + end + end + + namespace :api do + resources :customers do + get "recent" => "customers#recent", :as => :recent, :on => :collection + get "profile" => "customers#profile", :as => :profile, :on => :member + post "preview" => "customers#preview", :as => :preview, :on => :new + end + end + match 'sprockets.js' => ::TestRoutingMapper::SprocketsApp match 'people/:id/update', :to => 'people#update', :as => :update_person @@ -1295,6 +1322,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_custom_resource_routes_are_scoped + with_test_routes do + assert_equal '/customers/recent', recent_customers_path + assert_equal '/customers/1/profile', profile_customer_path(:id => '1') + assert_equal '/customers/new/preview', preview_new_customer_path + assert_equal '/customers/1/avatar/thumbnail.jpg', thumbnail_customer_avatar_path(:customer_id => '1', :format => :jpg) + assert_equal '/customers/1/invoices/outstanding', outstanding_customer_invoices_path(:customer_id => '1') + assert_equal '/customers/1/invoices/2/print', print_customer_invoice_path(:customer_id => '1', :id => '2') + assert_equal '/customers/1/invoices/new/preview', preview_new_customer_invoice_path(:customer_id => '1') + assert_equal '/customers/1/notes/new/preview', preview_new_customer_note_path(:customer_id => '1') + assert_equal '/notes/1/print', print_note_path(:id => '1') + assert_equal '/api/customers/recent', recent_api_customers_path + assert_equal '/api/customers/1/profile', profile_api_customer_path(:id => '1') + assert_equal '/api/customers/new/preview', preview_new_api_customer_path + + get '/customers/1/invoices/overdue' + assert_equal 'invoices#overdue', @response.body + end + end + private def with_test_routes yield -- cgit v1.2.3 From 4bfff05f37b8416496d25a045c0e1c38368f1e31 Mon Sep 17 00:00:00 2001 From: Scott Taylor Date: Wed, 16 Jun 2010 21:56:19 -0400 Subject: add missing shebang to rails bin. LH [#4885 state:resolved] Signed-off-by: Jeremy Kemper --- bin/rails | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/rails b/bin/rails index 4a74726e9b..a628cc35ca 100755 --- a/bin/rails +++ b/bin/rails @@ -1,3 +1,5 @@ +#!/usr/bin/env ruby + begin require "rails/cli" rescue LoadError -- cgit v1.2.3 From 8db8c6f4ce3e8dd7f90553ab7866bf9991773b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 19 Jun 2010 16:44:35 +0200 Subject: Add ActiveSupport::DescendantsTracker. --- activesupport/lib/active_support.rb | 1 + .../lib/active_support/descendants_tracker.rb | 36 +++++++++++ activesupport/test/descendants_tracker_test.rb | 72 ++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 activesupport/lib/active_support/descendants_tracker.rb create mode 100644 activesupport/test/descendants_tracker_test.rb diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index e34e46b4cf..f93b351655 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -51,6 +51,7 @@ module ActiveSupport autoload :Concern autoload :Configurable autoload :Deprecation + autoload :DescendantsTracker autoload :Gzip autoload :Inflector autoload :JSON diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb new file mode 100644 index 0000000000..a9379bf95b --- /dev/null +++ b/activesupport/lib/active_support/descendants_tracker.rb @@ -0,0 +1,36 @@ +require 'active_support/dependencies' + +module ActiveSupport + # This module provides an internal implementation to track descendants + # which is faster than iterating through ObjectSpace. + module DescendantsTracker + mattr_accessor :descendants + @@descendants = Hash.new { |h, k| h[k] = [] } + + def self.clear + @@descendants.each do |klass, descendants| + if ActiveSupport::Dependencies.autoloaded?(klass) + @@descendants.delete(klass) + else + descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) } + end + end + end + + def inherited(base) + self.direct_descendants << base + super + end + + def direct_descendants + @@descendants[self] + end + + def descendants + @@descendants[self].inject([]) do |descendants, klass| + descendants << klass + descendants.concat klass.descendants + end + end + end +end \ No newline at end of file diff --git a/activesupport/test/descendants_tracker_test.rb b/activesupport/test/descendants_tracker_test.rb new file mode 100644 index 0000000000..57c97b45d2 --- /dev/null +++ b/activesupport/test/descendants_tracker_test.rb @@ -0,0 +1,72 @@ +require 'abstract_unit' +require 'test/unit' +require 'active_support' + +class DescendantsTrackerTest < Test::Unit::TestCase + class Parent + extend ActiveSupport::DescendantsTracker + end + + class Child1 < Parent + end + + class Child2 < Parent + end + + class Grandchild1 < Child1 + end + + class Grandchild2 < Child1 + end + + def test_descendants + assert_equal [Child1, Grandchild1, Grandchild2, Child2], Parent.descendants + assert_equal [Grandchild1, Grandchild2], Child1.descendants + assert_equal [], Child2.descendants + end + + def test_direct_descendants + assert_equal [Child1, Child2], Parent.direct_descendants + assert_equal [Grandchild1, Grandchild2], Child1.direct_descendants + assert_equal [], Child2.direct_descendants + end + + def test_clear_with_autoloaded_parent_children_and_granchildren + mark_as_autoloaded Parent, Child1, Child2, Grandchild1, Grandchild2 do + ActiveSupport::DescendantsTracker.clear + assert_equal Hash.new, ActiveSupport::DescendantsTracker.descendants + end + end + + def test_clear_with_autoloaded_children_and_granchildren + mark_as_autoloaded Child1, Grandchild1, Grandchild2 do + ActiveSupport::DescendantsTracker.clear + assert_equal [Child2], Parent.descendants + assert_equal [], Child2.descendants + end + end + + def test_clear_with_autoloaded_granchildren + mark_as_autoloaded Grandchild1, Grandchild2 do + ActiveSupport::DescendantsTracker.clear + assert_equal [Child1, Child2], Parent.descendants + assert_equal [], Child1.descendants + assert_equal [], Child2.descendants + end + end + + protected + + def mark_as_autoloaded(*klasses) + old_autoloaded = ActiveSupport::Dependencies.autoloaded_constants.dup + ActiveSupport::Dependencies.autoloaded_constants = klasses.map(&:name) + + old_descendants = ActiveSupport::DescendantsTracker.descendants.dup + old_descendants.each { |k, v| old_descendants[k] = v.dup } + + yield + ensure + ActiveSupport::Dependencies.autoloaded_constants = old_autoloaded + ActiveSupport::DescendantsTracker.descendants = old_descendants + end +end \ No newline at end of file -- cgit v1.2.3 From a2b7fcb07ca47ca2285dee2afe97050532e94d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 19 Jun 2010 16:58:12 +0200 Subject: Change callbacks to automatically include DescendantsTracker and rename descendents to descendants. --- activesupport/lib/active_support/callbacks.rb | 10 +++++++--- activesupport/lib/active_support/core_ext/class/subclasses.rb | 10 +++++----- activesupport/test/descendants_tracker_test.rb | 7 +++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 3ff33eea72..c4e1eb2c04 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -1,6 +1,6 @@ +require 'active_support/descendants_tracker' require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/inheritable_attributes' -require 'active_support/core_ext/class/subclasses' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/kernel/singleton_class' @@ -85,6 +85,10 @@ module ActiveSupport module Callbacks extend Concern + included do + extend ActiveSupport::DescendantsTracker + end + def run_callbacks(kind, *args, &block) send("_run_#{kind}_callbacks", *args, &block) end @@ -428,7 +432,7 @@ module ActiveSupport options = filters.last.is_a?(Hash) ? filters.pop : {} filters.unshift(block) if block - ([self] + self.descendents).each do |target| + ([self] + self.descendants).each do |target| chain = target.send("_#{name}_callbacks") yield chain, type, filters, options target.__define_runner(name) @@ -502,7 +506,7 @@ module ActiveSupport def reset_callbacks(symbol) callbacks = send("_#{symbol}_callbacks") - self.descendents.each do |target| + self.descendants.each do |target| chain = target.send("_#{symbol}_callbacks") callbacks.each { |c| chain.delete(c) } target.__define_runner(symbol) diff --git a/activesupport/lib/active_support/core_ext/class/subclasses.rb b/activesupport/lib/active_support/core_ext/class/subclasses.rb index bbd8f5aef6..7d58a8b56a 100644 --- a/activesupport/lib/active_support/core_ext/class/subclasses.rb +++ b/activesupport/lib/active_support/core_ext/class/subclasses.rb @@ -11,9 +11,9 @@ class Class #:nodoc: # Rubinius if defined?(Class.__subclasses__) - def descendents + def descendants subclasses = [] - __subclasses__.each {|k| subclasses << k; subclasses.concat k.descendents } + __subclasses__.each {|k| subclasses << k; subclasses.concat k.descendants } subclasses end else @@ -21,7 +21,7 @@ class Class #:nodoc: begin ObjectSpace.each_object(Class.new) {} - def descendents + def descendants subclasses = [] ObjectSpace.each_object(class << self; self; end) do |k| subclasses << k unless k == self @@ -30,7 +30,7 @@ class Class #:nodoc: end # JRuby rescue StandardError - def descendents + def descendants subclasses = [] ObjectSpace.each_object(Class) do |k| subclasses << k if k < self @@ -48,7 +48,7 @@ class Class #:nodoc: def self.subclasses_of(*superclasses) #:nodoc: subclasses = [] superclasses.each do |klass| - subclasses.concat klass.descendents.select {|k| k.anonymous? || k.reachable?} + subclasses.concat klass.descendants.select {|k| k.anonymous? || k.reachable?} end subclasses end diff --git a/activesupport/test/descendants_tracker_test.rb b/activesupport/test/descendants_tracker_test.rb index 57c97b45d2..e3eccb8aa9 100644 --- a/activesupport/test/descendants_tracker_test.rb +++ b/activesupport/test/descendants_tracker_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'test/unit' require 'active_support' +require 'active_support/core_ext/hash/slice' class DescendantsTrackerTest < Test::Unit::TestCase class Parent @@ -19,6 +20,8 @@ class DescendantsTrackerTest < Test::Unit::TestCase class Grandchild2 < Child1 end + ALL = [Parent, Child1, Child2, Grandchild1, Grandchild2] + def test_descendants assert_equal [Child1, Grandchild1, Grandchild2, Child2], Parent.descendants assert_equal [Grandchild1, Grandchild2], Child1.descendants @@ -32,9 +35,9 @@ class DescendantsTrackerTest < Test::Unit::TestCase end def test_clear_with_autoloaded_parent_children_and_granchildren - mark_as_autoloaded Parent, Child1, Child2, Grandchild1, Grandchild2 do + mark_as_autoloaded *ALL do ActiveSupport::DescendantsTracker.clear - assert_equal Hash.new, ActiveSupport::DescendantsTracker.descendants + assert ActiveSupport::DescendantsTracker.descendants.slice(*ALL).empty? end end -- cgit v1.2.3 From 033e0a041f10ef4d4aa8ebb576560df20b971026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 19 Jun 2010 17:15:21 +0200 Subject: ActiveRecord and ActionPack now use the new descendants implementation. --- actionpack/lib/abstract_controller/base.rb | 13 ++-------- activerecord/lib/active_record/associations.rb | 2 +- activerecord/lib/active_record/base.rb | 36 +++----------------------- activerecord/lib/active_record/observer.rb | 3 ++- activerecord/test/cases/base_test.rb | 4 --- 5 files changed, 9 insertions(+), 49 deletions(-) diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index e1027840ef..8a8337858b 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -1,4 +1,5 @@ require 'active_support/configurable' +require 'active_support/descendants_tracker' require 'active_support/core_ext/module/anonymous' module AbstractController @@ -10,6 +11,7 @@ module AbstractController attr_internal :action_name include ActiveSupport::Configurable + extend ActiveSupport::DescendantsTracker class << self attr_reader :abstract @@ -21,17 +23,6 @@ module AbstractController @abstract = true end - def inherited(klass) - ::AbstractController::Base.descendants << klass.to_s - super - end - - # A list of all descendents of AbstractController::Base. This is - # useful for initializers which need to add behavior to all controllers. - def descendants - @descendants ||= [] - end - # A list of all internal methods for a controller. This finds the first # abstract superclass of a controller, and gets a list of all public # instance methods on that abstract class. Public instance methods of diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 9b59266bbc..567218e6fb 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -2066,7 +2066,7 @@ module ActiveRecord unless klass.descends_from_active_record? sti_column = aliased_table[klass.inheritance_column] sti_condition = sti_column.eq(klass.sti_name) - klass.send(:subclasses).each {|subclass| sti_condition = sti_condition.or(sti_column.eq(subclass.sti_name)) } + klass.descendants.each {|subclass| sti_condition = sti_condition.or(sti_column.eq(subclass.sti_name)) } @join << sti_condition end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 3b6ffa46f2..def0fdaa2f 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -2,6 +2,7 @@ require 'yaml' require 'set' require 'active_support/benchmarkable' require 'active_support/dependencies' +require 'active_support/descendants_tracker' require 'active_support/time' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute_accessors' @@ -274,28 +275,6 @@ module ActiveRecord #:nodoc: # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+. cattr_accessor :logger, :instance_writer => false - def self.inherited(child) #:nodoc: - @@subclasses[self] ||= [] - @@subclasses[self] << child - super - end - - def self.reset_subclasses #:nodoc: - nonreloadables = [] - subclasses.each do |klass| - unless ActiveSupport::Dependencies.autoloaded? klass - nonreloadables << klass - next - end - klass.instance_variables.each { |var| klass.send(:remove_instance_variable, var) } - klass.instance_methods(false).each { |m| klass.send :undef_method, m } - end - @@subclasses = {} - nonreloadables.each { |klass| (@@subclasses[klass.superclass] ||= []) << klass } - end - - @@subclasses = {} - ## # :singleton-method: # Contains the database configuration - as is typically stored in config/database.yml - @@ -810,7 +789,7 @@ module ActiveRecord #:nodoc: end def reset_column_information_and_inheritable_attributes_for_all_subclasses#:nodoc: - subclasses.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information } + descendants.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information } end def attribute_method?(attribute) @@ -975,7 +954,7 @@ module ActiveRecord #:nodoc: def type_condition sti_column = arel_table[inheritance_column] condition = sti_column.eq(sti_name) - subclasses.each{|subclass| condition = condition.or(sti_column.eq(subclass.sti_name)) } + descendants.each { |subclass| condition = condition.or(sti_column.eq(subclass.sti_name)) } condition end @@ -1165,14 +1144,6 @@ module ActiveRecord #:nodoc: with_scope(method_scoping, :overwrite, &block) end - # Returns a list of all subclasses of this class, meaning all descendants. - def subclasses - @@subclasses[self] ||= [] - @@subclasses[self] + @@subclasses[self].inject([]) {|list, subclass| list + subclass.subclasses } - end - - public :subclasses - # Sets the default options for the model. The format of the # options argument is the same as in find. # @@ -1900,6 +1871,7 @@ module ActiveRecord #:nodoc: extend ActiveModel::Naming extend QueryCache::ClassMethods extend ActiveSupport::Benchmarkable + extend ActiveSupport::DescendantsTracker include ActiveModel::Conversion include Validations diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index 0ea7fe7365..fabbc33005 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -105,8 +105,9 @@ module ActiveRecord end protected + def observed_subclasses - observed_classes.sum([]) { |klass| klass.send(:subclasses) } + observed_classes.sum([]) { |klass| klass.send(:descendants) } end def observe_callbacks? diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 5c175de6d4..7c74d87b61 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -2076,10 +2076,6 @@ class BasicsTest < ActiveRecord::TestCase assert !SubStiPost.descends_from_active_record? end - def test_base_subclasses_is_public_method - assert ActiveRecord::Base.public_methods.map(&:to_sym).include?(:subclasses) - end - def test_find_on_abstract_base_class_doesnt_use_type_condition old_class = LooseDescendant Object.send :remove_const, :LooseDescendant -- cgit v1.2.3 From d430db9fd407fd6aee25ca13538d8988dc7ee297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 19 Jun 2010 17:16:11 +0200 Subject: Remove descendants warning while executing tests. --- activesupport/lib/active_support/descendants_tracker.rb | 5 ++++- activesupport/test/descendants_tracker_test.rb | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb index a9379bf95b..a587d7770c 100644 --- a/activesupport/lib/active_support/descendants_tracker.rb +++ b/activesupport/lib/active_support/descendants_tracker.rb @@ -4,9 +4,12 @@ module ActiveSupport # This module provides an internal implementation to track descendants # which is faster than iterating through ObjectSpace. module DescendantsTracker - mattr_accessor :descendants @@descendants = Hash.new { |h, k| h[k] = [] } + def self.descendants + @@descendants + end + def self.clear @@descendants.each do |klass, descendants| if ActiveSupport::Dependencies.autoloaded?(klass) diff --git a/activesupport/test/descendants_tracker_test.rb b/activesupport/test/descendants_tracker_test.rb index e3eccb8aa9..3a424180de 100644 --- a/activesupport/test/descendants_tracker_test.rb +++ b/activesupport/test/descendants_tracker_test.rb @@ -70,6 +70,6 @@ class DescendantsTrackerTest < Test::Unit::TestCase yield ensure ActiveSupport::Dependencies.autoloaded_constants = old_autoloaded - ActiveSupport::DescendantsTracker.descendants = old_descendants + ActiveSupport::DescendantsTracker.descendants.replace(old_descendants) end end \ No newline at end of file -- cgit v1.2.3 From f368b21cb6e45268359c0f0b8beda175e3b40eae Mon Sep 17 00:00:00 2001 From: wycats Date: Sat, 19 Jun 2010 08:19:00 -0700 Subject: Remove a relic of #request being in RackDelegation --- actionpack/lib/action_controller/metal.rb | 11 +++++++++-- actionpack/lib/action_controller/metal/rack_delegation.rb | 4 ---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 775a5002e2..159d1f0748 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -52,8 +52,7 @@ module ActionController class Metal < AbstractController::Base abstract! - # :api: public - attr_internal :params, :env + attr_internal :env # Returns the last part of the controller's name, underscored, without the ending # "Controller". For instance, MyApp::MyPostsController would return "my_posts" for @@ -85,6 +84,14 @@ module ActionController super end + def params + @_params ||= request.parameters + end + + def params=(val) + @_params = val + end + # Basic implementations for content_type=, location=, and headers are # provided to reduce the dependency on the RackDelegation module # in Renderer and Redirector. diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb index 508ea6e2b7..544b4989c7 100644 --- a/actionpack/lib/action_controller/metal/rack_delegation.rb +++ b/actionpack/lib/action_controller/metal/rack_delegation.rb @@ -14,10 +14,6 @@ module ActionController super(action, request) end - def params - @_params ||= @_request.parameters - end - def response_body=(body) response.body = body if response super -- cgit v1.2.3 From 728b9eccad99d22028577e8b06433e8344b15d01 Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Thu, 17 Jun 2010 09:17:31 +0200 Subject: option_groups_from_collection_for_select should return HTML-safe string [#4879 state:resolved] Signed-off-by: Xavier Noria --- .../lib/action_view/helpers/form_options_helper.rb | 2 +- .../test/template/form_options_helper_test.rb | 30 +++++++++------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index fe71d2cdf7..e48580e0ad 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -398,7 +398,7 @@ module ActionView options_for_select += "" options_for_select += options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key) options_for_select += '' - end + end.html_safe end # Returns a string of tags, like options_for_select, but diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 19b73aa810..65b5f5ccc1 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -177,17 +177,16 @@ class FormOptionsHelperTest < ActionView::TestCase end def test_option_groups_from_collection_for_select - @continents = [ - Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ), - Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] ) - ] - assert_dom_equal( "\n\n", - option_groups_from_collection_for_select(@continents, "countries", "continent_name", "country_id", "country_name", "dk") + option_groups_from_collection_for_select(dummy_continents, "countries", "continent_name", "country_id", "country_name", "dk") ) end + def test_option_groups_from_collection_for_select_returns_html_safe_string + assert option_groups_from_collection_for_select(dummy_continents, "countries", "continent_name", "country_id", "country_name", "dk").html_safe? + end + def test_grouped_options_for_select_with_array assert_dom_equal( "\n\n", @@ -824,31 +823,21 @@ class FormOptionsHelperTest < ActionView::TestCase end def test_grouped_collection_select - @continents = [ - Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ), - Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] ) - ] - @post = Post.new @post.origin = 'dk' assert_dom_equal( %Q{}, - grouped_collection_select("post", "origin", @continents, :countries, :continent_name, :country_id, :country_name) + grouped_collection_select("post", "origin", dummy_continents, :countries, :continent_name, :country_id, :country_name) ) end def test_grouped_collection_select_under_fields_for - @continents = [ - Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ), - Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] ) - ] - @post = Post.new @post.origin = 'dk' output_buffer = fields_for :post, @post do |f| - concat f.grouped_collection_select("origin", @continents, :countries, :continent_name, :country_id, :country_name) + concat f.grouped_collection_select("origin", dummy_continents, :countries, :continent_name, :country_id, :country_name) end assert_dom_equal( @@ -864,4 +853,9 @@ class FormOptionsHelperTest < ActionView::TestCase Post.new("Babe went home", "Babe", "To a little house", "shh!"), Post.new("Cabe went home", "Cabe", "To a little house", "shh!") ] end + + def dummy_continents + [ Continent.new("", [Country.new("", ""), Country.new("so", "Somalia")] ), + Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] ) ] + end end -- cgit v1.2.3 From 312f43324159fbcd8749cd331ed7d6500a714a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 19 Jun 2010 17:51:29 +0200 Subject: Clear DescendantsTracker on each request. --- .../lib/action_dispatch/middleware/callbacks.rb | 8 +-- activerecord/lib/active_record/railtie.rb | 1 - railties/lib/rails/application/bootstrap.rb | 2 + .../application/initializers/load_path_test.rb | 2 +- railties/test/application/loading_test.rb | 73 ++++++++++++++++++++++ .../test/application/model_initialization_test.rb | 33 ---------- railties/test/application/rake_test.rb | 2 +- 7 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 railties/test/application/loading_test.rb delete mode 100644 railties/test/application/model_initialization_test.rb diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb index d07841218a..e4ae480bfb 100644 --- a/actionpack/lib/action_dispatch/middleware/callbacks.rb +++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb @@ -8,7 +8,7 @@ module ActionDispatch class Callbacks include ActiveSupport::Callbacks - define_callbacks :call, :terminator => "result == false", :rescuable => true + define_callbacks :call, :rescuable => true define_callbacks :prepare, :scope => :name # Add a preparation callback. Preparation callbacks are run before every @@ -37,12 +37,12 @@ module ActionDispatch def initialize(app, prepare_each_request = false) @app, @prepare_each_request = app, prepare_each_request - run_callbacks(:prepare) + _run_prepare_callbacks end def call(env) - run_callbacks(:call) do - run_callbacks(:prepare) if @prepare_each_request + _run_call_callbacks do + _run_prepare_callbacks if @prepare_each_request @app.call(env) end end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index a32fb7d399..0386fd4651 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -68,7 +68,6 @@ module ActiveRecord unless app.config.cache_classes ActiveSupport.on_load(:active_record) do ActionDispatch::Callbacks.after do - ActiveRecord::Base.reset_subclasses ActiveRecord::Base.clear_reloadable_connections! end end diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index 0a435f0f36..44e26b5713 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -1,4 +1,5 @@ require "active_support/notifications" +require "active_support/descendants_tracker" module Rails class Application @@ -55,6 +56,7 @@ module Rails initializer :set_clear_dependencies_hook do unless config.cache_classes ActionDispatch::Callbacks.after do + ActiveSupport::DescendantsTracker.clear ActiveSupport::Dependencies.clear end end diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb index d31915e129..714d62311d 100644 --- a/railties/test/application/initializers/load_path_test.rb +++ b/railties/test/application/initializers/load_path_test.rb @@ -19,7 +19,7 @@ module ApplicationTests assert $:.include?("#{app_path}/app/models") end - test "initializing an application adds lib path on inheritance hook" do + test "initializing an application allows to load code on lib path inside application class definitation" do app_file "lib/foo.rb", <<-RUBY module Foo; end RUBY diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb new file mode 100644 index 0000000000..b337d3fc6e --- /dev/null +++ b/railties/test/application/loading_test.rb @@ -0,0 +1,73 @@ +require 'isolation/abstract_unit' + +class LoadingTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + end + + def app + @app ||= Rails.application + end + + def test_load_should_load_constants + app_file "app/models/post.rb", <<-MODEL + class Post < ActiveRecord::Base + validates_acceptance_of :title, :accept => "omg" + end + MODEL + + require "#{rails_root}/config/environment" + setup_ar! + + p = Post.create(:title => 'omg') + assert_equal 1, Post.count + assert_equal 'omg', p.title + p = Post.first + assert_equal 'omg', p.title + end + + def test_descendants_are_cleaned_on_each_request_without_cache_classes + add_to_config <<-RUBY + config.cache_classes = false + RUBY + + app_file "app/models/post.rb", <<-MODEL + class Post < ActiveRecord::Base + end + MODEL + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do |map| + match '/load', :to => lambda { |env| [200, {}, Post.all] } + match '/unload', :to => lambda { |env| [200, {}, []] } + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + + require "#{rails_root}/config/environment" + setup_ar! + + assert_equal [], ActiveRecord::Base.descendants + get "/load" + assert_equal [Post], ActiveRecord::Base.descendants + get "/unload" + assert_equal [], ActiveRecord::Base.descendants + end + + protected + + def setup_ar! + ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") + ActiveRecord::Migration.verbose = false + ActiveRecord::Schema.define(:version => 1) do + create_table :posts do |t| + t.string :title + end + end + end +end diff --git a/railties/test/application/model_initialization_test.rb b/railties/test/application/model_initialization_test.rb deleted file mode 100644 index 6a22f8d8df..0000000000 --- a/railties/test/application/model_initialization_test.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'isolation/abstract_unit' - -class PostTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation - - def setup - build_app - boot_rails - end - - def test_reload_should_reload_constants - app_file "app/models/post.rb", <<-MODEL - class Post < ActiveRecord::Base - validates_acceptance_of :title, :accept => "omg" - end - MODEL - - require "#{rails_root}/config/environment" - ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") - ActiveRecord::Migration.verbose = false - ActiveRecord::Schema.define(:version => 1) do - create_table :posts do |t| - t.string :title - end - end - - p = Post.create(:title => 'omg') - assert_equal 1, Post.count - assert_equal 'omg', p.title - p = Post.first - assert_equal 'omg', p.title - end -end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 6b7a471494..40fb446b16 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -9,7 +9,7 @@ module ApplicationTests boot_rails FileUtils.rm_rf("#{app_path}/config/environments") end - + def test_gems_tasks_are_loaded_first_than_application_ones app_file "lib/tasks/app.rake", <<-RUBY $task_loaded = Rake::Task.task_defined?("db:create:all") -- cgit v1.2.3 From 51739d3228d12907d60fb1b0a2b1ef96c55f66a3 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 16 Jun 2010 11:30:37 -0400 Subject: moving before_validation and after_validation functionality from ActiveRecord to ActiveModel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#4653 state:resolved] Signed-off-by: José Valim --- activemodel/lib/active_model/validations.rb | 14 +--- .../lib/active_model/validations/callbacks.rb | 64 ++++++++++++++++++ .../test/cases/validations/callbacks_test.rb | 76 ++++++++++++++++++++++ activerecord/lib/active_record/base.rb | 1 + activerecord/lib/active_record/callbacks.rb | 23 +------ activerecord/lib/active_record/validations.rb | 4 +- 6 files changed, 148 insertions(+), 34 deletions(-) create mode 100644 activemodel/lib/active_model/validations/callbacks.rb create mode 100644 activemodel/test/cases/validations/callbacks_test.rb diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 57487cf75a..31516dc8a9 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -3,6 +3,7 @@ require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/keys' require 'active_model/errors' +require 'active_model/validations/callbacks' module ActiveModel @@ -45,6 +46,7 @@ module ActiveModel module Validations extend ActiveSupport::Concern include ActiveSupport::Callbacks + include ActiveModel::Validations::Callbacks included do extend ActiveModel::Translation @@ -158,18 +160,6 @@ module ActiveModel @errors ||= Errors.new(self) end - # Runs all the specified validations and returns true if no errors were added - # otherwise false. Context can optionally be supplied to define which callbacks - # to test against (the context is defined on the validations using :on). - def valid?(context = nil) - current_context, self.validation_context = validation_context, context - errors.clear - _run_validate_callbacks - errors.empty? - ensure - self.validation_context = current_context - end - # Performs the opposite of valid?. Returns true if errors were added, # false otherwise. def invalid?(context = nil) diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb new file mode 100644 index 0000000000..2c8798bcdd --- /dev/null +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -0,0 +1,64 @@ +require 'active_support/callbacks' + +module ActiveModel + module Validations + module Callbacks + # == Active Model Validation callbacks + # + # Provides an interface for any class to have before_validation and + # after_validation callbacks. + # + # First, extend ActiveModel::Callbacks from the class you are creating: + # + # class MyModel + # include ActiveModel::Validations::Callbacks + # + # before_validation :do_stuff_before_validation + # after_validation :do_tuff_after_validation + # end + # + # Like other before_* callbacks if before_validation returns false + # then valid? will not be called. + extend ActiveSupport::Concern + + included do + include ActiveSupport::Callbacks + define_callbacks :validation, :terminator => "result == false", :scope => [:kind, :name] + end + + module ClassMethods + def before_validation(*args, &block) + options = args.last + if options.is_a?(Hash) && options[:on] + options[:if] = Array.wrap(options[:if]) + options[:if] << "self.validation_context == :#{options[:on]}" + end + set_callback(:validation, :before, *args, &block) + end + + def after_validation(*args, &block) + options = args.extract_options! + options[:prepend] = true + options[:if] = Array.wrap(options[:if]) + options[:if] << "!halted && value != false" + options[:if] << "self.validation_context == :#{options[:on]}" if options[:on] + set_callback(:validation, :after, *(args << options), &block) + end + end + + # Runs all the specified validations and returns true if no errors were added + # otherwise false. Context can optionally be supplied to define which callbacks + # to test against (the context is defined on the validations using :on). + def valid?(context = nil) + current_context, self.validation_context = validation_context, context + errors.clear + @validate_callback_result = nil + validation_callback_result = _run_validation_callbacks { @validate_callback_result = _run_validate_callbacks } + (validation_callback_result && @validate_callback_result) ? errors.empty? : false + ensure + self.validation_context = current_context + end + + end + end +end diff --git a/activemodel/test/cases/validations/callbacks_test.rb b/activemodel/test/cases/validations/callbacks_test.rb new file mode 100644 index 0000000000..08dcf254c2 --- /dev/null +++ b/activemodel/test/cases/validations/callbacks_test.rb @@ -0,0 +1,76 @@ +# encoding: utf-8 +require 'cases/helper' + +class Dog + include ActiveModel::Validations + + attr_accessor :name, :history + + def history + @history ||= [] + end +end + +class DogWithMethodCallbacks < Dog + before_validation :set_before_validation_marker + after_validation :set_after_validation_marker + + def set_before_validation_marker; self.history << 'before_validation_marker'; end + def set_after_validation_marker; self.history << 'after_validation_marker' ; end +end + +class DogValidtorsAreProc < Dog + before_validation { self.history << 'before_validation_marker' } + after_validation { self.history << 'after_validation_marker' } +end + +class DogWithTwoValidators < Dog + before_validation { self.history << 'before_validation_marker1' } + before_validation { self.history << 'before_validation_marker2' } +end + +class DogValidatorReturningFalse < Dog + before_validation { false } + before_validation { self.history << 'before_validation_marker2' } +end + +class DogWithMissingName < Dog + before_validation { self.history << 'before_validation_marker' } + validates_presence_of :name +end + +class CallbacksWithMethodNamesShouldBeCalled < ActiveModel::TestCase + + def test_before_validation_and_after_validation_callbacks_should_be_called + d = DogWithMethodCallbacks.new + d.valid? + assert_equal ['before_validation_marker', 'after_validation_marker'], d.history + end + + def test_before_validation_and_after_validation_callbacks_should_be_called_with_proc + d = DogValidtorsAreProc.new + d.valid? + assert_equal ['before_validation_marker', 'after_validation_marker'], d.history + end + + def test_before_validation_and_after_validation_callbacks_should_be_called_in_declared_order + d = DogWithTwoValidators.new + d.valid? + assert_equal ['before_validation_marker1', 'before_validation_marker2'], d.history + end + + def test_further_callbacks_should_not_be_called_if_before_validation_returns_false + d = DogValidatorReturningFalse.new + output = d.valid? + assert_equal [], d.history + assert_equal false, output + end + + def test_validation_test_should_be_done + d = DogWithMissingName.new + output = d.valid? + assert_equal ['before_validation_marker'], d.history + assert_equal false, output + end + +end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index def0fdaa2f..ef8dbdb6e5 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1874,6 +1874,7 @@ module ActiveRecord #:nodoc: extend ActiveSupport::DescendantsTracker include ActiveModel::Conversion + include ActiveModel::Validations::Callbacks include Validations extend CounterCache include Locking::Optimistic, Locking::Pessimistic diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 44fee12001..42b56a3cf8 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -235,7 +235,7 @@ module ActiveRecord included do extend ActiveModel::Callbacks - define_callbacks :validation, :terminator => "result == false", :scope => [:kind, :name] + attr_accessor :validation_context define_model_callbacks :initialize, :find, :only => :after define_model_callbacks :save, :create, :update, :destroy @@ -250,28 +250,11 @@ module ActiveRecord end end - def before_validation(*args, &block) - options = args.last - if options.is_a?(Hash) && options[:on] - options[:if] = Array.wrap(options[:if]) - options[:if] << "@_on_validate == :#{options[:on]}" - end - set_callback(:validation, :before, *args, &block) - end - - def after_validation(*args, &block) - options = args.extract_options! - options[:prepend] = true - options[:if] = Array.wrap(options[:if]) - options[:if] << "!halted && value != false" - options[:if] << "@_on_validate == :#{options[:on]}" if options[:on] - set_callback(:validation, :after, *(args << options), &block) - end end def valid?(*) #:nodoc: - @_on_validate = new_record? ? :create : :update - _run_validation_callbacks { super } + self.validation_context = new_record? ? :create : :update + super end def destroy #:nodoc: diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index be64e00bd1..6ef9382b2a 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -49,12 +49,12 @@ module ActiveRecord # Runs all the specified validations and returns true if no errors were added otherwise false. def valid?(context = nil) context ||= (new_record? ? :create : :update) - super(context) + output = super(context) deprecated_callback_method(:validate) deprecated_callback_method(:"validate_on_#{context}") - errors.empty? + errors.empty? && output end protected -- cgit v1.2.3 From 0247995d05b3cd3ff5fe32d5fbd8fdd866646909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 19 Jun 2010 18:18:45 +0200 Subject: ActiveModel::Validations::Callbacks should not be required by default. --- activemodel/lib/active_model/validations.rb | 19 ++++++++++++++++++- activemodel/lib/active_model/validations/callbacks.rb | 17 +++++------------ activemodel/test/cases/validations/callbacks_test.rb | 1 + activerecord/lib/active_record/base.rb | 1 - activerecord/lib/active_record/callbacks.rb | 10 ++-------- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 31516dc8a9..fa6bd91ff7 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -46,7 +46,6 @@ module ActiveModel module Validations extend ActiveSupport::Concern include ActiveSupport::Callbacks - include ActiveModel::Validations::Callbacks included do extend ActiveModel::Translation @@ -160,6 +159,17 @@ module ActiveModel @errors ||= Errors.new(self) end + # Runs all the specified validations and returns true if no errors were added + # otherwise false. Context can optionally be supplied to define which callbacks + # to test against (the context is defined on the validations using :on). + def valid?(context = nil) + current_context, self.validation_context = validation_context, context + errors.clear + run_validations! + ensure + self.validation_context = current_context + end + # Performs the opposite of valid?. Returns true if errors were added, # false otherwise. def invalid?(context = nil) @@ -184,6 +194,13 @@ module ActiveModel # end # alias :read_attribute_for_validation :send + + protected + + def run_validations! + _run_validate_callbacks + errors.empty? + end end end diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index 2c8798bcdd..afd65d3dd5 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -46,19 +46,12 @@ module ActiveModel end end - # Runs all the specified validations and returns true if no errors were added - # otherwise false. Context can optionally be supplied to define which callbacks - # to test against (the context is defined on the validations using :on). - def valid?(context = nil) - current_context, self.validation_context = validation_context, context - errors.clear - @validate_callback_result = nil - validation_callback_result = _run_validation_callbacks { @validate_callback_result = _run_validate_callbacks } - (validation_callback_result && @validate_callback_result) ? errors.empty? : false - ensure - self.validation_context = current_context - end + protected + # Overwrite run validations to include callbacks. + def run_validations! + _run_validation_callbacks { super } + end end end end diff --git a/activemodel/test/cases/validations/callbacks_test.rb b/activemodel/test/cases/validations/callbacks_test.rb index 08dcf254c2..67b21eb106 100644 --- a/activemodel/test/cases/validations/callbacks_test.rb +++ b/activemodel/test/cases/validations/callbacks_test.rb @@ -3,6 +3,7 @@ require 'cases/helper' class Dog include ActiveModel::Validations + include ActiveModel::Validations::Callbacks attr_accessor :name, :history diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index ef8dbdb6e5..def0fdaa2f 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1874,7 +1874,6 @@ module ActiveRecord #:nodoc: extend ActiveSupport::DescendantsTracker include ActiveModel::Conversion - include ActiveModel::Validations::Callbacks include Validations extend CounterCache include Locking::Optimistic, Locking::Pessimistic diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 42b56a3cf8..997c85ef8c 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -234,8 +234,7 @@ module ActiveRecord included do extend ActiveModel::Callbacks - - attr_accessor :validation_context + include ActiveModel::Validations::Callbacks define_model_callbacks :initialize, :find, :only => :after define_model_callbacks :save, :create, :update, :destroy @@ -249,12 +248,6 @@ module ActiveRecord send(meth.to_sym, meth.to_sym) end end - - end - - def valid?(*) #:nodoc: - self.validation_context = new_record? ? :create : :update - super end def destroy #:nodoc: @@ -269,6 +262,7 @@ module ActiveRecord end private + def create_or_update #:nodoc: _run_save_callbacks { super } end -- cgit v1.2.3 From 65ce3d12971afd15de6ea22a2fc5af3ba1faf124 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sat, 19 Jun 2010 20:52:55 +0100 Subject: Accept an object for :constraints option [#4904 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- actionpack/test/dispatch/routing_test.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0018b6485b..5d6147c48a 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -102,7 +102,7 @@ module ActionDispatch end def requirements - @requirements ||= (@options[:constraints] || {}).tap do |requirements| + @requirements ||= (@options[:constraints].is_a?(Hash) ? @options[:constraints] : {}).tap do |requirements| requirements.reverse_merge!(@scope[:constraints]) if @scope[:constraints] @options.each { |k, v| requirements[k] = v if v.is_a?(Regexp) } end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 899990c69d..c4cdc4b2a8 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -68,6 +68,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get 'admin/accounts' => "queenbee#accounts" end + get 'admin/passwords' => "queenbee#passwords", :constraints => ::TestRoutingMapper::IpRestrictor + scope 'pt', :name_prefix => 'pt' do resources :projects, :path_names => { :edit => 'editar', :new => 'novo' }, :path => 'projetos' do post :preview, :on => :new @@ -501,6 +503,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/admin/accounts', {}, {'REMOTE_ADDR' => '10.0.0.100'} assert_equal 'pass', @response.headers['X-Cascade'] + + get '/admin/passwords', {}, {'REMOTE_ADDR' => '192.168.1.100'} + assert_equal 'queenbee#passwords', @response.body + + get '/admin/passwords', {}, {'REMOTE_ADDR' => '10.0.0.100'} + assert_equal 'pass', @response.headers['X-Cascade'] end end -- cgit v1.2.3 From ed3f042e99949526f483d1f567e40031deea33d3 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sat, 19 Jun 2010 22:35:54 +0100 Subject: Make polymorphic_url and scaffolding work with uncountable resources [#3930 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../lib/action_controller/polymorphic_routes.rb | 3 ++- .../lib/action_controller/record_identifier.rb | 14 ++++++++++--- .../test/activerecord/polymorphic_routes_test.rb | 1 + .../test/controller/record_identifier_test.rb | 23 ++++++++++++++++++++-- .../erb/scaffold/templates/edit.html.erb | 2 +- .../generators/erb/scaffold/templates/new.html.erb | 2 +- .../erb/scaffold/templates/show.html.erb | 2 +- railties/lib/rails/generators/named_base.rb | 8 ++++++++ .../scaffold_controller/templates/controller.rb | 2 +- .../scaffold/templates/functional_test.rb | 2 +- railties/test/generators/named_base_test.rb | 10 ++++++++++ 11 files changed, 58 insertions(+), 11 deletions(-) diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb index 7f2eb4306b..bee50a7a3b 100644 --- a/actionpack/lib/action_controller/polymorphic_routes.rb +++ b/actionpack/lib/action_controller/polymorphic_routes.rb @@ -11,7 +11,7 @@ module ActionController # polymorphic_url([:admin, @article, @comment]) # # results in: - # + # # admin_article_comment_url(@article, @comment) # # == Usage within the framework @@ -166,6 +166,7 @@ module ActionController route << RecordIdentifier.__send__("plural_class_name", record) route = route.singularize if inflection == :singular route << "_" + route << "index_" if RecordIdentifier.uncountable?(record) && inflection == :plural end action_prefix(options) + route + routing_type(options).to_s diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb index 907c369218..d20c3b64c5 100644 --- a/actionpack/lib/action_controller/record_identifier.rb +++ b/actionpack/lib/action_controller/record_identifier.rb @@ -1,7 +1,7 @@ require 'active_support/core_ext/module' module ActionController - # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or + # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or # Active Resources or pretty much any other model type that has an id. These patterns are then used to try elevate # the view actions to a higher logical level. Example: # @@ -28,7 +28,7 @@ module ActionController # end # # As the example above shows, you can stop caring to a large extent what the actual id of the post is. You just know - # that one is being assigned and that the subsequent calls in redirect_to and the RJS expect that same naming + # that one is being assigned and that the subsequent calls in redirect_to and the RJS expect that same naming # convention and allows you to write less code if you follow it. module RecordIdentifier extend self @@ -59,7 +59,7 @@ module ActionController # If you need to address multiple instances of the same class in the same view, you can prefix the dom_id: # # dom_id(Post.find(45), :edit) # => "edit_post_45" - def dom_id(record, prefix = nil) + def dom_id(record, prefix = nil) if record_id = record_key_for_dom_id(record) "#{dom_class(record, prefix)}#{JOIN}#{record_id}" else @@ -102,6 +102,14 @@ module ActionController model_name_from_record_or_class(record_or_class).singular end + # Identifies whether the class name of a record or class is uncountable. Examples: + # + # uncountable?(Sheep) # => true + # uncountable?(Post) => false + def uncountable?(record_or_class) + plural_class_name(record_or_class) == singular_class_name(record_or_class) + end + private def model_name_from_record_or_class(record_or_class) (record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 9f5e8ec657..6e1e6cdd20 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -381,6 +381,7 @@ class PolymorphicRoutesTest < ActionController::TestCase with_test_routes do @series.save assert_equal "http://example.com/series/#{@series.id}", polymorphic_url(@series) + assert_equal "http://example.com/series", polymorphic_url(Series.new) end end diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb index 813dedc80d..6a84475758 100644 --- a/actionpack/test/controller/record_identifier_test.rb +++ b/actionpack/test/controller/record_identifier_test.rb @@ -13,6 +13,19 @@ class Comment end end +class Sheep + extend ActiveModel::Naming + include ActiveModel::Conversion + + attr_reader :id + def to_key; id ? [id] : nil end + def save; @id = 1 end + def new_record?; @id.nil? end + def name + @id.nil? ? 'new sheep' : "sheep ##{@id}" + end +end + class Comment::Nested < Comment; end class Test::Unit::TestCase @@ -20,7 +33,7 @@ class Test::Unit::TestCase def comments_url 'http://www.example.com/comments' end - + def comment_url(comment) "http://www.example.com/comments/#{comment.id}" end @@ -35,6 +48,7 @@ class RecordIdentifierTest < Test::Unit::TestCase @record = @klass.new @singular = 'comment' @plural = 'comments' + @uncountable = Sheep end def test_dom_id_with_new_record @@ -58,7 +72,7 @@ class RecordIdentifierTest < Test::Unit::TestCase def test_dom_class assert_equal @singular, dom_class(@record) end - + def test_dom_class_with_prefix assert_equal "custom_prefix_#{@singular}", dom_class(@record, :custom_prefix) end @@ -79,6 +93,11 @@ class RecordIdentifierTest < Test::Unit::TestCase assert_equal @plural, plural_class_name(@klass) end + def test_uncountable + assert_equal true, uncountable?(@uncountable) + assert_equal false, uncountable?(@klass) + end + private def method_missing(method, *args) RecordIdentifier.send(method, *args) diff --git a/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb index 5bc507ffc8..415f820206 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb @@ -3,4 +3,4 @@ <%%= render 'form' %> <%%= link_to 'Show', @<%= singular_name %> %> | -<%%= link_to 'Back', <%= plural_name %>_path %> +<%%= link_to 'Back', <%= index_helper %>_path %> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb index 9a1c489331..ddabc9d349 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb @@ -2,4 +2,4 @@ <%%= render 'form' %> -<%%= link_to 'Back', <%= plural_name %>_path %> +<%%= link_to 'Back', <%= index_helper %>_path %> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb index 6b3518717a..31b8253b35 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb @@ -9,4 +9,4 @@ <% end -%> <%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %> | -<%%= link_to 'Back', <%= plural_name %>_path %> +<%%= link_to 'Back', <%= index_helper %>_path %> diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 8d1dfbd947..72ec2856d0 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -46,6 +46,14 @@ module Rails end end + def uncountable? + singular_name == plural_name + end + + def index_helper + uncountable? ? "#{plural_name}_index" : plural_name + end + # Tries to retrieve the application name or simple return application. def application_name if defined?(Rails) && Rails.application diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index bbdce669dc..b5f19b6d15 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -78,7 +78,7 @@ class <%= controller_class_name %>Controller < ApplicationController @<%= orm_instance.destroy %> respond_to do |format| - format.html { redirect_to(<%= table_name %>_url) } + format.html { redirect_to(<%= index_helper %>_url) } format.xml { head :ok } end end diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb index 4f8ddbffcf..d5d3d6d5cd 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb @@ -46,6 +46,6 @@ class <%= controller_class_name %>ControllerTest < ActionController::TestCase delete :destroy, :id => @<%= file_name %>.to_param end - assert_redirected_to <%= table_name %>_path + assert_redirected_to <%= index_helper %>_path end end diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb index e73dd237fb..1badae0713 100644 --- a/railties/test/generators/named_base_test.rb +++ b/railties/test/generators/named_base_test.rb @@ -93,6 +93,16 @@ class NamedBaseTest < Rails::Generators::TestCase assert_name g, "application", :application_name end + def test_index_helper + g = generator ['Post'] + assert_name g, 'posts', :index_helper + end + + def test_index_helper_with_uncountable + g = generator ['Sheep'] + assert_name g, 'sheep_index', :index_helper + end + protected def assert_name(generator, value, method) -- cgit v1.2.3 From 1f84061c5c271647dc5f7f1311e365e134130e0f Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sat, 19 Jun 2010 12:53:09 +0100 Subject: Don't use module to work out shallow name prefix and path as it may not accurately reflect the actual namespace [#4899 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/routing/mapper.rb | 26 ++++++++++++++++-------- actionpack/test/dispatch/routing_test.rb | 17 +++++++++++++++- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 5d6147c48a..c31f681411 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -33,7 +33,7 @@ module ActionDispatch end class Mapping #:nodoc: - IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow] + IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix] def initialize(set, scope, args) @set, @scope = set, scope @@ -343,7 +343,7 @@ module ActionDispatch def namespace(path) path = path.to_s - scope(:path => path, :name_prefix => path, :module => path) { yield } + scope(:path => path, :name_prefix => path, :module => path, :shallow_path => path, :shallow_prefix => path) { yield } end def constraints(constraints = {}) @@ -378,10 +378,18 @@ module ActionDispatch Mapper.normalize_path("#{parent}/#{child}") end + def merge_shallow_path_scope(parent, child) + Mapper.normalize_path("#{parent}/#{child}") + end + def merge_name_prefix_scope(parent, child) parent ? "#{parent}_#{child}" : child end + def merge_shallow_prefix_scope(parent, child) + parent ? "#{parent}_#{child}" : child + end + def merge_module_scope(parent, child) parent ? "#{parent}/#{child}" : child end @@ -662,10 +670,10 @@ module ActionDispatch with_scope_level(:nested) do if parent_resource.shallow? with_exclusive_scope do - if @scope[:module].blank? + if @scope[:shallow_path].blank? scope(*parent_resource.nested_scope) { yield } else - scope(@scope[:module], :name_prefix => @scope[:module].tr('/', '_')) do + scope(@scope[:shallow_path], :name_prefix => @scope[:shallow_prefix]) do scope(*parent_resource.nested_scope) { yield } end end @@ -848,7 +856,7 @@ module ActionDispatch "#{@scope[:path]}(.:format)" when :show, :update, :destroy if parent_resource.shallow? - "#{@scope[:module]}/#{parent_resource.path}/:id(.:format)" + "#{@scope[:shallow_path]}/#{parent_resource.path}/:id(.:format)" else "#{@scope[:path]}(.:format)" end @@ -856,7 +864,7 @@ module ActionDispatch "#{@scope[:path]}/#{action_path(:new)}(.:format)" when :edit if parent_resource.shallow? - "#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(:edit)}(.:format)" + "#{@scope[:shallow_path]}/#{parent_resource.path}/:id/#{action_path(:edit)}(.:format)" else "#{@scope[:path]}/#{action_path(:edit)}(.:format)" end @@ -866,7 +874,7 @@ module ActionDispatch "#{@scope[:path]}/#{action_path(action)}(.:format)" else if parent_resource.shallow? - "#{@scope[:module]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)" + "#{@scope[:shallow_path]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)" else "#{@scope[:path]}/#{action_path(action)}(.:format)" end @@ -880,7 +888,7 @@ module ActionDispatch @scope[:path] else if parent_resource.shallow? - "#{@scope[:module]}/#{parent_resource.path}/:id" + "#{@scope[:shallow_path]}/#{parent_resource.path}/:id" else @scope[:path] end @@ -901,7 +909,7 @@ module ActionDispatch def name_for_action(action) name_prefix = @scope[:name_prefix].blank? ? "" : "#{@scope[:name_prefix]}_" - shallow_prefix = @scope[:module].blank? ? "" : "#{@scope[:module].tr('/', '_')}_" + shallow_prefix = @scope[:shallow_prefix].blank? ? "" : "#{@scope[:shallow_prefix]}_" case action when :index, :create diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index c4cdc4b2a8..495255c22b 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -278,8 +278,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resource :dashboard, :constraints => { :ip => /192\.168\.1\.\d{1,3}/ } - scope :module => 'api' do + scope :module => :api do resource :token + resources :errors, :shallow => true do + resources :notices + end end scope :path => 'api' do @@ -1350,6 +1353,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_shallow_nested_routes_ignore_module + with_test_routes do + get '/errors/1/notices' + assert_equal 'api/notices#index', @response.body + assert_equal '/errors/1/notices', error_notices_path(:error_id => '1') + + get '/notices/1' + assert_equal 'api/notices#show', @response.body + assert_equal '/notices/1', notice_path(:id => '1') + end + end + private def with_test_routes yield -- cgit v1.2.3 From 86002a0dfe45c972a2498e33a6a2a882804603bd Mon Sep 17 00:00:00 2001 From: David Chelimsky Date: Fri, 18 Jun 2010 22:20:10 -0500 Subject: Support render_template in view tests. Useful for specifying which partials are rendered under different conditions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#4903 state:resolved] Signed-off-by: José Valim --- actionpack/lib/action_view/test_case.rb | 1 + actionpack/test/template/test_case_test.rb | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 15d424be74..306f59f9ca 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -84,6 +84,7 @@ module ActionView def setup_with_controller @controller = ActionView::TestCase::TestController.new + @request = @controller.request @output_buffer = ActiveSupport::SafeBuffer.new @rendered = '' diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index 9b50ea8a42..c365aec841 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -218,4 +218,12 @@ module ActionView end end end + + class RenderTemplateTest < ActionView::TestCase + test "render template" do + controller.controller_path = "test" + render(:template => "test/calling_partial_with_layout") + assert_template "partial_for_use_in_layout" + end + end end -- cgit v1.2.3 From 98a5188f518b1e8cfa9d7aa59856e5b32985eb46 Mon Sep 17 00:00:00 2001 From: Chris Griego Date: Sat, 19 Jun 2010 01:10:57 -0500 Subject: Strip trailing whitespace from generated applications [#4905 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/lib/rails/generators/rails/app/templates/README | 8 ++++---- .../generators/rails/app/templates/config/databases/mysql.yml | 2 +- .../generators/rails/app/templates/config/databases/oracle.yml | 2 +- .../rails/app/templates/config/initializers/inflections.rb | 2 +- .../rails/app/templates/config/initializers/secret_token.rb.tt | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/templates/README b/railties/lib/rails/generators/rails/app/templates/README index 9ec6db6d71..e2764dee03 100644 --- a/railties/lib/rails/generators/rails/app/templates/README +++ b/railties/lib/rails/generators/rails/app/templates/README @@ -37,7 +37,7 @@ link:files/vendor/rails/actionpack/README.html. 3. Go to http://localhost:3000/ and you'll see: "Welcome aboard: You're riding the Rails!" -4. Follow the guidelines to start developing your application. You can find +4. Follow the guidelines to start developing your application. You can find the following resources handy: * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html @@ -71,13 +71,13 @@ The result will be a message in your log file along the lines of: More information on how to use the logger is at http://www.ruby-doc.org/core/ -Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are several books available online as well: * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) -These two books will bring you up to speed on the Ruby language and also on +These two books will bring you up to speed on the Ruby language and also on programming in general. @@ -199,7 +199,7 @@ app/controllers ApplicationController which itself descends from ActionController::Base. app/models - Holds models that should be named like post.rb. Models descend from + Holds models that should be named like post.rb. Models descend from ActiveRecord::Base by default. app/views diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml index 6bf2f7b1fd..ffc8a0a8cb 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml @@ -52,7 +52,7 @@ production: database: <%= app_name %>_production pool: 5 username: root - password: + password: <% if mysql_socket -%> socket: <%= mysql_socket %> <% else -%> diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml index a1883f6256..f99ee937f3 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml @@ -36,4 +36,4 @@ production: adapter: oracle database: <%= app_name %>_production username: <%= app_name %> - password: + password: diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb index d531b8bb82..9e8b0131f8 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb @@ -1,6 +1,6 @@ # Be sure to restart your server when you modify this file. -# Add new inflection rules using the following format +# Add new inflection rules using the following format # (all these examples are active by default): # ActiveSupport::Inflector.inflections do |inflect| # inflect.plural /^(ox)$/i, '\1en' diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt index c2fa31aadb..22aa576f5d 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt @@ -2,6 +2,6 @@ # Your secret key for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! -# Make sure the secret is at least 30 characters and all random, +# Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. Rails.application.config.secret_token = '<%= app_secret %>' -- cgit v1.2.3 From f664c57fe854c230d25c448b941569b81860fa79 Mon Sep 17 00:00:00 2001 From: James Le Cuirot Date: Sat, 12 Jun 2010 11:55:31 +0100 Subject: Don't overwrite unsaved updates when loading an association but preserve the order of the loaded records. Reapplied from before but now allows already-saved records to be refreshed. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#4830 state:resolved] Signed-off-by: José Valim --- .../associations/association_collection.rb | 6 +++++- activerecord/test/cases/nested_attributes_test.rb | 21 +++++++++++++++++++++ activerecord/test/models/pirate.rb | 4 ++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index d9903243ce..bd67516518 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -388,7 +388,11 @@ module ActiveRecord begin if !loaded? if @target.is_a?(Array) && @target.any? - @target = find_target + @target.find_all {|t| t.new_record? } + @target = find_target.map do |f| + i = @target.index(f) + t = @target.delete_at(i) if i + (t && t.changed?) ? t : f + end + @target else @target = find_target end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 685b11cb03..65d6080ea5 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -466,6 +466,27 @@ module NestedAttributesOnACollectionAssociationTests assert_equal 'Grace OMalley', @child_1.reload.name end + def test_should_not_overwrite_unsaved_updates_when_loading_association + @pirate.reload + @pirate.send(association_setter, [{ :id => @child_1.id, :name => 'Grace OMalley' }]) + assert_equal 'Grace OMalley', @pirate.send(@association_name).send(:load_target).find { |r| r.id == @child_1.id }.name + end + + def test_should_preserve_order_when_not_overwriting_unsaved_updates + @pirate.reload + @pirate.send(association_setter, [{ :id => @child_1.id, :name => 'Grace OMalley' }]) + assert_equal @child_1.id, @pirate.send(@association_name).send(:load_target).first.id + end + + def test_should_refresh_saved_records_when_not_overwriting_unsaved_updates + @pirate.reload + record = @pirate.class.reflect_on_association(@association_name).klass.new(:name => 'Grace OMalley') + @pirate.send(@association_name) << record + record.save! + @pirate.send(@association_name).last.update_attributes!(:name => 'Polly') + assert_equal 'Polly', @pirate.send(@association_name).send(:load_target).last.name + end + def test_should_take_a_hash_with_composite_id_keys_and_assign_the_attributes_to_the_associated_models @child_1.stubs(:id).returns('ABC1X') @child_2.stubs(:id).returns('ABC2X') diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb index f1dbe32c6e..d89c8cf381 100644 --- a/activerecord/test/models/pirate.rb +++ b/activerecord/test/models/pirate.rb @@ -1,7 +1,7 @@ class Pirate < ActiveRecord::Base belongs_to :parrot, :validate => true belongs_to :non_validated_parrot, :class_name => 'Parrot' - has_and_belongs_to_many :parrots, :validate => true + has_and_belongs_to_many :parrots, :validate => true, :order => 'parrots.id ASC' has_and_belongs_to_many :non_validated_parrots, :class_name => 'Parrot' has_and_belongs_to_many :parrots_with_method_callbacks, :class_name => "Parrot", :before_add => :log_before_add, @@ -21,7 +21,7 @@ class Pirate < ActiveRecord::Base has_one :ship has_one :update_only_ship, :class_name => 'Ship' has_one :non_validated_ship, :class_name => 'Ship' - has_many :birds + has_many :birds, :order => 'birds.id ASC' has_many :birds_with_method_callbacks, :class_name => "Bird", :before_add => :log_before_add, :after_add => :log_after_add, -- cgit v1.2.3 From 02ea1aa88ce92ee3fa0cc87c719f6fc6c1428bcc Mon Sep 17 00:00:00 2001 From: Sam Elliott and Santiago Pastorino Date: Sun, 13 Jun 2010 20:58:36 -0300 Subject: <=> is defined twice on multibyte/chars.rb for Ruby < 1.9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#4850 state:committed] Signed-off-by: José Valim --- .../lib/active_support/multibyte/chars.rb | 24 +++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index d6ccb4bac1..a275176b4a 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -50,10 +50,6 @@ module ActiveSupport #:nodoc: end end - def <=>(other) - @wrapped_string <=> other - end - # Forward all undefined methods to the wrapped string. def method_missing(method, *args, &block) if method.to_s =~ /!$/ @@ -87,6 +83,16 @@ module ActiveSupport #:nodoc: include Comparable + # Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, + # equal or after the object on the right side of the operation. It accepts any object that implements +to_s+. + # See String#<=> for more details. + # + # Example: + # 'é'.mb_chars <=> 'ü'.mb_chars #=> -1 + def <=>(other) + @wrapped_string <=> other.to_s + end + if RUBY_VERSION < "1.9" # Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns # +false+ otherwise. @@ -94,16 +100,6 @@ module ActiveSupport #:nodoc: $KCODE == 'UTF8' && consumes?(string) end - # Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, - # equal or after the object on the right side of the operation. It accepts any object that implements +to_s+. - # See String#<=> for more details. - # - # Example: - # 'é'.mb_chars <=> 'ü'.mb_chars #=> -1 - def <=>(other) - @wrapped_string <=> other.to_s - end - # Returns a new Chars object containing the _other_ object concatenated to the string. # # Example: -- cgit v1.2.3 From e061212e86ef0342fad1211fd980fc4b2195fe69 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Mon, 14 Jun 2010 13:39:58 -0300 Subject: Refactor build_arel: move joins out and simplify havings. [#4860 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../lib/active_record/relation/query_methods.rb | 92 +++++++++++----------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 7a48a6596a..50e94134f5 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -116,45 +116,7 @@ module ActiveRecord def build_arel arel = table - joined_associations = [] - association_joins = [] - - joins = @joins_values.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq - - joins.each do |join| - association_joins << join if [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join) - end - - stashed_association_joins = joins.select {|j| j.is_a?(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation)} - - non_association_joins = (joins - association_joins - stashed_association_joins).reject {|j| j.blank?} - custom_joins = custom_join_sql(*non_association_joins) - - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins) - - join_dependency.graft(*stashed_association_joins) - - @implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty? - - to_join = [] - - join_dependency.join_associations.each do |association| - if (association_relation = association.relation).is_a?(Array) - to_join << [association_relation.first, association.join_class, association.association_join.first] - to_join << [association_relation.last, association.join_class, association.association_join.last] - else - to_join << [association_relation, association.join_class, association.association_join] - end - end - - to_join.each do |tj| - unless joined_associations.detect {|ja| ja[0] == tj[0] && ja[1] == tj[1] && ja[2] == tj[2] } - joined_associations << tj - arel = arel.join(tj[0], tj[1]).on(*tj[2]) - end - end - - arel = arel.join(custom_joins) + arel = build_joins(arel, @joins_values) if @joins_values.present? @where_values.uniq.each do |where| next if where.blank? @@ -168,9 +130,7 @@ module ActiveRecord end end - @having_values.uniq.each do |h| - arel = h.is_a?(String) ? arel.having(h) : arel.having(*h) - end + arel = arel.having(*@having_values.uniq.select{|h| h.present?}) arel = arel.take(@limit_value) if @limit_value.present? arel = arel.skip(@offset_value) if @offset_value.present? @@ -181,18 +141,16 @@ module ActiveRecord selects = @select_values.uniq - quoted_table_name = @klass.quoted_table_name - if selects.present? selects.each do |s| @implicit_readonly = false arel = arel.project(s) if s.present? end else - arel = arel.project(quoted_table_name + '.*') + arel = arel.project(@klass.quoted_table_name + '.*') end - arel = @from_value.present? ? arel.from(@from_value) : arel.from(quoted_table_name) + arel = @from_value.present? ? arel.from(@from_value) : arel.from(@klass.quoted_table_name) case @lock_value when TrueClass @@ -221,6 +179,48 @@ module ActiveRecord private + def build_joins(relation, joins) + joined_associations = [] + association_joins = [] + + joins = @joins_values.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq + + joins.each do |join| + association_joins << join if [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join) + end + + stashed_association_joins = joins.select {|j| j.is_a?(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation)} + + non_association_joins = (joins - association_joins - stashed_association_joins).reject {|j| j.blank?} + custom_joins = custom_join_sql(*non_association_joins) + + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins) + + join_dependency.graft(*stashed_association_joins) + + @implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty? + + to_join = [] + + join_dependency.join_associations.each do |association| + if (association_relation = association.relation).is_a?(Array) + to_join << [association_relation.first, association.join_class, association.association_join.first] + to_join << [association_relation.last, association.join_class, association.association_join.last] + else + to_join << [association_relation, association.join_class, association.association_join] + end + end + + to_join.each do |tj| + unless joined_associations.detect {|ja| ja[0] == tj[0] && ja[1] == tj[1] && ja[2] == tj[2] } + joined_associations << tj + relation = relation.join(tj[0], tj[1]).on(*tj[2]) + end + end + + relation.join(custom_joins) + end + def apply_modules(modules) values = Array.wrap(modules) @extensions += values if values.present? -- cgit v1.2.3 From 95a8f252c028c94b70cce4888bce42b7e9e30786 Mon Sep 17 00:00:00 2001 From: rohit Date: Wed, 16 Jun 2010 18:50:50 +0530 Subject: remove executable permission from files that don't need it. [#4802 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/http/request.rb | 0 activemodel/Rakefile | 0 activerecord/examples/performance.rb | 0 activerecord/lib/active_record/associations.rb | 0 activerecord/lib/active_record/base.rb | 0 activerecord/lib/active_record/connection_adapters/abstract_adapter.rb | 0 activerecord/test/cases/base_test.rb | 0 activerecord/test/cases/counter_cache_test.rb | 0 activesupport/bin/generate_tables | 0 activesupport/lib/active_support/core_ext/object/to_param.rb | 0 railties/guides/assets/javascripts/code_highlighter.js | 0 railties/guides/assets/javascripts/guides.js | 0 railties/guides/assets/stylesheets/print.css | 0 railties/guides/assets/stylesheets/reset.css | 0 railties/guides/assets/stylesheets/style.css | 0 railties/lib/rails/commands/generate.rb | 0 railties/lib/rails/generators/rails/app/templates/Rakefile | 0 17 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 actionpack/lib/action_dispatch/http/request.rb mode change 100755 => 100644 activemodel/Rakefile mode change 100755 => 100644 activerecord/examples/performance.rb mode change 100755 => 100644 activerecord/lib/active_record/associations.rb mode change 100755 => 100644 activerecord/lib/active_record/base.rb mode change 100755 => 100644 activerecord/lib/active_record/connection_adapters/abstract_adapter.rb mode change 100755 => 100644 activerecord/test/cases/base_test.rb mode change 100755 => 100644 activerecord/test/cases/counter_cache_test.rb mode change 100755 => 100644 activesupport/bin/generate_tables mode change 100755 => 100644 activesupport/lib/active_support/core_ext/object/to_param.rb mode change 100755 => 100644 railties/guides/assets/javascripts/code_highlighter.js mode change 100755 => 100644 railties/guides/assets/javascripts/guides.js mode change 100755 => 100644 railties/guides/assets/stylesheets/print.css mode change 100755 => 100644 railties/guides/assets/stylesheets/reset.css mode change 100755 => 100644 railties/guides/assets/stylesheets/style.css mode change 100755 => 100644 railties/lib/rails/commands/generate.rb mode change 100755 => 100644 railties/lib/rails/generators/rails/app/templates/Rakefile diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb old mode 100755 new mode 100644 diff --git a/activemodel/Rakefile b/activemodel/Rakefile old mode 100755 new mode 100644 diff --git a/activerecord/examples/performance.rb b/activerecord/examples/performance.rb old mode 100755 new mode 100644 diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb old mode 100755 new mode 100644 diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb old mode 100755 new mode 100644 diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb old mode 100755 new mode 100644 diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb old mode 100755 new mode 100644 diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb old mode 100755 new mode 100644 diff --git a/activesupport/bin/generate_tables b/activesupport/bin/generate_tables old mode 100755 new mode 100644 diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb old mode 100755 new mode 100644 diff --git a/railties/guides/assets/javascripts/code_highlighter.js b/railties/guides/assets/javascripts/code_highlighter.js old mode 100755 new mode 100644 diff --git a/railties/guides/assets/javascripts/guides.js b/railties/guides/assets/javascripts/guides.js old mode 100755 new mode 100644 diff --git a/railties/guides/assets/stylesheets/print.css b/railties/guides/assets/stylesheets/print.css old mode 100755 new mode 100644 diff --git a/railties/guides/assets/stylesheets/reset.css b/railties/guides/assets/stylesheets/reset.css old mode 100755 new mode 100644 diff --git a/railties/guides/assets/stylesheets/style.css b/railties/guides/assets/stylesheets/style.css old mode 100755 new mode 100644 diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb old mode 100755 new mode 100644 diff --git a/railties/lib/rails/generators/rails/app/templates/Rakefile b/railties/lib/rails/generators/rails/app/templates/Rakefile old mode 100755 new mode 100644 -- cgit v1.2.3 From 667522ca9834ce1f173a3421fb0bf0f555324c6f Mon Sep 17 00:00:00 2001 From: Norman Clarke Date: Fri, 28 May 2010 16:36:22 -0300 Subject: Adds titleize/titlecase to AS::Multibyte::Chars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#2794 state:resolved] Signed-off-by: José Valim --- activesupport/lib/active_support/multibyte/chars.rb | 10 ++++++++++ activesupport/test/multibyte_chars_test.rb | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index a275176b4a..04193bfa65 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -371,6 +371,16 @@ module ActiveSupport #:nodoc: (slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase end + # Capitalizes the first letter of every word, when possible. + # + # Example: + # "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró" + # "日本語".mb_chars.titleize # => "日本語" + def titleize + chars(downcase.to_s.gsub(/\b('?[\S])/u) { Unicode.apply_mapping $1, :uppercase_mapping }) + end + alias_method :titlecase, :titleize + # Returns the KC normalization of the string by default. NFKC is considered the best normalization form for # passing strings to databases and validations. # diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index f7a5834527..602828ef5f 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -443,6 +443,11 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal 'Abc', 'abc'.mb_chars.capitalize end + def test_titleize_should_work_on_ascii_characters + assert_equal '', ''.mb_chars.titleize + assert_equal 'Abc Abc', 'abc abc'.mb_chars.titleize + end + def test_respond_to_knows_which_methods_the_proxy_responds_to assert ''.mb_chars.respond_to?(:slice) # Defined on Chars assert ''.mb_chars.respond_to?(:capitalize!) # Defined on Chars @@ -480,6 +485,15 @@ class MultibyteCharsExtrasTest < Test::Unit::TestCase end end + def test_titleize_should_be_unicode_aware + assert_equal "Él Que Se Enteró", chars("ÉL QUE SE ENTERÓ").titleize + assert_equal "Абвг Абвг", chars("аБвг аБвг").titleize + end + + def test_titleize_should_not_affect_characters_that_do_not_case_fold + assert_equal "日本語", chars("日本語").titleize + end + def test_limit_should_not_break_on_blank_strings example = chars('') assert_equal example, example.limit(0) -- cgit v1.2.3 From bb6cd6d3ec02996c7dd11a4bb96381da18b7de8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarsoly=20Andr=C3=A1s?= Date: Sat, 29 May 2010 22:09:14 +0200 Subject: Use Rack::Utils.bytesize when calculating content-length of exception pages. [#4727 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_dispatch/middleware/show_exceptions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 0a6d2bfc8a..e095b51342 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -122,7 +122,7 @@ module ActionDispatch end def render(status, body) - [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, [body]] + [status, {'Content-Type' => 'text/html', 'Content-Length' => body.bytesize.to_s}, [body]] end def public_path -- cgit v1.2.3 From bb324693ab8e197b369b90e2c3b46d67395a58e5 Mon Sep 17 00:00:00 2001 From: Ryan Duryea Date: Tue, 4 May 2010 11:49:22 -0700 Subject: Pass rack the absolute path of server's pid file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running as a daemon, rack will cd to "/" and paths relative to the root of the rails app aren't valid when rack is setting up. Because of this, "rails server -d" was failing silently when trying to write it's pid file Signed-off-by: José Valim --- railties/lib/rails/commands/server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 3f74cd49fc..861baa297e 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -83,7 +83,7 @@ module Rails :environment => (ENV['RAILS_ENV'] || "development").dup, :daemonize => false, :debugger => false, - :pid => "tmp/pids/server.pid" + :pid => File.expand_path("tmp/pids/server.pid") }) end end -- cgit v1.2.3 From 73df48083a8e0bdb10752c1b481549caac35b6cf Mon Sep 17 00:00:00 2001 From: Ryan Duryea Date: Wed, 5 May 2010 11:42:10 -0700 Subject: Added absolute path for config.ru as well. Turns out this is also needed to fix the daemon issue under ruby 1.8.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [#4531 state:resolved] Signed-off-by: José Valim --- railties/lib/rails/commands/server.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 861baa297e..cb9b871875 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -83,7 +83,8 @@ module Rails :environment => (ENV['RAILS_ENV'] || "development").dup, :daemonize => false, :debugger => false, - :pid => File.expand_path("tmp/pids/server.pid") + :pid => File.expand_path("tmp/pids/server.pid"), + :config => File.expand_path("config.ru") }) end end -- cgit v1.2.3 From 96f5e59a26329aa972b8061a818410b0b378f306 Mon Sep 17 00:00:00 2001 From: Jan De Poorter Date: Mon, 7 Jun 2010 15:03:07 +0200 Subject: Make sure a namespaced <%= render form %> still renders the _form partial [#4784 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_view/render/partials.rb | 2 +- actionpack/test/controller/render_test.rb | 11 +++++++++++ actionpack/test/fixtures/fun/games/_form.erb | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 actionpack/test/fixtures/fun/games/_form.erb diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 85f67d4f14..fd896c263d 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -316,7 +316,7 @@ module ActionView object.class.model_name.partial_path.dup.tap do |partial| path = @view.controller_path - partial.insert(0, "#{File.dirname(path)}/") if path.include?(?/) + partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/) end end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index e3ed097c67..a57a12f271 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -7,6 +7,10 @@ module Fun # :ported: def hello_world end + + def nested_partial_with_form_builder + render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, view_context, {}, Proc.new {}) + end end end @@ -1230,6 +1234,13 @@ class RenderTest < ActionController::TestCase assert_match(/