aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md2
-rw-r--r--actionpack/lib/action_controller/metal/flash.rb6
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb3
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb19
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb10
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb121
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb2
-rw-r--r--actionpack/test/controller/flash_test.rb1
-rw-r--r--actionpack/test/dispatch/routing/inspector_test.rb170
-rw-r--r--activemodel/lib/active_model/conversion.rb18
-rw-r--r--activemodel/lib/active_model/mass_assignment_security.rb6
-rw-r--r--activemodel/lib/active_model/serialization.rb50
-rw-r--r--activemodel/lib/active_model/serializers/json.rb8
-rw-r--r--activemodel/lib/active_model/validations/acceptance.rb20
-rw-r--r--activemodel/lib/active_model/validations/clusivity.rb2
-rw-r--r--activemodel/lib/active_model/validations/confirmation.rb23
-rw-r--r--activemodel/lib/active_model/validations/exclusion.rb31
-rw-r--r--activemodel/lib/active_model/validations/format.rb39
-rw-r--r--activemodel/lib/active_model/validations/inclusion.rb37
-rw-r--r--activemodel/lib/active_model/validations/length.rb50
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb50
-rw-r--r--activemodel/lib/active_model/validations/presence.rb21
-rw-r--r--activemodel/lib/active_model/validator.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb6
-rw-r--r--activerecord/lib/active_record/relation.rb5
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb33
-rw-r--r--activerecord/lib/active_record/scoping/default.rb8
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb18
-rw-r--r--activerecord/test/cases/tasks/database_tasks_test.rb16
-rw-r--r--guides/source/active_record_querying.textile28
-rw-r--r--railties/lib/rails/application.rb4
-rw-r--r--railties/lib/rails/engine.rb3
-rw-r--r--railties/lib/rails/info_controller.rb3
-rw-r--r--railties/lib/rails/tasks/routes.rake4
35 files changed, 620 insertions, 208 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 67c9e04ab2..a616eaa09c 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* Add routes to page while debugging a RoutingError in development. *Richard Schneeman and Mattt Thompson*
+
* Add `ActionController::Flash.add_flash_types` method to allow people to register their own flash types. e.g.:
class ApplicationController
diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb
index 47e71371e3..b078beb675 100644
--- a/actionpack/lib/action_controller/metal/flash.rb
+++ b/actionpack/lib/action_controller/metal/flash.rb
@@ -3,10 +3,10 @@ module ActionController #:nodoc:
extend ActiveSupport::Concern
included do
- class_attribute :_flash_types, :instance_methods => false
+ class_attribute :_flash_types, instance_accessor: false
self._flash_types = []
- delegate :flash, :to => :request
+ delegate :flash, to: :request
add_flash_types(:alert, :notice)
end
@@ -14,7 +14,7 @@ module ActionController #:nodoc:
def add_flash_types(*types)
types.each do |type|
next if _flash_types.include?(type)
-
+
define_method(type) do
request.flash[type]
end
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index eeb37db2e7..9f3c997024 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -139,9 +139,6 @@ module ActionController #:nodoc:
# session or flash after the template starts rendering will not propagate
# to the client.
#
- # If you try to modify cookies, session or flash, an <tt>ActionDispatch::ClosedError</tt>
- # will be raised, showing those objects are closed for modification.
- #
# == Middlewares
#
# Middlewares that need to manipulate the body won't work with streaming.
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index b903f98761..af3e6b3557 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -1,5 +1,7 @@
require 'action_dispatch/http/request'
require 'action_dispatch/middleware/exception_wrapper'
+require 'action_dispatch/routing/inspector'
+
module ActionDispatch
# This middleware is responsible for logging exceptions and
@@ -7,8 +9,9 @@ module ActionDispatch
class DebugExceptions
RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates')
- def initialize(app)
- @app = app
+ def initialize(app, routes_app = nil)
+ @app = app
+ @routes_app = routes_app
end
def call(env)
@@ -39,7 +42,8 @@ module ActionDispatch
:exception => wrapper.exception,
:application_trace => wrapper.application_trace,
:framework_trace => wrapper.framework_trace,
- :full_trace => wrapper.full_trace
+ :full_trace => wrapper.full_trace,
+ :routes => formatted_routes(exception)
)
file = "rescues/#{wrapper.rescue_template}"
@@ -78,5 +82,14 @@ module ActionDispatch
def stderr_logger
@stderr_logger ||= ActiveSupport::Logger.new($stderr)
end
+
+ private
+ def formatted_routes(exception)
+ return false unless @routes_app.respond_to?(:routes)
+ if exception.is_a?(ActionController::RoutingError) || exception.is_a?(ActionView::Template::Error)
+ inspector = ActionDispatch::Routing::RouteInspector.new
+ inspector.format(@routes_app.routes.routes).join("\n")
+ end
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
index 177d383e94..8c594c1523 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
@@ -10,8 +10,14 @@
</ol>
</p>
<% end %>
+<%= render :template => "rescues/_trace" %>
+
+<h2>
+ Routes
+</h2>
+
<p>
- Try running <code>rake routes</code> for more information on available routes.
+ Routes match in priority from top to bottom
</p>
-<%= render :template => "rescues/_trace" %>
+<p><pre><%= @routes %></pre></p>
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
new file mode 100644
index 0000000000..17e19453ea
--- /dev/null
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -0,0 +1,121 @@
+require 'delegate'
+
+module ActionDispatch
+ module Routing
+ class RouteWrapper < SimpleDelegator
+ def endpoint
+ rack_app ? rack_app.inspect : "#{controller}##{action}"
+ end
+
+ def constraints
+ requirements.except(:controller, :action)
+ end
+
+ def rack_app(app = self.app)
+ @rack_app ||= begin
+ class_name = app.class.name.to_s
+ if class_name == "ActionDispatch::Routing::Mapper::Constraints"
+ rack_app(app.app)
+ elsif ActionDispatch::Routing::Redirect === app || class_name !~ /^ActionDispatch::Routing/
+ app
+ end
+ end
+ end
+
+ def verb
+ super.source.gsub(/[$^]/, '')
+ end
+
+ def path
+ super.spec.to_s
+ end
+
+ def name
+ super.to_s
+ end
+
+ def reqs
+ @reqs ||= begin
+ reqs = endpoint
+ reqs += " #{constraints.inspect}" unless constraints.empty?
+ reqs
+ end
+ end
+
+ def controller
+ requirements[:controller] || ':controller'
+ end
+
+ def action
+ requirements[:action] || ':action'
+ end
+
+ def internal?
+ path =~ %r{/rails/info.*|^#{Rails.application.config.assets.prefix}}
+ end
+
+ def engine?
+ rack_app && rack_app.respond_to?(:routes)
+ end
+ end
+
+ ##
+ # This class is just used for displaying route information when someone
+ # executes `rake routes`. People should not use this class.
+ class RouteInspector # :nodoc:
+ def initialize
+ @engines = Hash.new
+ end
+
+ def format(all_routes, filter = nil)
+ if filter
+ all_routes = all_routes.select{ |route| route.defaults[:controller] == filter }
+ end
+
+ routes = collect_routes(all_routes)
+
+ formatted_routes(routes) +
+ formatted_routes_for_engines
+ end
+
+ def collect_routes(routes)
+ routes = routes.collect do |route|
+ RouteWrapper.new(route)
+ end.reject do |route|
+ route.internal?
+ end.collect do |route|
+ collect_engine_routes(route)
+
+ {:name => route.name, :verb => route.verb, :path => route.path, :reqs => route.reqs }
+ end
+ end
+
+ def collect_engine_routes(route)
+ name = route.endpoint
+ return unless route.engine?
+ return if @engines[name]
+
+ routes = route.rack_app.routes
+ if routes.is_a?(ActionDispatch::Routing::RouteSet)
+ @engines[name] = collect_routes(routes.routes)
+ end
+ end
+
+ def formatted_routes_for_engines
+ @engines.map do |name, routes|
+ ["\nRoutes for #{name}:"] + formatted_routes(routes)
+ end.flatten
+ end
+
+ def formatted_routes(routes)
+ name_width = routes.map{ |r| r[:name].length }.max
+ verb_width = routes.map{ |r| r[:verb].length }.max
+ path_width = routes.map{ |r| r[:path].length }.max
+
+ routes.map do |r|
+ "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 02c1250c76..68b0195700 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -95,7 +95,7 @@ module ActionView
# have SSL certificates for each of the asset hosts this technique allows you
# to avoid warnings in the client about mixed media.
#
- # ActionController::Base.asset_host = Proc.new { |source, request|
+ # config.action_controller.asset_host = Proc.new { |source, request|
# if request.ssl?
# "#{request.protocol}#{request.host_with_port}"
# else
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb
index f91aa246f4..8340aab4d2 100644
--- a/actionpack/test/controller/flash_test.rb
+++ b/actionpack/test/controller/flash_test.rb
@@ -220,7 +220,6 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest
SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33'
class TestController < ActionController::Base
-
add_flash_types :bar
def set_flash
diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb
new file mode 100644
index 0000000000..ae830300a1
--- /dev/null
+++ b/actionpack/test/dispatch/routing/inspector_test.rb
@@ -0,0 +1,170 @@
+require 'minitest/autorun'
+require 'action_controller'
+require 'rails/engine'
+require 'action_dispatch/routing/inspector'
+
+module ActionDispatch
+ module Routing
+ class RouteInspectTest < ActiveSupport::TestCase
+ def setup
+ @set = ActionDispatch::Routing::RouteSet.new
+ @inspector = ActionDispatch::Routing::RouteInspector.new
+ app = ActiveSupport::OrderedOptions.new
+ app.config = ActiveSupport::OrderedOptions.new
+ app.config.assets = ActiveSupport::OrderedOptions.new
+ app.config.assets.prefix = '/sprockets'
+ Rails.stubs(:application).returns(app)
+ Rails.stubs(:env).returns("development")
+ end
+
+ def draw(&block)
+ @set.draw(&block)
+ @inspector.format(@set.routes)
+ end
+
+ def test_displaying_routes_for_engines
+ engine = Class.new(Rails::Engine) do
+ def self.to_s
+ "Blog::Engine"
+ end
+ end
+ engine.routes.draw do
+ get '/cart', :to => 'cart#show'
+ end
+
+ output = draw do
+ get '/custom/assets', :to => 'custom_assets#show'
+ mount engine => "/blog", :as => "blog"
+ end
+
+ expected = [
+ "custom_assets GET /custom/assets(.:format) custom_assets#show",
+ " blog /blog Blog::Engine",
+ "\nRoutes for Blog::Engine:",
+ "cart GET /cart(.:format) cart#show"
+ ]
+ assert_equal expected, output
+ end
+
+ def test_cart_inspect
+ output = draw do
+ get '/cart', :to => 'cart#show'
+ end
+ assert_equal ["cart GET /cart(.:format) cart#show"], output
+ end
+
+ def test_inspect_shows_custom_assets
+ output = draw do
+ get '/custom/assets', :to => 'custom_assets#show'
+ end
+ assert_equal ["custom_assets GET /custom/assets(.:format) custom_assets#show"], output
+ end
+
+ def test_inspect_routes_shows_resources_route
+ output = draw do
+ resources :articles
+ end
+ expected = [
+ " articles GET /articles(.:format) articles#index",
+ " POST /articles(.:format) articles#create",
+ " new_article GET /articles/new(.:format) articles#new",
+ "edit_article GET /articles/:id/edit(.:format) articles#edit",
+ " article GET /articles/:id(.:format) articles#show",
+ " PATCH /articles/:id(.:format) articles#update",
+ " PUT /articles/:id(.:format) articles#update",
+ " DELETE /articles/:id(.:format) articles#destroy" ]
+ assert_equal expected, output
+ end
+
+ def test_inspect_routes_shows_root_route
+ output = draw do
+ root :to => 'pages#main'
+ end
+ assert_equal ["root GET / pages#main"], output
+ end
+
+ def test_inspect_routes_shows_dynamic_action_route
+ output = draw do
+ get 'api/:action' => 'api'
+ end
+ assert_equal [" GET /api/:action(.:format) api#:action"], output
+ end
+
+ def test_inspect_routes_shows_controller_and_action_only_route
+ output = draw do
+ get ':controller/:action'
+ end
+ assert_equal [" GET /:controller/:action(.:format) :controller#:action"], output
+ end
+
+ def test_inspect_routes_shows_controller_and_action_route_with_constraints
+ output = draw do
+ get ':controller(/:action(/:id))', :id => /\d+/
+ end
+ assert_equal [" GET /:controller(/:action(/:id))(.:format) :controller#:action {:id=>/\\d+/}"], output
+ end
+
+ def test_rake_routes_shows_route_with_defaults
+ output = draw do
+ get 'photos/:id' => 'photos#show', :defaults => {:format => 'jpg'}
+ end
+ assert_equal [%Q[ GET /photos/:id(.:format) photos#show {:format=>"jpg"}]], output
+ end
+
+ def test_rake_routes_shows_route_with_constraints
+ output = draw do
+ get 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/
+ end
+ assert_equal [" GET /photos/:id(.:format) photos#show {:id=>/[A-Z]\\d{5}/}"], output
+ end
+
+ class RackApp
+ def self.call(env)
+ end
+ end
+
+ def test_rake_routes_shows_route_with_rack_app
+ output = draw do
+ get 'foo/:id' => RackApp, :id => /[A-Z]\d{5}/
+ end
+ assert_equal [" GET /foo/:id(.:format) #{RackApp.name} {:id=>/[A-Z]\\d{5}/}"], output
+ end
+
+ def test_rake_routes_shows_route_with_rack_app_nested_with_dynamic_constraints
+ constraint = Class.new do
+ def to_s
+ "( my custom constraint )"
+ end
+ end
+
+ output = draw do
+ scope :constraint => constraint.new do
+ mount RackApp => '/foo'
+ end
+ end
+
+ assert_equal [" /foo #{RackApp.name} {:constraint=>( my custom constraint )}"], output
+ end
+
+ def test_rake_routes_dont_show_app_mounted_in_assets_prefix
+ output = draw do
+ get '/sprockets' => RackApp
+ end
+ assert_no_match(/RackApp/, output.first)
+ assert_no_match(/\/sprockets/, output.first)
+ end
+
+ def test_redirect
+ output = draw do
+ get "/foo" => redirect("/foo/bar"), :constraints => { :subdomain => "admin" }
+ get "/bar" => redirect(path: "/foo/bar", status: 307)
+ get "/foobar" => redirect{ "/foo/bar" }
+ end
+
+ assert_equal " foo GET /foo(.:format) redirect(301, /foo/bar) {:subdomain=>\"admin\"}", output[0]
+ assert_equal " bar GET /bar(.:format) redirect(307, path: /foo/bar)", output[1]
+ assert_equal "foobar GET /foobar(.:format) redirect(301)", output[2]
+ end
+ end
+ end
+end
diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb
index 89d87a8b6f..57b1bc2ada 100644
--- a/activemodel/lib/active_model/conversion.rb
+++ b/activemodel/lib/active_model/conversion.rb
@@ -45,18 +45,30 @@ module ActiveModel
# Returns an Enumerable of all key attributes if any is set, regardless if
# the object is persisted or not. If there no key attributes, returns +nil+.
+ #
+ # class Person < ActiveRecord::Base
+ # end
+ #
+ # person = Person.create
+ # person.to_key # => [1]
def to_key
key = respond_to?(:id) && id
key ? [key] : nil
end
- # Returns a string representing the object's key suitable for use in URLs,
- # or +nil+ if <tt>persisted?</tt> is false.
+ # Returns a +string+ representing the object's key suitable for use in URLs,
+ # or +nil+ if <tt>persisted?</tt> is +false+.
+ #
+ # class Person < ActiveRecord::Base
+ # end
+ #
+ # person = Person.create
+ # person.to_param # => "1"
def to_param
persisted? ? to_key.join('-') : nil
end
- # Returns a string identifying the path associated with the object.
+ # Returns a +string+ identifying the path associated with the object.
# ActionPack uses this to find a suitable partial to represent the object.
#
# class Person
diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb
index 8f2c0bf00a..e57fcf1610 100644
--- a/activemodel/lib/active_model/mass_assignment_security.rb
+++ b/activemodel/lib/active_model/mass_assignment_security.rb
@@ -141,8 +141,10 @@ module ActiveModel
#
# attr_accessor :name, :credit_rating
#
- # attr_accessible :name
- # attr_accessible :name, :credit_rating, :as => :admin
+ # # Both admin and default user can change name of a customer
+ # attr_accessible :name, :as => [:admin, :default]
+ # # Only admin can change credit rating of a customer
+ # attr_accessible :credit_rating, :as => :admin
#
# def assign_attributes(values, options = {})
# sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb
index 6d8fd21814..8a63014ffb 100644
--- a/activemodel/lib/active_model/serialization.rb
+++ b/activemodel/lib/active_model/serialization.rb
@@ -25,17 +25,16 @@ module ActiveModel
# person.name = "Bob"
# person.serializable_hash # => {"name"=>"Bob"}
#
- # You need to declare an attributes hash which contains the attributes
- # you want to serialize. Attributes must be strings, not symbols.
- # When called, serializable hash will use
- # instance methods that match the name of the attributes hash's keys.
- # In order to override this behavior, take a look at the private
- # method +read_attribute_for_serialization+.
+ # You need to declare an attributes hash which contains the attributes you
+ # want to serialize. Attributes must be strings, not symbols. When called,
+ # serializable hash will use instance methods that match the name of the
+ # attributes hash's keys. In order to override this behavior, take a look at
+ # the private method +read_attribute_for_serialization+.
#
# Most of the time though, you will want to include the JSON or XML
# serializations. Both of these modules automatically include the
- # <tt>ActiveModel::Serialization</tt> module, so there is no need to explicitly
- # include it.
+ # <tt>ActiveModel::Serialization</tt> module, so there is no need to
+ # explicitly include it.
#
# A minimal implementation including XML and JSON would be:
#
@@ -64,13 +63,37 @@ module ActiveModel
# person.to_json # => "{\"name\":\"Bob\"}"
# person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
#
- # Valid options are <tt>:only</tt>, <tt>:except</tt>, <tt>:methods</tt> and <tt>:include</tt>.
- # The following are all valid examples:
+ # Valid options are <tt>:only</tt>, <tt>:except</tt>, <tt>:methods</tt> and
+ # <tt>:include</tt>. The following are all valid examples:
#
- # person.serializable_hash(:only => 'name')
- # person.serializable_hash(:include => :address)
- # person.serializable_hash(:include => { :address => { :only => 'city' }})
+ # person.serializable_hash(only: 'name')
+ # person.serializable_hash(include: :address)
+ # person.serializable_hash(include: { address: { only: 'city' }})
module Serialization
+ # Returns a serialized hash of your object.
+ #
+ # class Person
+ # include ActiveModel::Serialization
+ #
+ # attr_accessor :name, :age
+ #
+ # def attributes
+ # {'name' => nil, 'age' => nil}
+ # end
+ #
+ # def capitalized_name
+ # name.capitalize
+ # end
+ # end
+ #
+ # person = Person.new
+ # person.name = 'bob'
+ # person.age = 22
+ # person.serializable_hash # => {"name"=>"bob", "age"=>22}
+ # person.serializable_hash(only: :name) # => {"name"=>"bob"}
+ # person.serializable_hash(except: :name) # => {"age"=>22}
+ # person.serializable_hash(methods: :capitalized_name)
+ # # => {"name"=>"bob", "age"=>22, "capitalized_name"=>"Bob"}
def serializable_hash(options = nil)
options ||= {}
@@ -115,7 +138,6 @@ module ActiveModel
# @data[key]
# end
# end
- #
alias :read_attribute_for_serialization :send
# Add associations specified via the <tt>:include</tt> option.
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index b4baf3a946..e4c7553cb8 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -87,8 +87,12 @@ module ActiveModel
# # { "comments" => [ { "body" => "Don't think too hard" } ],
# # "title" => "So I was thinking" } ] }
def as_json(options = nil)
- root = include_root_in_json
- root = options[:root] if options.try(:key?, :root)
+ root = if options && options.key?(:root)
+ options[:root]
+ else
+ include_root_in_json
+ end
+
if root
root = self.class.model_name.element if root == true
{ root => serializable_hash(options) }
diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb
index 43651094cf..18e71750de 100644
--- a/activemodel/lib/active_model/validations/acceptance.rb
+++ b/activemodel/lib/active_model/validations/acceptance.rb
@@ -27,7 +27,7 @@ module ActiveModel
#
# class Person < ActiveRecord::Base
# validates_acceptance_of :terms_of_service
- # validates_acceptance_of :eula, :message => "must be abided"
+ # validates_acceptance_of :eula, message: "must be abided"
# end
#
# If the database column does not exist, the +terms_of_service+ attribute
@@ -41,23 +41,23 @@ module ActiveModel
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+ (default
- # is true).
+ # is +true+).
# * <tt>:accept</tt> - 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.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
- # if the validation should occur (e.g. <tt>:if => :allow_validation</tt>,
- # or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
- # method, proc or string should return or evaluate to a true or false
- # value.
+ # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
+ # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to
# determine if the validation should not occur (for example,
- # <tt>:unless => :skip_validation</tt>, or
- # <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>).
- # The method, proc or string should return or evaluate to a true or
- # false value.
+ # <tt>unless: :skip_validation</tt>, or
+ # <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>).
+ # The method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
def validates_acceptance_of(*attr_names)
diff --git a/activemodel/lib/active_model/validations/clusivity.rb b/activemodel/lib/active_model/validations/clusivity.rb
index b632a2bd6b..676457ec0f 100644
--- a/activemodel/lib/active_model/validations/clusivity.rb
+++ b/activemodel/lib/active_model/validations/clusivity.rb
@@ -2,7 +2,7 @@ require 'active_support/core_ext/range.rb'
module ActiveModel
module Validations
- module Clusivity
+ module Clusivity #:nodoc:
ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
"and must be supplied as the :in option of the configuration hash"
diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb
index b6cf82fb19..d41f401999 100644
--- a/activemodel/lib/active_model/validations/confirmation.rb
+++ b/activemodel/lib/active_model/validations/confirmation.rb
@@ -25,7 +25,7 @@ module ActiveModel
# class Person < ActiveRecord::Base
# validates_confirmation_of :user_name, :password
# validates_confirmation_of :email_address,
- # :message => "should match confirmation"
+ # message: 'should match confirmation'
# end
#
# View:
@@ -38,10 +38,10 @@ module ActiveModel
# attribute.
#
# NOTE: This check is performed only if +password_confirmation+ is not
- # +nil+. To require confirmation, make sure
- # to add a presence check for the confirmation attribute:
+ # +nil+. To require confirmation, make sure to add a presence check for
+ # the confirmation attribute:
#
- # validates_presence_of :password_confirmation, :if => :password_changed?
+ # validates_presence_of :password_confirmation, if: :password_changed?
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "doesn't match
@@ -50,15 +50,16 @@ module ActiveModel
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
- # if the validation should occur (e.g. <tt>:if => :allow_validation</tt>,
- # or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
- # method, proc or string should return or evaluate to a true or false
- # value.
+ # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
+ # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to
# determine if the validation should not occur (e.g.
- # <tt>:unless => :skip_validation</tt>, or
- # <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
- # method, proc or string should return or evaluate to a true or false value.
+ # <tt>unless: :skip_validation</tt>, or
+ # <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
def validates_confirmation_of(*attr_names)
diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb
index c8d7057606..a9a1af039c 100644
--- a/activemodel/lib/active_model/validations/exclusion.rb
+++ b/activemodel/lib/active_model/validations/exclusion.rb
@@ -19,35 +19,36 @@ module ActiveModel
# particular enumerable object.
#
# class Person < ActiveRecord::Base
- # validates_exclusion_of :username, :in => %w( admin superuser ), :message => "You don't belong here"
- # validates_exclusion_of :age, :in => 30..60, :message => "This site is only for under 30 and over 60"
- # validates_exclusion_of :format, :in => %w( mov avi ), :message => "extension %{value} is not allowed"
- # validates_exclusion_of :password, :in => lambda { |p| [p.username, p.first_name] },
- # :message => "should not be the same as your username or first name"
+ # validates_exclusion_of :username, in: %w( admin superuser ), message: "You don't belong here"
+ # validates_exclusion_of :age, in: 30..60, message: 'This site is only for under 30 and over 60'
+ # validates_exclusion_of :format, in: %w( mov avi ), message: "extension %{value} is not allowed"
+ # validates_exclusion_of :password, in: ->(person) { [person.username, person.first_name] },
+ # message: 'should not be the same as your username or first name'
# end
#
# Configuration options:
- # * <tt>:in</tt> - An enumerable object of items that the value shouldn't be
- # part of. This can be supplied as a proc or lambda which returns an
+ # * <tt>:in</tt> - An enumerable object of items that the value shouldn't
+ # be part of. This can be supplied as a proc or lambda which returns an
# enumerable. If the enumerable is a range the test is performed with
# <tt>Range#cover?</tt>, otherwise with <tt>include?</tt>.
# * <tt>:message</tt> - Specifies a custom error message (default is: "is
# reserved").
- # * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute
- # is +nil+ (default is +false+).
+ # * <tt>:allow_nil</tt> - If set to true, skips this validation if the
+ # attribute is +nil+ (default is +false+).
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the
# attribute is blank(default is +false+).
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if
- # the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
- # <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
- # or string should return or evaluate to a true or false value.
+ # the validation should occur (e.g. <tt>if: :allow_validation</tt>, or
+ # <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
+ # proc or string should return or evaluate to a +true+ or +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
- # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
- # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
- # method, proc or string should return or evaluate to a true or false value.
+ # if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
+ # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
def validates_exclusion_of(*attr_names)
diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb
index d48987c482..a2126f8372 100644
--- a/activemodel/lib/active_model/validations/format.rb
+++ b/activemodel/lib/active_model/validations/format.rb
@@ -57,14 +57,14 @@ module ActiveModel
# attribute matches the regular expression:
#
# class Person < ActiveRecord::Base
- # validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :on => :create
+ # validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, on: :create
# end
#
# Alternatively, you can require that the specified attribute does _not_
# match the regular expression:
#
# class Person < ActiveRecord::Base
- # validates_format_of :email, :without => /NOSPAM/
+ # validates_format_of :email, without: /NOSPAM/
# end
#
# You can also provide a proc or lambda which will determine the regular
@@ -73,15 +73,16 @@ module ActiveModel
# class Person < ActiveRecord::Base
# # Admin can have number as a first letter in their screen name
# validates_format_of :screen_name,
- # :with => lambda{ |person| person.admin? ? /\A[a-z0-9][a-z0-9_\-]*\z/i : /\A[a-z][a-z0-9_\-]*\z/i }
+ # with: ->(person) { person.admin? ? /\A[a-z0-9][a-z0-9_\-]*\z/i : /\A[a-z][a-z0-9_\-]*\z/i }
# end
#
# Note: use <tt>\A</tt> and <tt>\Z</tt> to match the start and end of the
# string, <tt>^</tt> and <tt>$</tt> match the start/end of a line.
#
- # Due to frequent misuse of <tt>^</tt> and <tt>$</tt>, you need to pass the
- # :multiline => true option in case you use any of these two anchors in the provided
- # regular expression. In most cases, you should be using <tt>\A</tt> and <tt>\z</tt>.
+ # Due to frequent misuse of <tt>^</tt> and <tt>$</tt>, you need to pass
+ # the <tt>multiline: true</tt> option in case you use any of these two
+ # anchors in the provided regular expression. In most cases, you should be
+ # using <tt>\A</tt> and <tt>\z</tt>.
#
# You must pass either <tt>:with</tt> or <tt>:without</tt> as an option.
# In addition, both must be a regular expression or a proc or lambda, or
@@ -89,27 +90,29 @@ module ActiveModel
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "is invalid").
- # * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute
- # is +nil+ (default is +false+).
+ # * <tt>:allow_nil</tt> - If set to true, skips this validation if the
+ # attribute is +nil+ (default is +false+).
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the
# attribute is blank (default is +false+).
# * <tt>:with</tt> - Regular expression that if the attribute matches will
- # result in a successful validation. This can be provided as a proc or lambda
- # returning regular expression which will be called at runtime.
- # * <tt>:without</tt> - Regular expression that if the attribute does not match
- # will result in a successful validation. This can be provided as a proc or
+ # result in a successful validation. This can be provided as a proc or
# lambda returning regular expression which will be called at runtime.
+ # * <tt>:without</tt> - Regular expression that if the attribute does not
+ # match will result in a successful validation. This can be provided as
+ # a proc or lambda returning regular expression which will be called at
+ # runtime.
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
- # if the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
- # <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
- # or string should return or evaluate to a true or false value.
+ # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
+ # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
+ # proc or string should return or evaluate to a +true+ or +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
- # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
- # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
- # method, proc or string should return or evaluate to a true or false value.
+ # if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
+ # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
# * <tt>:multiline</tt> - Set to true if your regular expression contains
diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb
index 154db5aedc..e7ad07f040 100644
--- a/activemodel/lib/active_model/validations/inclusion.rb
+++ b/activemodel/lib/active_model/validations/inclusion.rb
@@ -19,34 +19,35 @@ module ActiveModel
# particular enumerable object.
#
# class Person < ActiveRecord::Base
- # validates_inclusion_of :gender, :in => %w( m f )
- # validates_inclusion_of :age, :in => 0..99
- # validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %{value} is not included in the list"
- # validates_inclusion_of :states, :in => lambda{ |person| STATES[person.country] }
+ # validates_inclusion_of :gender, in: %w( m f )
+ # validates_inclusion_of :age, in: 0..99
+ # validates_inclusion_of :format, in: %w( jpg gif png ), message: "extension %{value} is not included in the list"
+ # validates_inclusion_of :states, in: ->(person) { STATES[person.country] }
# end
#
# Configuration options:
# * <tt>:in</tt> - An enumerable object of available items. This can be
- # supplied as a proc or lambda which returns an enumerable. If the enumerable
- # is a range the test is performed with <tt>Range#cover?</tt>, otherwise with
- # <tt>include?</tt>.
- # * <tt>:message</tt> - Specifies a custom error message (default is: "is not
- # included in the list").
- # * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute
- # is +nil+ (default is +false+).
- # * <tt>:allow_blank</tt> - If set to true, skips this validation if the
+ # supplied as a proc or lambda which returns an enumerable. If the
+ # enumerable is a range the test is performed with <tt>Range#cover?</tt>,
+ # otherwise with <tt>include?</tt>.
+ # * <tt>:message</tt> - Specifies a custom error message (default is: "is
+ # not included in the list").
+ # * <tt>:allow_nil</tt> - If set to +true+, skips this validation if the
+ # attribute is +nil+ (default is +false+).
+ # * <tt>:allow_blank</tt> - If set to +true+, skips this validation if the
# attribute is blank (default is +false+).
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if
- # the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
- # <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
- # or string should return or evaluate to a true or false value.
+ # the validation should occur (e.g. <tt>if: :allow_validation</tt>, or
+ # <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
+ # or string should return or evaluate to a +true+ or +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
- # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
- # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
- # method, proc or string should return or evaluate to a true or false value.
+ # if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
+ # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
def validates_inclusion_of(*attr_names)
diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb
index 40ebe0cd2e..3b0be96ac6 100644
--- a/activemodel/lib/active_model/validations/length.rb
+++ b/activemodel/lib/active_model/validations/length.rb
@@ -62,36 +62,37 @@ module ActiveModel
module HelperMethods
- # Validates that the specified attribute matches the length restrictions supplied. Only one option can be used at a time:
+ # Validates that the specified attribute matches the length restrictions
+ # supplied. Only one option can be used at a time:
#
# class Person < ActiveRecord::Base
- # validates_length_of :first_name, :maximum => 30
- # validates_length_of :last_name, :maximum => 30, :message => "less than 30 if you don't mind"
- # validates_length_of :fax, :in => 7..32, :allow_nil => true
- # validates_length_of :phone, :in => 7..32, :allow_blank => true
- # validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name"
- # validates_length_of :zip_code, :minimum => 5, :too_short => "please enter at least 5 characters"
- # validates_length_of :smurf_leader, :is => 4, :message => "papa is spelled with 4 characters... don't play me."
- # validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least 100 words.",
- # :tokenizer => lambda { |str| str.scan(/\w+/) }
+ # validates_length_of :first_name, maximum: 30
+ # validates_length_of :last_name, maximum: 30, message: "less than 30 if you don't mind"
+ # validates_length_of :fax, in: 7..32, allow_nil: true
+ # validates_length_of :phone, in: 7..32, allow_blank: true
+ # validates_length_of :user_name, within: 6..20, too_long: 'pick a shorter name', too_short: 'pick a longer name'
+ # validates_length_of :zip_code, minimum: 5, too_short: 'please enter at least 5 characters'
+ # validates_length_of :smurf_leader, is: 4, message: "papa is spelled with 4 characters... don't play me."
+ # validates_length_of :essay, minimum: 100, too_short: 'Your essay must be at least 100 words.',
+ # tokenizer: ->(str) { str.scan(/\w+/) }
# end
#
# Configuration options:
# * <tt>:minimum</tt> - The minimum size of the attribute.
# * <tt>:maximum</tt> - The maximum size of the attribute.
# * <tt>:is</tt> - The exact size of the attribute.
- # * <tt>:within</tt> - A range specifying the minimum and maximum size of the
- # attribute.
- # * <tt>:in</tt> - A synonym(or alias) for <tt>:within</tt>.
+ # * <tt>:within</tt> - A range specifying the minimum and maximum size of
+ # the attribute.
+ # * <tt>:in</tt> - A synonym (or alias) for <tt>:within</tt>.
# * <tt>:allow_nil</tt> - Attribute may be +nil+; skip validation.
# * <tt>:allow_blank</tt> - Attribute may be blank; skip validation.
# * <tt>:too_long</tt> - The error message if the attribute goes over the
# maximum (default is: "is too long (maximum is %{count} characters)").
# * <tt>:too_short</tt> - The error message if the attribute goes under the
# minimum (default is: "is too short (min is %{count} characters)").
- # * <tt>:wrong_length</tt> - The error message if using the <tt>:is</tt> method
- # and the attribute is the wrong size (default is: "is the wrong length
- # (should be %{count} characters)").
+ # * <tt>:wrong_length</tt> - The error message if using the <tt>:is</tt>
+ # method and the attribute is the wrong size (default is: "is the wrong
+ # length (should be %{count} characters)").
# * <tt>:message</tt> - The error message to use for a <tt>:minimum</tt>,
# <tt>:maximum</tt>, or <tt>:is</tt> violation. An alias of the appropriate
# <tt>too_long</tt>/<tt>too_short</tt>/<tt>wrong_length</tt> message.
@@ -99,16 +100,17 @@ module ActiveModel
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if
- # the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
- # <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
- # or string should return or evaluate to a true or false value.
+ # the validation should occur (e.g. <tt>if: :allow_validation</tt>, or
+ # <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
+ # proc or string should return or evaluate to a +true+ or +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
- # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
- # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
- # proc or string should return or evaluate to a true or false value.
+ # if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
+ # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:tokenizer</tt> - Specifies how to split up the attribute string.
- # (e.g. <tt>:tokenizer => lambda {|str| str.scan(/\w+/)}</tt> to count words
- # as in above example). Defaults to <tt>lambda{ |value| value.split(//) }</tt>
+ # (e.g. <tt>tokenizer: ->(str) { str.scan(/\w+/) }</tt> to count words
+ # as in above example). Defaults to <tt>->(value) { value.split(//) }</tt>
# which counts individual characters.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index 1069ed3906..6b3dd6caec 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -79,13 +79,13 @@ module ActiveModel
end
module HelperMethods
- # Validates whether the value of the specified attribute is numeric by trying
- # to convert it to a float with Kernel.Float (if <tt>only_integer</tt> is false)
- # or applying it to the regular expression <tt>/\A[\+\-]?\d+\Z/</tt> (if
- # <tt>only_integer</tt> is set to true).
+ # Validates whether the value of the specified attribute is numeric by
+ # trying to convert it to a float with Kernel.Float (if <tt>only_integer</tt>
+ # is +false+) or applying it to the regular expression <tt>/\A[\+\-]?\d+\Z/</tt>
+ # (if <tt>only_integer</tt> is set to +true+).
#
# class Person < ActiveRecord::Base
- # validates_numericality_of :value, :on => :create
+ # validates_numericality_of :value, on: :create
# end
#
# Configuration options:
@@ -93,32 +93,34 @@ module ActiveModel
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
- # * <tt>:only_integer</tt> - Specifies whether the value has to be an integer,
- # e.g. an integral value (default is +false+).
+ # * <tt>:only_integer</tt> - Specifies whether the value has to be an
+ # integer, e.g. an integral value (default is +false+).
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+ (default is
# +false+). Notice that for fixnum and float columns empty strings are
# converted to +nil+.
# * <tt>:greater_than</tt> - Specifies the value must be greater than the
# supplied value.
- # * <tt>:greater_than_or_equal_to</tt> - Specifies the value must be greater
- # than or equal the supplied value.
- # * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied value.
- # * <tt>:less_than</tt> - Specifies the value must be less than the supplied
- # value.
- # * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less than or
- # equal the supplied value.
- # * <tt>:other_than</tt> - Specifies the value must be other than the supplied
+ # * <tt>:greater_than_or_equal_to</tt> - Specifies the value must be
+ # greater than or equal the supplied value.
+ # * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied
# value.
+ # * <tt>:less_than</tt> - Specifies the value must be less than the
+ # supplied value.
+ # * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less
+ # than or equal the supplied value.
+ # * <tt>:other_than</tt> - Specifies the value must be other than the
+ # supplied value.
# * <tt>:odd</tt> - Specifies the value must be an odd number.
# * <tt>:even</tt> - Specifies the value must be an even number.
- # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if
- # the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
- # <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
- # or string should return or evaluate to a true or false value.
+ # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
+ # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
+ # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
+ # proc or string should return or evaluate to a +true+ or +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
- # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
- # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
- # method, proc or string should return or evaluate to a true or false value.
+ # if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
+ # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
#
@@ -134,8 +136,8 @@ module ActiveModel
# For example:
#
# class Person < ActiveRecord::Base
- # validates_numericality_of :width, :less_than => Proc.new { |person| person.height }
- # validates_numericality_of :width, :greater_than => :minimum_weight
+ # validates_numericality_of :width, less_than: Proc.new { |person| person.height }
+ # validates_numericality_of :width, greater_than: :minimum_weight
# end
def validates_numericality_of(*attr_names)
validates_with NumericalityValidator, _merge_attributes(attr_names)
diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb
index a7dcdbba3d..cb7e9104db 100644
--- a/activemodel/lib/active_model/validations/presence.rb
+++ b/activemodel/lib/active_model/validations/presence.rb
@@ -20,9 +20,9 @@ module ActiveModel
#
# The first_name attribute must be in the object and it cannot be blank.
#
- # If you want to validate the presence of a boolean field (where the real values
- # are true and false), you will want to use
- # <tt>validates_inclusion_of :field_name, :in => [true, false]</tt>.
+ # If you want to validate the presence of a boolean field (where the real
+ # values are +true+ and +false+), you will want to use
+ # <tt>validates_inclusion_of :field_name, in: [true, false]</tt>.
#
# This is due to the way Object#blank? handles boolean values:
# <tt>false.blank? # => true</tt>.
@@ -32,14 +32,15 @@ module ActiveModel
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
# validation contexts by default (+nil+), other options are <tt>:create</tt>
# and <tt>:update</tt>.
- # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if
- # the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
- # <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
- # or string should return or evaluate to a true or false value.
+ # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
+ # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
+ # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
+ # proc or string should return or evaluate to a +true+ or +false+ value.
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
- # if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
- # or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
- # proc or string should return or evaluate to a true or false value.
+ # if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
+ # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a +true+ or
+ # +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
def validates_presence_of(*attr_names)
diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb
index 2953126c3c..d5d0798704 100644
--- a/activemodel/lib/active_model/validator.rb
+++ b/activemodel/lib/active_model/validator.rb
@@ -129,7 +129,7 @@ module ActiveModel #:nodoc:
# record, attribute and value.
#
# All Active Model validations are built on top of this validator.
- class EachValidator < Validator
+ class EachValidator < Validator #:nodoc:
attr_reader :attributes
# Returns a new validator instance. All options will be available via the
@@ -168,7 +168,7 @@ module ActiveModel #:nodoc:
# +BlockValidator+ is a special +EachValidator+ which receives a block on initialization
# and call this block for each attribute being validated. +validates_each+ uses this validator.
- class BlockValidator < EachValidator
+ class BlockValidator < EachValidator #:nodoc:
def initialize(options, &block)
@block = block
super
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
index a6e16da730..be6fda95b4 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb
@@ -65,6 +65,7 @@ module ActiveRecord
end
private
+
def cache_sql(sql, binds)
result =
if @query_cache[sql].key?(binds)
@@ -85,11 +86,7 @@ module ActiveRecord
end
def locked?(arel)
- if arel.respond_to?(:locked)
- arel.locked
- else
- false
- end
+ arel.respond_to?(:locked) && arel.locked
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 65c7ef0153..3c3f01223c 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -57,7 +57,6 @@ module ActiveRecord
# Checks to see if a column exists in a given table.
#
- # === Examples
# # Check a column exists
# column_exists?(:suppliers, :name)
#
@@ -65,7 +64,10 @@ module ActiveRecord
# column_exists?(:suppliers, :name, :string)
#
# # Check a column exists with a specific definition
- # column_exists?(:suppliers, :name, :string, :limit => 100)
+ # column_exists?(:suppliers, :name, :string, limit: 100)
+ # column_exists?(:suppliers, :name, :string, default: 'default')
+ # column_exists?(:suppliers, :name, :string, null: false)
+ # column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
def column_exists?(table_name, column_name, type = nil, options = {})
columns(table_name).any?{ |c| c.name == column_name.to_s &&
(!type || c.type == type) &&
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index a39328b89b..dd1f77e925 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -515,10 +515,7 @@ module ActiveRecord
end
def inspect
- limit = [limit_value, 11].compact.min
- entries = loaded? ? to_a.take(limit) : limit(limit)
-
- entries.map!(&:inspect)
+ entries = to_a.take([limit_value, 11].compact.min).map!(&:inspect)
entries[10] = '...' if entries.size == 11
"#<#{self.class.name} [#{entries.join(', ')}]>"
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 6f49548aab..e401ed37b0 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -41,6 +41,17 @@ module ActiveRecord
alias extensions extending_values
+ # Specify relationships to be included in the result set. For
+ # example:
+ #
+ # users = User.includes(:address)
+ # users.each do |user|
+ # user.address.city
+ # end
+ #
+ # allows you to access the +address+ attribute of the +User+ model without
+ # firing an additional query. This will often result in a
+ # performance improvement over a simple +join+
def includes(*args)
args.empty? ? self : spawn.includes!(*args)
end
@@ -131,6 +142,18 @@ module ActiveRecord
self
end
+ # Allows to specify a group attribute:
+ #
+ # User.group(:name)
+ # => SELECT "users".* FROM "users" GROUP BY name
+ #
+ # Returns an array with distinct records based on the `group` attribute:
+ #
+ # User.select([:id, :name])
+ # => [#<User id: 1, name: "Oscar">, #<User id: 2, name: "Oscar">, #<User id: 3, name: "Foo">
+ #
+ # User.group(:name)
+ # => [#<User id: 3, name: "Foo", ...>, #<User id: 2, name: "Oscar", ...>]
def group(*args)
args.blank? ? self : spawn.group!(*args)
end
@@ -142,6 +165,16 @@ module ActiveRecord
self
end
+ # Allows to specify an order attribute:
+ #
+ # User.order('name')
+ # => SELECT "users".* FROM "users" ORDER BY name
+ #
+ # User.order('name DESC')
+ # => SELECT "users".* FROM "users" ORDER BY name DESC
+ #
+ # User.order('name DESC, email')
+ # => SELECT "users".* FROM "users" ORDER BY name DESC, email
def order(*args)
args.blank? ? self : spawn.order!(*args)
end
diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb
index af51c803a7..b35fec7920 100644
--- a/activerecord/lib/active_record/scoping/default.rb
+++ b/activerecord/lib/active_record/scoping/default.rb
@@ -31,14 +31,14 @@ module ActiveRecord
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
# }
#
- # It is recommended that you use the block form of unscoped because chaining
- # unscoped with <tt>scope</tt> does not work. Assuming that
+ # It is recommended that you use the block form of unscoped because
+ # chaining unscoped with <tt>scope</tt> does not work. Assuming that
# <tt>published</tt> is a <tt>scope</tt>, the following two statements
- # are equal: the default_scope is applied on both.
+ # are equal: the <tt>default_scope</tt> is applied on both.
#
# Post.unscoped.published
# Post.published
- def unscoped #:nodoc:
+ def unscoped
block_given? ? relation.scoping { yield } : relation
end
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb
index f1241502f5..fb3dfc2730 100644
--- a/activerecord/lib/active_record/tasks/database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/database_tasks.rb
@@ -3,13 +3,17 @@ module ActiveRecord
module DatabaseTasks # :nodoc:
extend self
- TASKS_PATTERNS = {
- /mysql/ => ActiveRecord::Tasks::MySQLDatabaseTasks,
- /postgresql/ => ActiveRecord::Tasks::PostgreSQLDatabaseTasks,
- /sqlite/ => ActiveRecord::Tasks::SQLiteDatabaseTasks
- }
LOCAL_HOSTS = ['127.0.0.1', 'localhost']
+ def register_task(pattern, task)
+ @tasks ||= {}
+ @tasks[pattern] = task
+ end
+
+ register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks)
+ register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
+ register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks)
+
def create(*arguments)
configuration = arguments.first
class_for_adapter(configuration['adapter']).new(*arguments).create
@@ -84,8 +88,8 @@ module ActiveRecord
private
def class_for_adapter(adapter)
- key = TASKS_PATTERNS.keys.detect { |pattern| adapter[pattern] }
- TASKS_PATTERNS[key]
+ key = @tasks.keys.detect { |pattern| adapter[pattern] }
+ @tasks[key]
end
def each_current_configuration(environment)
diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb
index 8c96a8aaa1..4f3489b7a5 100644
--- a/activerecord/test/cases/tasks/database_tasks_test.rb
+++ b/activerecord/test/cases/tasks/database_tasks_test.rb
@@ -16,6 +16,22 @@ module ActiveRecord
:postgresql => :postgresql_tasks,
:sqlite3 => :sqlite_tasks
}
+
+ class DatabaseTasksRegisterTask < ActiveRecord::TestCase
+ def test_register_task
+ klazz = Class.new do
+ def initialize(*arguments); end
+ def structure_dump(filename); end
+ end
+ instance = klazz.new
+
+ klazz.stubs(:new).returns instance
+ instance.expects(:structure_dump).with("awesome-file.sql")
+
+ ActiveRecord::Tasks::DatabaseTasks.register_task(/foo/, klazz)
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => :foo}, "awesome-file.sql")
+ end
+ end
class DatabaseTasksCreateTest < ActiveRecord::TestCase
include DatabaseTasksSetupper
diff --git a/guides/source/active_record_querying.textile b/guides/source/active_record_querying.textile
index 101988c59e..9863d16fda 100644
--- a/guides/source/active_record_querying.textile
+++ b/guides/source/active_record_querying.textile
@@ -12,8 +12,6 @@ This guide covers different ways to retrieve data from the database using Active
endprologue.
-WARNING. This Guide is based on Rails 3.0. Some of the code shown here will not work in other versions of Rails.
-
If you're used to using raw SQL to find database records, then you will generally find that there are better ways to carry out the same operations in Rails. Active Record insulates you from the need to use SQL in most cases.
Code examples throughout this guide will refer to one or more of the following models:
@@ -53,20 +51,26 @@ h3. Retrieving Objects from the Database
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+
-* +select+
+* +bind+
+* +create_with+
+* +extending+
+* +from+
* +group+
-* +order+
-* +reorder+
-* +reverse_order+
-* +limit+
-* +offset+
-* +joins+
+* +having+
* +includes+
+* +joins+
+* +limit+
* +lock+
+* +offset+
+* +order+
+* +none+
* +readonly+
-* +from+
-* +having+
+* +references+
+* +reorder+
+* +reverse_order+
+* +select+
+* +uniq+
+* +where+
All of the above methods return an instance of <tt>ActiveRecord::Relation</tt>.
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index d5ec2cbfd9..3afbf0a03e 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -267,6 +267,7 @@ module Rails
def default_middleware_stack #:nodoc:
ActionDispatch::MiddlewareStack.new.tap do |middleware|
+ app = self
if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache
require "action_dispatch/http/rack_cache"
middleware.use ::Rack::Cache, rack_cache
@@ -290,11 +291,10 @@ module Rails
middleware.use ::ActionDispatch::RequestId
middleware.use ::Rails::Rack::Logger, config.log_tags # must come after Rack::MethodOverride to properly log overridden methods
middleware.use ::ActionDispatch::ShowExceptions, config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path)
- middleware.use ::ActionDispatch::DebugExceptions
+ middleware.use ::ActionDispatch::DebugExceptions, app
middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies
unless config.cache_classes
- app = self
middleware.use ::ActionDispatch::Reloader, lambda { app.reload_dependencies? }
end
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 383c159d3d..f469c334a7 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -176,8 +176,7 @@ module Rails
#
# * routes: when you mount an Engine with <tt>mount(MyEngine::Engine => '/my_engine')</tt>,
# it's used as default :as option
- # * some of the rake tasks are based on engine name, e.g. <tt>my_engine:install:migrations</tt>,
- # <tt>my_engine:install:assets</tt>
+ # * rake task for installing migrations <tt>my_engine:install:migrations</tt>
#
# Engine name is set by default based on class name. For <tt>MyEngine::Engine</tt> it will be
# <tt>my_engine_engine</tt>. You can change it manually using the <tt>engine_name</tt> method:
diff --git a/railties/lib/rails/info_controller.rb b/railties/lib/rails/info_controller.rb
index bacdcbf3aa..83ab8c7e9d 100644
--- a/railties/lib/rails/info_controller.rb
+++ b/railties/lib/rails/info_controller.rb
@@ -1,4 +1,4 @@
-require 'rails/application/routes_inspector'
+require 'action_dispatch/routing/inspector'
class Rails::InfoController < ActionController::Base
self.view_paths = File.join(File.dirname(__FILE__), 'templates')
@@ -16,6 +16,7 @@ class Rails::InfoController < ActionController::Base
def routes
inspector = Rails::Application::RoutesInspector.new
+ inspector = ActionDispatch::Routing::RouteInspector.new
@info = inspector.format(_routes.routes).join("\n")
end
diff --git a/railties/lib/rails/tasks/routes.rake b/railties/lib/rails/tasks/routes.rake
index 4ade825616..afc4e147e1 100644
--- a/railties/lib/rails/tasks/routes.rake
+++ b/railties/lib/rails/tasks/routes.rake
@@ -1,7 +1,7 @@
desc 'Print out all defined routes in match order, with names. Target specific controller with CONTROLLER=x.'
task :routes => :environment do
all_routes = Rails.application.routes.routes
- require 'rails/application/routes_inspector'
- inspector = Rails::Application::RoutesInspector.new
+ require 'action_dispatch/routing/inspector'
+ inspector = ActionDispatch::Routing::RouteInspector.new
puts inspector.format(all_routes, ENV['CONTROLLER']).join "\n"
end