aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--actionmailer/actionmailer.gemspec2
-rw-r--r--actionpack/CHANGELOG.md14
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb2
-rw-r--r--actionpack/lib/action_view/template/handlers/erb.rb11
-rw-r--r--actionpack/test/controller/new_base/render_template_test.rb10
-rw-r--r--actionpack/test/dispatch/routing_test.rb29
-rw-r--r--actionpack/test/template/render_test.rb5
-rw-r--r--actionpack/test/template/template_test.rb4
-rw-r--r--activemodel/CHANGELOG.md4
-rw-r--r--activemodel/lib/active_model/dirty.rb5
-rw-r--r--activemodel/test/cases/dirty_test.rb3
-rw-r--r--activemodel/test/cases/errors_test.rb5
-rw-r--r--activerecord/CHANGELOG.md6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb1
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb6
-rw-r--r--activerecord/test/cases/associations/eager_test.rb14
-rw-r--r--activerecord/test/cases/persistence_test.rb2
-rw-r--r--activerecord/test/models/developer.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/time/marshal.rb2
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb6
-rw-r--r--activesupport/test/multibyte_chars_test.rb3
-rw-r--r--activesupport/test/time_zone_test.rb7
-rw-r--r--guides/assets/images/customized_error_messages.pngbin2561 -> 0 bytes
-rw-r--r--guides/assets/images/error_messages.pngbin10964 -> 0 bytes
-rw-r--r--guides/assets/images/rails4_features.pngbin0 -> 132154 bytes
-rw-r--r--guides/assets/images/validation_error_messages.pngbin583 -> 0 bytes
-rw-r--r--guides/source/4_0_release_notes.md867
-rw-r--r--guides/source/action_mailer_basics.md53
-rw-r--r--guides/source/active_record_validations.md689
-rw-r--r--guides/source/migrations.md582
-rw-r--r--guides/source/performance_testing.md4
-rw-r--r--railties/CHANGELOG.md2
-rw-r--r--railties/lib/rails/commands/profiler.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/gitignore2
-rw-r--r--railties/lib/rails/source_annotation_extractor.rb2
-rw-r--r--railties/test/application/rake/notes_test.rb8
40 files changed, 807 insertions, 1567 deletions
diff --git a/.travis.yml b/.travis.yml
index 7e3d728872..930fc8f583 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,7 +22,7 @@ notifications:
on_success: change
on_failure: always
rooms:
- - secure: "CGWvthGkBKNnTnk9YSmf9AXKoiRI33fCl5D3jU4nx3cOPu6kv2R9nMjt9EAo\nOuS4Q85qNSf4VNQ2cUPNiNYSWQ+XiTfivKvDUw/QW9r1FejYyeWarMsSBWA+\n0fADjF1M2dkDIVLgYPfwoXEv7l+j654F1KLKB69F0F/netwP9CQ="
+ - secure: "qDX+Bw/tsg0ogYX0y/kTz5d326BL4JfjZQ66my2VdmRNwHyvv+mrONJ627Kt\n/U6HPA2FtSIMhtYWezi6qtGOKqZ3rns9B3gGGuaLgoCKLtCK2xzdR+OmNaNp\nXpuwGod2uABnpaDGDRYhsJ7X/efct1rk/C//S6s2b6rWKHNQd8k="
bundler_args: --path vendor/bundle
matrix:
allow_failures:
diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec
index e9f979f34b..67ec0d1097 100644
--- a/actionmailer/actionmailer.gemspec
+++ b/actionmailer/actionmailer.gemspec
@@ -21,5 +21,5 @@ Gem::Specification.new do |s|
s.add_dependency 'actionpack', version
- s.add_dependency 'mail', '~> 2.5.2'
+ s.add_dependency 'mail', '~> 2.5.3'
end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index e5bd21ea7b..43fd727500 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,4 +1,18 @@
## Rails 4.0.0 (unreleased) ##
+* Fixed a bug that ignores constraints on a glob route. This was caused because the constraint
+ regular expression is overwritten when the `routes.rb` file is processed. Fixes #7924
+
+ *Maura Fitzgerald*
+
+* More descriptive error messages when calling `render :partial` with
+ an invalid `:layout` argument.
+ #8376
+
+ render :partial => 'partial', :layout => true
+
+ # results in ActionView::MissingTemplate: Missing partial /true
+
+ *Yves Senn*
* Sweepers was extracted from Action Controller as `rails-observers` gem.
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index d1645eea3a..55e4561e8e 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -158,7 +158,7 @@ module ActionDispatch
def 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) }
+ @options.each { |k, v| requirements[k] ||= v if v.is_a?(Regexp) }
end
end
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index f5fdf766ad..8fb9b6ff18 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -293,7 +293,7 @@ module ActionView
object, as = @object, @variable
if !block && (layout = @options[:layout])
- layout = find_template(layout, @template_keys)
+ layout = find_template(layout.to_s, @template_keys)
end
object ||= locals[as]
diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb
index 731d8f9dab..afbbece90f 100644
--- a/actionpack/lib/action_view/template/handlers/erb.rb
+++ b/actionpack/lib/action_view/template/handlers/erb.rb
@@ -14,6 +14,17 @@ module ActionView
src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
end
+ # Erubis toggles <%= and <%== behavior when escaping is enabled.
+ # We override to always treat <%== as escaped.
+ def add_expr(src, code, indicator)
+ case indicator
+ when '=='
+ add_expr_escaped(src, code)
+ else
+ super
+ end
+ end
+
BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
def add_expr_literal(src, code)
diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb
index d0be4f66d1..6b2ae2b2a9 100644
--- a/actionpack/test/controller/new_base/render_template_test.rb
+++ b/actionpack/test/controller/new_base/render_template_test.rb
@@ -9,7 +9,8 @@ module RenderTemplate
"locals.html.erb" => "The secret is <%= secret %>",
"xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend",
"with_raw.html.erb" => "Hello <%=raw '<strong>this is raw</strong>' %>",
- "with_implicit_raw.html.erb" => "Hello <%== '<strong>this is also raw</strong>' %>",
+ "with_implicit_raw.html.erb" => "Hello <%== '<strong>this is also raw</strong>' %> in a html template",
+ "with_implicit_raw.text.erb" => "Hello <%== '<strong>this is also raw</strong>' %> in a text template",
"test/with_json.html.erb" => "<%= render :template => 'test/with_json', :formats => [:json] %>",
"test/with_json.json.erb" => "<%= render :template => 'test/final', :formats => [:json] %>",
"test/final.json.erb" => "{ final: json }",
@@ -113,7 +114,12 @@ module RenderTemplate
get :with_implicit_raw
- assert_body "Hello <strong>this is also raw</strong>"
+ assert_body "Hello <strong>this is also raw</strong> in a html template"
+ assert_status 200
+
+ get :with_implicit_raw, format: 'text'
+
+ assert_body "Hello <strong>this is also raw</strong> in a text template"
assert_status 200
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 4f5d8fdb7c..cb5299e8d3 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -3065,6 +3065,35 @@ class TestConstraintsAccessingParameters < ActionDispatch::IntegrationTest
end
end
+class TestGlobRoutingMapper < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
+
+ get "/*id" => redirect("/not_cars"), :constraints => {id: /dummy/}
+ get "/cars" => ok
+ end
+ end
+
+ #include Routes.url_helpers
+ def app; Routes end
+
+ def test_glob_constraint
+ get "/dummy"
+ assert_equal "301", @response.code
+ assert_equal "/not_cars", @response.header['Location'].match('/[^/]+$')[0]
+ end
+
+ def test_glob_constraint_skip_route
+ get "/cars"
+ assert_equal "200", @response.code
+ end
+ def test_glob_constraint_skip_all
+ get "/missing"
+ assert_equal "404", @response.code
+ end
+end
+
class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
app.draw do
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 4e6a676fc6..9fb26e32b1 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -437,6 +437,11 @@ module RenderTestCases
@view.render(:partial => 'test/partial_with_layout_block_content', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
end
+ def test_render_partial_with_layout_raises_descriptive_error
+ e = assert_raises(ActionView::MissingTemplate) { @view.render(partial: 'test/partial', layout: true) }
+ assert_match "Missing partial /true with", e.message
+ end
+
def test_render_with_nested_layout
assert_equal %(<title>title</title>\n\n<div id="column">column</div>\n<div id="content">content</div>\n),
@view.render(:file => "test/nested_layout", :layout => "layouts/yield")
diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb
index ed9d303158..8d32205fb8 100644
--- a/actionpack/test/template/template_test.rb
+++ b/actionpack/test/template/template_test.rb
@@ -82,8 +82,8 @@ class TestERBTemplate < ActiveSupport::TestCase
end
def test_text_template_does_not_html_escape
- @template = new_template("<%= apostrophe %>", format: :text)
- assert_equal "l'apostrophe", render
+ @template = new_template("<%= apostrophe %> <%== apostrophe %>", format: :text)
+ assert_equal "l'apostrophe l'apostrophe", render
end
def test_raw_template
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index aacef97858..b955e98835 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,5 +1,9 @@
## Rails 4.0.0 (unreleased) ##
+* `[attribute]_changed?` now returns `false` after a call to `reset_[attribute]!`
+
+ *Renato Mascarenhas*
+
* Observers was extracted from Active Model as `rails-observers` gem.
*Rafael Mendonça França*
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index d47c3ae1bb..ecb7a9e9b1 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -174,7 +174,10 @@ module ActiveModel
# Handle <tt>reset_*!</tt> for +method_missing+.
def reset_attribute!(attr)
- __send__("#{attr}=", changed_attributes[attr]) if attribute_changed?(attr)
+ if attribute_changed?(attr)
+ __send__("#{attr}=", changed_attributes[attr])
+ changed_attributes.delete(attr)
+ end
end
end
end
diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb
index eaaf910bac..0b9f9537e2 100644
--- a/activemodel/test/cases/dirty_test.rb
+++ b/activemodel/test/cases/dirty_test.rb
@@ -78,7 +78,7 @@ class DirtyTest < ActiveModel::TestCase
@model.name = "Bob"
@model.reset_name!
assert_nil @model.name
- #assert !@model.name_changed #Doesn't work yet
+ assert !@model.name_changed?
end
test "setting color to same value should not result in change being recorded" do
@@ -114,5 +114,4 @@ class DirtyTest < ActiveModel::TestCase
assert_equal ["Otto", "Mr. Manfredgensonton"], @model.name_change
assert_equal @model.name_was, "Otto"
end
-
end
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index 293ce07f4e..1ffce1ae47 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -116,7 +116,7 @@ class ErrorsTest < ActiveModel::TestCase
test "added? should default message to :invalid" do
person = Person.new
- person.errors.add(:name, :invalid)
+ person.errors.add(:name)
assert person.errors.added?(:name)
end
@@ -161,7 +161,7 @@ class ErrorsTest < ActiveModel::TestCase
person = Person.new
person.errors.add(:name, "can not be blank")
person.errors.add(:name, "can not be nil")
- assert_equal ["name can not be blank", "name can not be nil"], person.errors.to_a
+ assert_equal ["name can not be blank", "name can not be nil"], person.errors.full_messages
end
test 'full_message should return the given message if attribute equals :base' do
@@ -240,4 +240,3 @@ class ErrorsTest < ActiveModel::TestCase
person.errors.add_on_blank :name, :message => 'custom'
end
end
-
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 130d0f05d2..aaaf27a211 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,11 @@
## Rails 4.0.0 (unreleased) ##
+* Do not instantiate intermediate Active Record objects when eager loading.
+ These records caused `after_find` to run more than expected.
+ Fix #3313
+
+ *Yves Senn*
+
* Add STI support to init and building associations.
Allows you to do BaseClass.new(:type => "SubClass") as well as
parent.children.build(:type => "SubClass") or parent.build_child
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 7c561b6f82..9f7086cd07 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -267,7 +267,6 @@ module ActiveRecord
FROM pg_class seq,
pg_attribute attr,
pg_depend dep,
- pg_namespace name,
pg_constraint cons
WHERE seq.oid = dep.objid
AND seq.relkind = 'S'
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index eafe4a54c4..7ddaea1bb0 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -225,9 +225,11 @@ module ActiveRecord
orders = relation.order_values.map { |val| val.presence }.compact
values = @klass.connection.distinct("#{quoted_table_name}.#{primary_key}", orders)
- relation = relation.dup
+ relation = relation.dup.select(values)
+
+ id_rows = @klass.connection.select_all(relation.arel, 'SQL', relation.bind_values)
+ ids_array = id_rows.map {|row| row[primary_key]}
- ids_array = relation.select(values).collect {|row| row[primary_key]}
ids_array.empty? ? raise(ThrowResult) : table[primary_key].in(ids_array)
end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 124bf65d3a..94437380a4 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -616,8 +616,8 @@ class EagerAssociationTest < ActiveRecord::TestCase
general = categories.find { |c| c == categories(:general) }
technology = categories.find { |c| c == categories(:technology) }
- post1 = general.posts.to_a.find { |p| p == posts(:welcome) }
- post2 = technology.posts.to_a.find { |p| p == posts(:welcome) }
+ post1 = general.posts.to_a.find { |p| p == welcome }
+ post2 = technology.posts.to_a.find { |p| p == welcome }
assert_equal post1.object_id, post2.object_id
end
@@ -944,6 +944,12 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal 3, Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
end
+ def test_dont_create_temporary_active_record_instances
+ Developer.instance_count = 0
+ developers = Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a
+ assert_equal developers.count, Developer.instance_count
+ end
+
def test_order_on_join_table_with_include_and_limit
assert_equal 5, Developer.all.merge!(:includes => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).to_a.size
end
@@ -984,10 +990,10 @@ class EagerAssociationTest < ActiveRecord::TestCase
post = Post.create!(:title => 'Beaches', :body => "I like beaches!")
Reader.create! :person => people(:david), :post => post
LazyReader.create! :person => people(:susan), :post => post
-
+
assert_equal 1, post.lazy_readers.to_a.size
assert_equal 2, post.lazy_readers_skimmers_or_not.to_a.size
-
+
post_with_readers = Post.includes(:lazy_readers_skimmers_or_not).find(post.id)
assert_equal 2, post_with_readers.lazy_readers_skimmers_or_not.to_a.size
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index b2609f6395..02034c87b4 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -499,7 +499,7 @@ class PersistencesTest < ActiveRecord::TestCase
def test_update_column_with_one_changed_and_one_updated
t = Topic.order('id').limit(1).first
- title, author_name = t.title, t.author_name
+ author_name = t.author_name
t.author_name = 'John'
t.update_column(:title, 'super_title')
assert_equal 'John', t.author_name
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index 622dd75aeb..1c048bb6b4 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -57,6 +57,16 @@ class Developer < ActiveRecord::Base
def log=(message)
audit_logs.build :message => message
end
+
+ after_find :track_instance_count
+ cattr_accessor :instance_count
+
+ def track_instance_count
+ self.class.instance_count ||= 0
+ self.class.instance_count += 1
+ end
+ private :track_instance_count
+
end
class AuditLog < ActiveRecord::Base
diff --git a/activesupport/lib/active_support/core_ext/time/marshal.rb b/activesupport/lib/active_support/core_ext/time/marshal.rb
index 1bf622d6a6..497c4c3fb8 100644
--- a/activesupport/lib/active_support/core_ext/time/marshal.rb
+++ b/activesupport/lib/active_support/core_ext/time/marshal.rb
@@ -24,7 +24,7 @@ if Time.local(2010).zone != Marshal.load(Marshal.dump(Time.local(2010))).zone
def _dump(*args)
obj = dup
obj.instance_variable_set('@_zone', zone)
- obj._dump_without_zone(*args)
+ obj.send :_dump_without_zone, *args
end
end
end
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index 1a37d6f2a4..b6fca9df91 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -285,9 +285,9 @@ module ActiveSupport
parts.fetch(:year, now.year),
parts.fetch(:mon, now.month),
parts.fetch(:mday, now.day),
- parts.fetch(:hour, now.hour),
- parts.fetch(:min, now.min),
- parts.fetch(:sec, now.sec) + parts.fetch(:sec_fraction, 0),
+ parts.fetch(:hour, 0),
+ parts.fetch(:min, 0),
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
parts.fetch(:offset, 0)
)
diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb
index 0088a06c34..2bf73291a2 100644
--- a/activesupport/test/multibyte_chars_test.rb
+++ b/activesupport/test/multibyte_chars_test.rb
@@ -47,7 +47,10 @@ class MultibyteCharsTest < ActiveSupport::TestCase
end
def test_methods_are_forwarded_to_wrapped_string_for_byte_strings
+ original_encoding = BYTE_STRING.encoding
assert_equal BYTE_STRING.length, BYTE_STRING.mb_chars.length
+ ensure
+ BYTE_STRING.force_encoding(original_encoding)
end
def test_forwarded_method_with_non_string_result_should_be_returned_vertabim
diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb
index bdeb80a294..9c3b5d0667 100644
--- a/activesupport/test/time_zone_test.rb
+++ b/activesupport/test/time_zone_test.rb
@@ -219,6 +219,13 @@ class TimeZoneTest < ActiveSupport::TestCase
end
end
+ def test_parse_with_missing_time_components
+ zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+ zone.stubs(:now).returns zone.local(1999, 12, 31, 12, 59, 59)
+ twz = zone.parse('2012-12-01')
+ assert_equal Time.utc(2012, 12, 1), twz.time
+ end
+
def test_parse_with_javascript_date
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.parse("Mon May 28 2012 00:00:00 GMT-0700 (PDT)")
diff --git a/guides/assets/images/customized_error_messages.png b/guides/assets/images/customized_error_messages.png
deleted file mode 100644
index fcf47b4be0..0000000000
--- a/guides/assets/images/customized_error_messages.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/error_messages.png b/guides/assets/images/error_messages.png
deleted file mode 100644
index 1189e486d4..0000000000
--- a/guides/assets/images/error_messages.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/rails4_features.png b/guides/assets/images/rails4_features.png
new file mode 100644
index 0000000000..a979f02207
--- /dev/null
+++ b/guides/assets/images/rails4_features.png
Binary files differ
diff --git a/guides/assets/images/validation_error_messages.png b/guides/assets/images/validation_error_messages.png
deleted file mode 100644
index 30e4ca4a3d..0000000000
--- a/guides/assets/images/validation_error_messages.png
+++ /dev/null
Binary files differ
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index b4442130ac..42794b180e 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -1,42 +1,24 @@
Ruby on Rails 4.0 Release Notes
===============================
-Highlights in Rails 4.0: (WIP)
+Highlights in Rails 4.0:
* Ruby 1.9.3 only
* Strong Parameters
* Queue API
-* Caching Improvements
-* ActionController::Live
+* Turbolinks
+* Russian Doll Caching
+* Asynchronous Mailers
-These release notes cover the major changes, but do not include each bug-fix and changes. If you want to see everything, check out the [list of commits](https://github.com/rails/rails/commits/master) in the main Rails repository on GitHub.
+These release notes cover only the major changes. To know about various bug fixes and changes, please refer to the change logs or check out the [list of commits](https://github.com/rails/rails/commits/master) in the main Rails repository on GitHub.
--------------------------------------------------------------------------------
Upgrading to Rails 4.0
----------------------
-TODO. This is a WIP guide.
+If you're upgrading an existing application, it's a great idea to have good test coverage before going in. You should also first upgrade to Rails 3.2 in case you haven't and make sure your application still runs as expected before attempting an update to Rails 4.0. A list of things to watch out for when upgrading is available in the [Upgrading to Rails](upgrading_ruby_on_rails.html#upgrading-from-rails-3-2-to-rails-4-0) guide.
-If you're upgrading an existing application, it's a great idea to have good test coverage before going in. You should also first upgrade to Rails 3.2 in case you haven't and make sure your application still runs as expected before attempting an update to Rails 4.0. Then take heed of the following changes:
-
-### Rails 4.0 requires at least Ruby 1.9.3
-
-Rails 4.0 requires Ruby 1.9.3 or higher. Support for all of the previous Ruby versions has been dropped officially and you should upgrade as early as possible.
-
-### What to update in your apps
-
-* Update your Gemfile to depend on
- * `rails = 4.0.0`
- * `sass-rails ~> 3.2.3`
- * `coffee-rails ~> 3.2.1`
- * `uglifier >= 1.0.3`
-
-TODO: Update the versions above.
-
-* Rails 4.0 removes `vendor/plugins` completely. You have to replace these plugins by extracting them as gems and adding them in your Gemfile. If you choose not to make them gems, you can move them into, say, `lib/my_plugin/*` and add an appropriate initializer in `config/initializers/my_plugin.rb`.
-
-TODO: Configuration changes in environment files
Creating a Rails 4.0 application
--------------------------------
@@ -70,11 +52,14 @@ $ ruby /path/to/rails/railties/bin/rails new myapp --dev
Major Features
--------------
-Moved to a Plugin
------------------
+TODO. Give a list and then talk about each of them briefly. We can point to relevant code commits or documentation from these sections.
+
+![Rails 4.0](images/rails4_features.png)
-With Rails 4 several pieces have been extracted. While Rails won't ship with these features anymore,
-you can simply add the extracted plugin to your `Gemfile` to bring the functionality back.
+Extraction of features to gems
+---------------------------
+
+In Rails 4.0, several features have been extracted into gems. You can simply add the extracted gems to your `Gemfile` to bring the functionality back.
* Hash-based & Dynamic finder methods ([Github](https://github.com/rails/activerecord-deprecated_finders))
* Mass assignment protection in Active Record models ([Github](https://github.com/rails/protected_attributes), [Pull Request](https://github.com/rails/rails/pull/7251))
@@ -83,6 +68,7 @@ you can simply add the extracted plugin to your `Gemfile` to bring the functiona
* Active Resource ([Github](https://github.com/rails/activeresource), [Pull Request](https://github.com/rails/rails/pull/572), [Blog](http://yetimedia.tumblr.com/post/35233051627/activeresource-is-dead-long-live-activeresource))
* Action Caching ([Github](https://github.com/rails/actionpack-action_caching), [Pull Request](https://github.com/rails/rails/pull/7833))
* Page Caching ([Github](https://github.com/rails/actionpack-page_caching), [Pull Request](https://github.com/rails/rails/pull/7833))
+* Sprockets ([Github](https://github.com/rails/sprockets-rails))
Documentation
-------------
@@ -94,848 +80,93 @@ Documentation
Railties
--------
-* Ensure that RAILS_ENV is set when accessing Rails.env.
-
-* Don't eager-load app/assets and app/views.
+Please refer to the [Changelog](https://github.com/rails/rails/blob/master/railties/CHANGELOG.md) for detailed changes.
-* Add `.rake` to list of file extensions included by `rake notes` and `rake notes:custom`.
+### Notable changes
* New test locations `test/models`, `test/helpers`, `test/controllers`, and `test/mailers`. Corresponding rake tasks added as well. ([Pull Request](https://github.com/rails/rails/pull/7878))
-* Set a different cache per environment for assets pipeline through `config.assets.cache`.
-
-* `Rails.public_path` now returns a Pathname object.
-
-* Remove highly uncommon `config.assets.manifest` option for moving the manifest path. This option is now unsupported in sprockets-rails.
-
-* Add `config.action_controller.permit_all_parameters` to disable StrongParameters protection, it's false by default.
-
-* Remove `config.active_record.whitelist_attributes` and `config.active_record.mass_assignment_sanitizer` from new applications since MassAssignmentSecurity has been extracted from Rails.
-
-* Change `rails new` and `rails plugin new` generators to name the `.gitkeep` files as `.keep` in a more SCM-agnostic way. Change `--skip-git` option to only skip the `.gitignore` file and still generate the `.keep` files. Add `--skip-keeps` option to skip the `.keep` files.
-
-* Fixed support for DATABASE_URL environment variable for rake db tasks.
-
-* rails dbconsole now can use SSL for MySQL. The database.yml options sslca, sslcert, sslcapath, sslcipher and sslkey now affect rails dbconsole.
-
-* Correctly handle SCRIPT_NAME when generating routes to engine in application that's mounted at a sub-uri. With this behavior, you *should not* use default_url_options[:script_name] to set proper application's mount point by yourself.
-
-* `config.threadsafe!` is deprecated in favor of `config.eager_load` which provides a more fine grained control on what is eager loaded.
-
-* The migration generator will now produce AddXXXToYYY/RemoveXXXFromYYY migrations with references statements, for instance
-
- rails g migration AddReferencesToProducts user:references supplier:references{polymorphic}
-
- will generate the migration with:
-
- add_reference :products, :user, index: true
- add_reference :products, :supplier, polymorphic: true, index: true
-
-* Allow scaffold/model/migration generators to accept a `polymorphic` modifier for `references`/`belongs_to`, for instance
-
- ```
- rails g model Product supplier:references{polymorphic}
- ```
-
- will generate the model with `belongs_to :supplier, polymorphic: true` association and appropriate migration.
-
-* Set `config.active_record.migration_error` to `:page_load` for development.
-
-* Add runner to `Rails::Railtie` as a hook called just after runner starts.
-
-* Add `/rails/info/routes` path which displays the same information as `rake routes`.
-
-* Improved `rake routes` output for redirects.
-
-* Load all environments available in `config.paths["config/environments"]`.
-
-* Add `config.queue_consumer` to change the job queue consumer from the default `ActiveSupport::ThreadedQueueConsumer`.
-
-* Add `Rails.queue` for processing jobs in the background.
-
-* Remove `Rack::SSL` in favour of `ActionDispatch::SSL`.
-
-* Allow to set class that will be used to run as a console, other than IRB, with `Rails.application.config.console=`. It's best to add it to console block.
-
- ```ruby
- # it can be added to config/application.rb
- console do
- # this block is called only when running console,
- # so we can safely require pry here
- require "pry"
- config.console = Pry
- end
- ```
-
-* Add a convenience method `hide!` to Rails generators to hide the current generator namespace from showing when running `rails generate`.
+* Threadsafe on by default
-* Scaffold now uses `content_tag_for` in `index.html.erb`.
-
-* `Rails::Plugin` is removed. Instead of adding plugins to `vendor/plugins`, use gems or bundler with path or git dependencies.
+* Add `Rails.queue` for processing jobs in the background.
### Deprecations
-Action Mailer
--------------
-
-* Allow to set default Action Mailer options via `config.action_mailer.default_options=`.
-
-* Raise an `ActionView::MissingTemplate` exception when no implicit template could be found.
-
-* Asynchronously send messages via the Rails Queue. ([Pull Request](https://github.com/rails/rails/pull/6839))
-
-* Delivery Options (such as SMTP Settings) can now be set dynamically per mailer action.
-
- Delivery options are set via <tt>:delivery_method_options</tt> key on mail.
-
- ```ruby
- def welcome_mailer(user,company)
- delivery_options = { user_name: company.smtp_user, password: company.smtp_password, address: company.smtp_host }
- mail(to: user.email, subject: "Welcome!", delivery_method_options: delivery_options)
- end
- ```
-
-* Allow for callbacks in mailers similar to ActionController::Base. You can now set up headers/attachments using `before_filter` or `after_filter`. You could also change delivery settings or prevent delivery in an after filter based on instance variables set in your mailer action. You have access to `ActionMailer::Base` instance methods like `message`, `attachments`, `headers`.
-
-Action Pack
------------
-
-### Action Controller
-
-* Add `ActionController::Flash.add_flash_types` method to allow people to register their own flash types. e.g.:
-
- ```ruby
- class ApplicationController
- add_flash_types :error, :warning
- end
- ```
-
- If you add the above code, you can use `<%= error %>` in an erb, and `redirect_to /foo, :error => 'message'` in a controller.
-
-* Encrypted Cookies + Sign using Derived Keys. ([Pull Request](https://github.com/rails/rails/pull/8112))
-
-* Remove Active Model dependency from Action Pack.
-
-* Support unicode characters in routes. Route will be automatically escaped, so instead of manually escaping:
-
- ```ruby
- get Rack::Utils.escape('こんにちは') => 'home#index'
- ```
-
- You just have to write the unicode route:
-
- ```ruby
- get 'こんにちは' => 'home#index'
- ```
-
-* Return proper format on exceptions.
-
-* Extracted redirect logic from `ActionController::ForceSSL::ClassMethods.force_ssl` into `ActionController::ForceSSL#force_ssl_redirect`.
-
-* URL path parameters with invalid encoding now raise `ActionController::BadRequest`.
-
-* Malformed query and request parameter hashes now raise `ActionController::BadRequest`.
-
-* `respond_to` and `respond_with` now raise `ActionController::UnknownFormat` instead of directly returning head 406. The exception is rescued and converted to 406 in the exception handling middleware.
-
-* JSONP now uses `application/javascript` instead of `application/json` as the MIME type.
-
-* Session arguments passed to process calls in functional tests are now merged into the existing session, whereas previously they would replace the existing session. This change may break some existing tests if they are asserting the exact contents of the session but should not break existing tests that only assert individual keys.
-
-* Forms of persisted records use always PATCH (via the `_method` hack).
-
-* For resources, both PATCH and PUT are routed to the `update` action.
-
-* Don't ignore `force_ssl` in development. This is a change of behavior - use an `:if` condition to recreate the old behavior.
-
- ```ruby
- class AccountsController < ApplicationController
- force_ssl :if => :ssl_configured?
-
- def ssl_configured?
- !Rails.env.development?
- end
- end
- ```
-
-#### Deprecations
-
-* Deprecated `ActionController::Integration` in favour of `ActionDispatch::Integration`.
-
-* Deprecated `ActionController::IntegrationTest` in favour of `ActionDispatch::IntegrationTest`.
-
-* Deprecated `ActionController::PerformanceTest` in favour of `ActionDispatch::PerformanceTest`.
-
-* Deprecated `ActionController::AbstractRequest` in favour of `ActionDispatch::Request`.
-
-* Deprecated `ActionController::Request` in favour of `ActionDispatch::Request`.
-
-* Deprecated `ActionController::AbstractResponse` in favour of `ActionDispatch::Response`.
-
-* Deprecated `ActionController::Response` in favour of `ActionDispatch::Response`.
-
-* Deprecated `ActionController::Routing` in favour of `ActionDispatch::Routing`.
-
-### Action Dispatch
-
-* Add Routing Concerns to declare common routes that can be reused inside others resources and routes.
-
- Code before:
-
- ```ruby
- resources :messages do
- resources :comments
- end
-
- resources :posts do
- resources :comments
- resources :images, only: :index
- end
- ```
-
- Code after:
-
- ```ruby
- concern :commentable do
- resources :comments
- end
-
- concern :image_attachable do
- resources :images, only: :index
- end
-
- resources :messages, concerns: :commentable
-
- resources :posts, concerns: [:commentable, :image_attachable]
- ```
-
-* Show routes in exception page while debugging a `RoutingError` in development.
-
-* Helper methods for HTML5 inputs. ([Pull Request](https://github.com/rails/rails/pull/6359))
-
-* Include `mounted_helpers` (helpers for accessing mounted engines) in `ActionDispatch::IntegrationTest` by default.
-
-* Added `ActionDispatch::SSL` middleware that when included force all the requests to be under HTTPS protocol.
-
-* Copy literal route constraints to defaults so that url generation know about them. The copied constraints are `:protocol`, `:subdomain`, `:domain`, `:host` and `:port`.
-
-* Allows `assert_redirected_to` to match against a regular expression.
-
-* Adds a backtrace to the routing error page in development.
-
-* `assert_generates`, `assert_recognizes`, and `assert_routing` all raise `Assertion` instead of `RoutingError`.
-
-* Allows the route helper root to take a string argument. For example, `root 'pages#main'` as a shortcut for `root to: 'pages#main'`.
-
-* Adds support for the PATCH verb: Request objects respond to `patch?`. Routes now have a new `patch` method, and understand `:patch` in the existing places where a verb is configured, like `:via`. Functional tests have a new method `patch` and integration tests have a new method `patch_via_redirect`.
-If `:patch` is the default verb for updates, edits are tunneled as `PATCH` rather than as `PUT` and routing acts accordingly.
-
-* Integration tests support the OPTIONS method.
-
-* `expires_in` accepts a `must_revalidate` flag. If true, "must-revalidate" is added to the `Cache-Control` header.
-
-* Default responder will now always use your overridden block in `respond_with` to render your response.
-
-* Turn off verbose mode of `rack-cache`, we still have `X-Rack-Cache` to check that info.
-
-#### Deprecations
-
-### Action View
-
-* Remove Active Model dependency from Action Pack.
-
-* Allow to use `mounted_helpers` (helpers for accessing mounted engines) in `ActionView::TestCase`.
-
-* Make current object and counter (when it applies) variables accessible when rendering templates with `:object` or `:collection`.
-
-* Allow to lazy load `default_form_builder` by passing a string instead of a constant.
-
-* Add index method to `FormBuilder` class.
-
-* Adds support for layouts when rendering a partial with a given collection.
-
-* Remove `:disable_with` in favor of `data-disable-with` option from `submit_tag`, `button_tag` and `button_to` helpers.
-
-* Remove `:mouseover` option from `image_tag` helper.
-
-* Templates without a handler extension now raises a deprecation warning but still defaults to `ERb`. In future releases, it will simply return the template content.
-
-* Add a `divider` option to `grouped_options_for_select` to generate a separator optgroup automatically, and deprecate prompt as third argument, in favor of using an options hash.
-
-* Add `time_field` and `time_field_tag` helpers which render an `input[type="time"]` tag.
-
-* Removed old `text_helper` apis for `highlight`, `excerpt` and `word_wrap`.
-
-* Remove the leading \n added by textarea on `assert_select`.
-
-* Changed default value for `config.action_view.embed_authenticity_token_in_remote_forms` to false. This change breaks remote forms that need to work also without JavaScript, so if you need such behavior, you can either set it to true or explicitly pass `:authenticity_token => true` in form options.
-
-* Make possible to use a block in `button_to` helper if button text is hard to fit into the name parameter:
-
- ```ruby
- <%= button_to [:make_happy, @user] do %>
- Make happy <strong><%= @user.name %></strong>
- <% end %>
- # => "<form method="post" action="/users/1/make_happy" class="button_to">
- # <div>
- # <button type="submit">
- # Make happy <strong>Name</strong>
- # </button>
- # </div>
- # </form>"
- ```
-
-* Replace `include_seconds` boolean argument with `:include_seconds => true` option in `distance_of_time_in_words` and `time_ago_in_words` signature.
-
-* Remove `button_to_function` and `link_to_function` helpers.
-
-* `truncate` now always returns an escaped HTML-safe string. The option `:escape` can be used as `false` to not escape the result.
-
-* `truncate` now accepts a block to show extra content when the text is truncated.
-
-* Add `week_field`, `week_field_tag`, `month_field`, `month_field_tag`, `datetime_local_field`, `datetime_local_field_tag`, `datetime_field` and `datetime_field_tag` helpers.
-
-* Add `color_field` and `color_field_tag` helpers.
-
-* Add `include_hidden` option to select tag. With `:include_hidden => false` select with multiple attribute doesn't generate hidden input with blank value.
-
-* Removed default size option from the `text_field`, `search_field`, `telephone_field`, `url_field`, `email_field` helpers.
-
-* Removed default cols and rows options from the `text_area` helper.
-
-* Adds `image_url`, `javascript_url`, `stylesheet_url`, `audio_url`, `video_url`, and `font_url` to assets tag helper. These URL helpers will return the full path to your assets. This is useful when you are going to reference this asset from external host.
-
-* Allow `value_method` and `text_method` arguments from `collection_select` and `options_from_collection_for_select` to receive an object that responds to `:call` such as a proc, to evaluate the option in the current element context. This works the same way with `collection_radio_buttons` and `collection_check_boxes`.
-
-* Add `date_field` and `date_field_tag` helpers which render an `input[type="date"]` tag.
-
-* Add `collection_check_boxes` form helper, similar to `collection_select`:
-
- ```ruby
- collection_check_boxes :post, :author_ids, Author.all, :id, :name
- # Outputs something like:
- <input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" />
- <label for="post_author_ids_1">D. Heinemeier Hansson</label>
- <input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" />
- <label for="post_author_ids_2">D. Thomas</label>
- <input name="post[author_ids][]" type="hidden" value="" />
- ```
-
- The label/check_box pairs can be customized with a block.
-
-* Add `collection_radio_buttons` form helper, similar to `collection_select`:
-
- ```ruby
- collection_radio_buttons :post, :author_id, Author.all, :id, :name
- # Outputs something like:
- <input id="post_author_id_1" name="post[author_id]" type="radio" value="1" />
- <label for="post_author_id_1">D. Heinemeier Hansson</label>
- <input id="post_author_id_2" name="post[author_id]" type="radio" value="2" />
- <label for="post_author_id_2">D. Thomas</label>
- ```
-
- The label/radio_button pairs can be customized with a block.
-
-* `check_box` with an HTML5 attribute `:form` will now replicate the `:form` attribute to the hidden field as well.
-
-* label form helper accepts `:for => nil` to not generate the attribute.
-
-* Add `:format` option to `number_to_percentage`.
-
-* Add `config.action_view.logger` to configure logger for `Action View`.
+* `config.threadsafe!` is deprecated in favor of `config.eager_load` which provides a more fine grained control on what is eager loaded.
-* `check_box` helper with `:disabled => true` will generate a `disabled` hidden field to conform with the HTML convention where disabled fields are not submitted with the form. This is a behavior change, previously the hidden tag had a value of the disabled checkbox.
+* `Rails::Plugin` has gone. Instead of adding plugins to `vendor/plugins` use gems or bundler with path or git dependencies.
-* `favicon_link_tag` helper will now use the favicon in `app/assets` by default.
-
-* `ActionView::Helpers::TextHelper#highlight` now defaults to the HTML5 `mark` element.
-
-#### Deprecations
-
-### Sprockets
-
-Moved into a separate gem `sprockets-rails`.
-
-Active Record
+Action Mailer
-------------
-* Add `add_reference` and `remove_reference` schema statements. Aliases, `add_belongs_to` and `remove_belongs_to` are acceptable. References are reversible.
-
- ```ruby
- # Create a user_id column
- add_reference(:products, :user)
-
- # Create a supplier_id, supplier_type columns and appropriate index
- add_reference(:products, :supplier, polymorphic: true, index: true)
-
- # Remove polymorphic reference
- remove_reference(:products, :supplier, polymorphic: true)
- ```
-
-* Add `:default` and `:null` options to `column_exists?`.
-
- ```ruby
- column_exists?(:testings, :taggable_id, :integer, null: false)
- column_exists?(:testings, :taggable_type, :string, default: 'Photo')
- ```
-
-* `ActiveRecord::Relation#inspect` now makes it clear that you are dealing with a `Relation` object rather than an array:
-
- ```ruby
- User.where(:age => 30).inspect
- # => <ActiveRecord::Relation [#<User ...>, #<User ...>]>
-
- User.where(:age => 30).to_a.inspect
- # => [#<User ...>, #<User ...>]
- ```
-
- if more than 10 items are returned by the relation, inspect will only show the first 10 followed by ellipsis.
-
-* Add `:collation` and `:ctype` support to PostgreSQL. These are available for PostgreSQL 8.4 or later.
-
- ```yaml
- development:
- adapter: postgresql
- host: localhost
- database: rails_development
- username: foo
- password: bar
- encoding: UTF8
- collation: ja_JP.UTF8
- ctype: ja_JP.UTF8
- ```
-
-* `FinderMethods#exists?` now returns `false` with the `false` argument.
-
-* Added support for specifying the precision of a timestamp in the postgresql adapter. So, instead of having to incorrectly specify the precision using the `:limit` option, you may use `:precision`, as intended. For example, in a migration:
-
- ```ruby
- def change
- create_table :foobars do |t|
- t.timestamps :precision => 0
- end
- end
- ```
-
-* Allow `ActiveRecord::Relation#pluck` to accept multiple columns. Returns an array of arrays containing the typecasted values:
-
- ```ruby
- Person.pluck(:id, :name)
- # SELECT people.id, people.name FROM people
- # => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
- ```
-
-* Improve the derivation of HABTM join table name to take account of nesting. It now takes the table names of the two models, sorts them lexically and then joins them, stripping any common prefix from the second table name. Some examples:
-
- ```
- Top level models (Category <=> Product)
- Old: categories_products
- New: categories_products
-
- Top level models with a global table_name_prefix (Category <=> Product)
- Old: site_categories_products
- New: site_categories_products
-
- Nested models in a module without a table_name_prefix method (Admin::Category <=> Admin::Product)
- Old: categories_products
- New: categories_products
-
- Nested models in a module with a table_name_prefix method (Admin::Category <=> Admin::Product)
- Old: categories_products
- New: admin_categories_products
-
- Nested models in a parent model (Catalog::Category <=> Catalog::Product)
- Old: categories_products
- New: catalog_categories_products
-
- Nested models in different parent models (Catalog::Category <=> Content::Page)
- Old: categories_pages
- New: catalog_categories_content_pages
- ```
-
-* Move HABTM validity checks to `ActiveRecord::Reflection`. One side effect of this is to move when the exceptions are raised from the point of declaration to when the association is built. This is consistant with other association validity checks.
-
-* Added `stored_attributes` hash which contains the attributes stored using `ActiveRecord::Store`. This allows you to retrieve the list of attributes you've defined.
-
- ```ruby
- class User < ActiveRecord::Base
- store :settings, accessors: [:color, :homepage]
- end
-
- User.stored_attributes[:settings] # [:color, :homepage]
- ```
-
-* PostgreSQL default log level is now 'warning', to bypass the noisy notice messages. You can change the log level using the `min_messages` option available in your `config/database.yml`.
-
-* Add uuid datatype support to PostgreSQL adapter.
-
-* Added `ActiveRecord::Migration.check_pending!` that raises an error if migrations are pending.
-
-* Added `#destroy!` which acts like `#destroy` but will raise an `ActiveRecord::RecordNotDestroyed` exception instead of returning `false`.
-
-* Allow blocks for count with `ActiveRecord::Relation`, to work similar as `Array#count`: `Person.where("age > 26").count { |person| person.gender == 'female' }`
-
-* Added support to `CollectionAssociation#delete` for passing fixnum or string values as record ids. This finds the records responding to the ids and deletes them.
-
- ```ruby
- class Person < ActiveRecord::Base
- has_many :pets
- end
-
- person.pets.delete("1") # => [#<Pet id: 1>]
- person.pets.delete(2, 3) # => [#<Pet id: 2>, #<Pet id: 3>]
- ```
-
-* It's not possible anymore to destroy a model marked as read only.
-
-* Added ability to `ActiveRecord::Relation#from` to accept other `ActiveRecord::Relation` objects.
-
-* Added custom coders support for `ActiveRecord::Store`. Now you can set your custom coder like this:
-
- ```ruby
- store :settings, accessors: [ :color, :homepage ], coder: JSON
- ```
-
-* `mysql` and `mysql2` connections will set `SQL_MODE=STRICT_ALL_TABLES` by default to avoid silent data loss. This can be disabled by specifying `strict: false` in `config/database.yml`. ([Pull Request](https://github.com/rails/rails/pull/6069))
-
-* Added default order to `ActiveRecord::Base#first` to assure consistent results among different database engines. Introduced `ActiveRecord::Base#take` as a replacement to the old behavior.
-
-* Added an `:index` option to automatically create indexes for `references` and `belongs_to` statements in migrations. This can be either a boolean or a hash that is identical to options available to the `add_index` method:
-
- ```ruby
- create_table :messages do |t|
- t.references :person, :index => true
- end
- ```
-
- Is the same as:
-
- ```ruby
- create_table :messages do |t|
- t.references :person
- end
- add_index :messages, :person_id
- ```
-
- Generators have also been updated to use the new syntax.
-
-* Added bang methods for mutating `ActiveRecord::Relation` objects. For example, while `foo.where(:bar)` will return a new object leaving foo unchanged, `foo.where!(:bar)` will mutate the foo object.
-
-* Added `#find_by` and `#find_by!` to mirror the functionality provided by dynamic finders in a way that allows dynamic input more easily:
-
- ```ruby
- Post.find_by name: 'Spartacus', rating: 4
- Post.find_by "published_at < ?", 2.weeks.ago
- Post.find_by! name: 'Spartacus'
- ```
-
-* Added `ActiveRecord::Base#slice` to return a hash of the given methods with their names as keys and returned values as values.
-
-* Remove IdentityMap - IdentityMap has never graduated to be an "enabled-by-default" feature, due to some inconsistencies with associations, as described in this [commit](https://github.com/rails/rails/commit/302c912bf6bcd0fa200d964ec2dc4a44abe328a6). Hence the removal from the codebase, until such issues are fixed.
-
-* Added a feature to dump/load internal state of `SchemaCache` instance because we want to boot more quickly when we have many models. ([Pull Request](https://github.com/rails/rails/pull/5162))
-
- ```ruby
- # execute rake task.
- RAILS_ENV=production bundle exec rake db:schema:cache:dump
- => generate db/schema_cache.dump
-
- # add config.use_schema_cache_dump = true in config/production.rb. BTW, true is default.
-
- # boot rails.
- RAILS_ENV=production bundle exec rails server
- => use db/schema_cache.dump
-
- # If you remove clear dumped cache, execute rake task.
- RAILS_ENV=production bundle exec rake db:schema:cache:clear
- => remove db/schema_cache.dump
- ```
-
-* Added support for partial indices to `PostgreSQL` adapter.
-
-* The `add_index` method now supports a `where` option that receives a string with the partial index criteria.
-
-* Added the `ActiveRecord::NullRelation` class implementing the null object pattern for the Relation class.
-
-* Implemented `ActiveRecord::Relation#none` method which returns a chainable relation with zero records (an instance of the `NullRelation` class). Any subsequent condition chained to the returned relation will continue generating an empty relation and will not fire any query to the database.
-
-* Added `create_join_table` migration helper to create HABTM join tables.
-
- ```ruby
- create_join_table :products, :categories
- # =>
- # create_table :categories_products, :id => false do |td|
- # td.integer :product_id, :null => false
- # td.integer :category_id, :null => false
- # end
- ```
-
-* The primary key is always initialized in the `@attributes` hash to nil (unless another value has been specified).
-
-* In previous releases, the following would generate a single query with an OUTER JOIN comments, rather than two separate queries:
-
- ```ruby
- Post.includes(:comments).where("comments.name = 'foo'")
- ```
+Please refer to the [Changelog](https://github.com/rails/rails/blob/master/actionmailer/CHANGELOG.md) for detailed changes.
- This behaviour relies on matching SQL string, which is an inherently flawed idea unless we write an SQL parser, which we do not wish to do. Therefore, it is now deprecated.
+### Notable changes
- To avoid deprecation warnings and for future compatibility, you must explicitly state which tables you reference, when using SQL snippets:
-
- ```ruby
- Post.includes(:comments).where("comments.name = 'foo'").references(:comments)
- ```
-
- Note that you do not need to explicitly specify references in the following cases, as they can be automatically inferred:
-
- ```ruby
- Post.where(comments: { name: 'foo' })
- Post.where('comments.name' => 'foo')
- Post.order('comments.name')
- ```
-
- You also do not need to worry about this unless you are doing eager loading. Basically, don't worry unless you see a deprecation warning or (in future releases) an SQL error due to a missing JOIN.
-
-* Support for the `schema_info` table has been dropped. Please switch to `schema_migrations`.
-
-* Connections *must* be closed at the end of a thread. If not, your connection pool can fill and an exception will be raised.
-
-* PostgreSQL hstore records can be created.
-
-* PostgreSQL hstore types are automatically deserialized from the database.
-
-* Support for array datatype in PostgreSQL. ([Pull Request](https://github.com/rails/rails/pull/7547))
-
-* Added `#update_columns` method which updates the attributes from the passed-in hash without calling save, hence skipping validations and callbacks. `ActiveRecordError` will be raised when called on new objects or when at least one of the attributes is marked as read only.
-
- ```ruby
- post.attributes # => {"id"=>2, "title"=>"My title", "body"=>"My content", "author"=>"Peter"}
- post.update_columns({title: 'New title', author: 'Sebastian'}) # => true
- post.attributes # => {"id"=>2, "title"=>"New title", "body"=>"My content", "author"=>"Sebastian"}
- ```
+* Asynchronously send messages via the Rails Queue. ([Pull Request](https://github.com/rails/rails/pull/6839))
### Deprecations
-* Deprecated most of the 'dynamic finder' methods. All dynamic methods except for `find_by_...` and `find_by_...!` are deprecated. Here's how you can rewrite the code:
-
- ```ruby
- find_all_by_... can be rewritten using where(...)
- find_last_by_... can be rewritten using where(...).last
- scoped_by_... can be rewritten using where(...)
- find_or_initialize_by_... can be rewritten using where(...).first_or_initialize
- find_or_create_by_... can be rewritten using where(...).first_or_create
- find_or_create_by_...! can be rewritten using where(...).first_or_create!
- ```
-
- The implementation of the deprecated dynamic finders has been moved to the `active_record_deprecated_finders` gem.
-
-* Deprecated the old-style hash based finder API. This means that methods which previously accepted "finder options" no longer do. For example this:
-
- ```ruby
- Post.find(:all, :conditions => { :comments_count => 10 }, :limit => 5)
- ```
-
- should be rewritten in the new style which has existed since Rails 3:
-
- ```ruby
- Post.where(comments_count: 10).limit(5)
- ```
-
- Note that as an interim step, it is possible to rewrite the above as:
-
- ```ruby
- Post.scoped(:where => { :comments_count => 10 }, :limit => 5)
- ```
-
- This could save you a lot of work if there is a lot of old-style finder usage in your application.
-
- Calling `Post.scoped(options)` is a shortcut for `Post.scoped.merge(options)`. `Relation#merge` now accepts a hash of options, but they must be identical to the names of the equivalent finder method. These are mostly identical to the old-style finder option names, except in the following cases:
-
- ```
- :conditions becomes :where
- :include becomes :includes
- :extend becomes :extending
- ```
-
- The code to implement the deprecated features has been moved out to the `active_record_deprecated_finders` gem. This gem is a dependency of Active Record in Rails 4.0. It will no longer be a dependency from Rails 4.1, but if your app relies on the deprecated features then you can add it to your own Gemfile. It will be maintained by the Rails core team until Rails 5.0 is released.
-
-* Deprecate eager-evaluated scopes.
-
- Don't use this:
-
- ```ruby
- scope :red, where(color: 'red')
- default_scope where(color: 'red')
- ```
-
- Use this:
-
- ```ruby
- scope :red, -> { where(color: 'red') }
- default_scope { where(color: 'red') }
- ```
-
- The former has numerous issues. It is a common newbie gotcha to do the following:
-
- ```ruby
- scope :recent, where(published_at: Time.now - 2.weeks)
- ```
-
- Or a more subtle variant:
-
- ```ruby
- scope :recent, -> { where(published_at: Time.now - 2.weeks) }
- scope :recent_red, recent.where(color: 'red')
- ```
-
- Eager scopes are also very complex to implement within Active Record, and there are still bugs. For example, the following does not do what you expect:
-
- ```ruby
- scope :remove_conditions, except(:where)
- where(...).remove_conditions # => still has conditions
- ```
-
-* Added deprecation for the `:dependent => :restrict` association option.
-
-* Up until now `has_many` and `has_one, :dependent => :restrict` option raised a `DeleteRestrictionError` at the time of destroying the object. Instead, it will add an error on the model.
-
-* To fix this warning, make sure your code isn't relying on a `DeleteRestrictionError` and then add `config.active_record.dependent_restrict_raises = false` to your application config.
-
-* New rails application would be generated with the `config.active_record.dependent_restrict_raises = false` in the application config.
-
-* The migration generator now creates a join table with (commented) indexes every time the migration name contains the word "join_table".
-
-* `ActiveRecord::SessionStore` is removed from Rails 4.0 and is now a separate [gem](https://github.com/rails/activerecord-session_store).
-
Active Model
------------
-* Changed `AM::Serializers::JSON.include_root_in_json` default value to false. Now, AM Serializers and AR objects have the same default behaviour.
-
- ```ruby
- class User < ActiveRecord::Base; end
-
- class Person
- include ActiveModel::Model
- include ActiveModel::AttributeMethods
- include ActiveModel::Serializers::JSON
-
- attr_accessor :name, :age
-
- def attributes
- instance_values
- end
- end
+Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activemodel/CHANGELOG.md) for detailed changes.
- user.as_json
- => {"id"=>1, "name"=>"Konata Izumi", "age"=>16, "awesome"=>true}
- # root is not included
+### Notable changes
- person.as_json
- => {"name"=>"Francesco", "age"=>22}
- # root is not included
- ```
+* Add `ActiveModel::ForbiddenAttributesProtection`, a simple module to protect attributes from mass assignment when non-permitted attributes are passed.
-* Passing false hash values to `validates` will no longer enable the corresponding validators.
-
-* `ConfirmationValidator` error messages will attach to `:#{attribute}_confirmation` instead of `attribute`.
-
-* Added `ActiveModel::Model`, a mixin to make Ruby objects work with Action Pack out of the box. ([Pull Request](https://github.com/rails/rails/pull/5253))
-
-* `ActiveModel::Errors#to_json` supports a new parameter `:full_messages`.
-
-* Trims down the API by removing `valid?` and `errors.full_messages`.
+* Added `ActiveModel::Model`, a mixin to make Ruby objects work with AP out of box.
### Deprecations
-Active Resource
----------------
-
-* Active Resource is removed from Rails 4.0 and is now a separate [gem](https://github.com/rails/activeresource).
-
Active Support
--------------
-* Add default values to all `ActiveSupport::NumberHelper` methods, to avoid errors with empty locales or missing values.
-
-* `Time#change` now works with time values with offsets other than UTC or the local time zone.
-
-* Add `Time#prev_quarter` and `Time#next_quarter` short-hands for `months_ago(3)` and `months_since(3)`.
-
-* Add `Time#last_week`, `Time#last_month`, `Time#last_year` as aliases for `Time#prev_week`, `Time#prev_month`, and `Time#prev_year`.
+Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activesupport/CHANGELOG.md) for detailed changes.
-* Add `Date#last_week`, `Date#last_month`, `Date#last_year` as aliases for `Date#prev_week`, `Date#prev_month`, and `Date#prev_year`.
+### Notable changes
-* Remove obsolete and unused `require_association` method from dependencies.
+* Replace deprecated `memcache-client` gem with `dalli` in ActiveSupport::Cache::MemCacheStore.
-* Add `:instance_accessor` option for `config_accessor`.
+* Optimize ActiveSupport::Cache::Entry to reduce memory and processing overhead.
- ```ruby
- class User
- include ActiveSupport::Configurable
- config_accessor :allowed_access, instance_accessor: false
- end
+* Inflections can now be defined per locale. `singularize` and `pluralize` accept locale as an extra argument.
- User.new.allowed_access = true # => NoMethodError
- User.new.allowed_access # => NoMethodError
- ```
+* `Object#try` will now return nil instead of raise a NoMethodError if the receiving object does not implement the method, but you can still get the old behavior by using the new `Object#try!`.
-* `ActionView::Helpers::NumberHelper` methods have been moved to `ActiveSupport::NumberHelper` and are now available via `Numeric#to_s`.
-
-* `Numeric#to_s` now accepts the formatting options :phone, :currency, :percentage, :delimited, :rounded, :human, and :human_size.
-
-* Add `Hash#transform_keys`, `Hash#transform_keys!`, `Hash#deep_transform_keys` and `Hash#deep_transform_keys!`.
-
-* Changed xml type datetime to dateTime (with upper case letter T).
-
-* Add `:instance_accessor` option for `class_attribute`.
-
-* `constantize` now looks in the ancestor chain.
-
-* Add `Hash#deep_stringify_keys` and `Hash#deep_stringify_keys!` to convert all keys from a `Hash` instance into strings.
-
-* Add `Hash#deep_symbolize_keys` and `Hash#deep_symbolize_keys!` to convert all keys from a `Hash` instance into symbols.
-
-* `Object#try` can't call private methods.
-
-* AS::Callbacks#run_callbacks remove key argument.
+### Deprecations
-* `deep_dup` works more expectedly now and duplicates also values in `Hash` instances and elements in `Array` instances.
+* Deprecate `ActiveSupport::TestCase#pending` method, use `skip` from MiniTest instead.
-* Inflector no longer applies ice -> ouse to words like slice, police.
+* ActiveSupport::Benchmarkable#silence has been deprecated due to its lack of thread safety. It will be removed without replacement in Rails 4.1.
-* Add `ActiveSupport::Deprecations.behavior = :silence` to completely ignore Rails runtime deprecations.
+* `ActiveSupport::JSON::Variable` is deprecated. Define your own `#as_json` and `#encode_json` methods for custom JSON string literals.
-* Make `Module#delegate` stop using send - can no longer delegate to private methods.
+* Deprecates the compatibility method Module#local_constant_names, use Module#local_constants instead (which returns symbols).
-* AS::Callbacks deprecate :rescuable option.
+* BufferedLogger is deprecated. Use ActiveSupport::Logger, or the logger from Ruby stdlib.
-* Adds `Integer#ordinal` to get the ordinal suffix string of an integer.
-* AS::Callbacks :per_key option is no longer supported.
+Action Pack
+-----------
-* AS::Callbacks#define_callbacks add :skip_after_callbacks_if_terminated option.
+Please refer to the [Changelog](https://github.com/rails/rails/blob/master/railties/CHANGELOG.md) for detailed changes.
-* Add html_escape_once to ERB::Util, and delegate escape_once tag helper to it.
+### Notable changes
-* Remove `ActiveSupport::TestCase#pending` method, use `skip` instead.
+### Deprecations
-* Deletes the compatibility method `Module#method_names`, use `Module#methods` from now on (which returns symbols).
-* Deletes the compatibility method `Module#instance_method_names`, use `Module#instance_methods` from now on (which returns symbols).
+Active Record
+-------------
-* Unicode database updated to 6.1.0.
+Please refer to the [Changelog](https://github.com/rails/rails/blob/master/railties/CHANGELOG.md) for detailed changes.
-* Adds `encode_big_decimal_as_string` option to force JSON serialization of BigDecimals as numeric instead of wrapping them in strings for safety.
+### Notable changes
### Deprecations
-* `ActiveSupport::Callbacks`: deprecate usage of filter object with `#before` and `#after` methods as `around` callback.
-
-* `BufferedLogger` is deprecated. Use `ActiveSupport::Logger` or the `logger` from Ruby stdlib.
-
-* Deprecates the compatibility method `Module#local_constant_names` and use `Module#local_constants` instead (which returns symbols).
-
Credits
-------
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 83cb5e5a3f..ddb0e438c9 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -397,7 +397,7 @@ end
The above will send a multipart email with an attachment, properly nested with the top level being `multipart/mixed` and the first part being a `multipart/alternative` containing the plain text and HTML email messages.
-#### Sending Emails with Dynamic Delivery Options
+### Sending Emails with Dynamic Delivery Options
If you wish to override the default delivery options (e.g. SMTP credentials) while delivering emails, you can do this using `delivery_method_options` in the mailer action.
@@ -444,6 +444,57 @@ class UserMailer < ActionMailer::Base
end
```
+Action Mailer Callbacks
+---------------------------
+
+Action Mailer allows for you to specify a `before_filter`, `after_filter` and 'around_filter'.
+
+* Filters can be specified with a block or a symbol to a method in the mailer class similar to controllers.
+
+* You could use a `before_filter` to prepopulate the mail object with defaults, delivery_method_options or insert default headers and attachments.
+
+* You could use an `after_filter` to do similar setup as a `before_filter` but using instance variables set in your mailer action.
+
+```ruby
+class UserMailer < ActionMailer::Base
+ after_filter :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers
+
+ def feedback_message(business, user)
+ @business = business
+ @user = user
+ mail
+ end
+
+ def campaign_message(business, user)
+ @business = business
+ @user = user
+ end
+
+ private
+
+ def set_delivery_options
+ # You have access to the mail instance and @business and @user instance variables here
+ if @business && @business.has_smtp_settings?
+ mail.delivery_method.settings.merge!(@business.smtp_settings)
+ end
+ end
+
+ def prevent_delivery_to_guests
+ if @user && @user.guest?
+ mail.perform_deliveries = false
+ end
+ end
+
+ def set_business_headers
+ if @business
+ headers["X-SMTPAPI-CATEGORY"] = @business.code
+ end
+ end
+end
+```
+
+* Mailer Filters abort further processing if body is set to a non-nil value.
+
Using Action Mailer Helpers
---------------------------
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index 541b1a1e84..e752c6f3f9 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -6,34 +6,76 @@ the database using Active Record's validations feature.
After reading this guide, you will know:
-* Understand the life cycle 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 life cycle.
-* Create special classes that encapsulate common behavior for your callbacks.
+* Use the built-in Active Record validation helpers
+* Create your own custom validation methods
+* Work with the error messages generated by the validation process
--------------------------------------------------------------------------------
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.
+Here's an example of a very simple validation:
-### Why Use Validations?
+```ruby
+class Person < ActiveRecord::Base
+ validates :name, presence: true
+end
-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.
+Person.create(name: "John Doe").valid? # => true
+Person.create(name: nil).valid? # => false
+```
-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:
+As you can see, our validation lets us know that our `Person` is not valid
+without a `name` attribute. The second `Person` will not be persisted to the
+database.
-* 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.
+Before we dig into more details, let's talk about how validations fit into the
+big picture of your application.
+
+### 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. 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.
+
+There are several other ways to validate data before it is saved into your
+database, including native database constraints, client-side validations,
+controller-level validations. Here's a summary of the pros and cons:
+
+* 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, as it will make your application a
+ pleasure to work with in the long run.
+
+Choose these in certain, specific cases. It's the opinion of the Rails team
+that model-level validations are the most appropriate in most circumstances.
### 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:
+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:
```ruby
class Person < ActiveRecord::Base
@@ -54,13 +96,21 @@ $ rails console
=> false
```
-TIP: All lines starting with a dollar sign `$` are intended to be run on the command line.
+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 avoids
+storing an invalid object in the database. You can choose to have specific
+validations run when an object is created, saved, or updated.
-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.
-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:
+The following methods trigger validations, and will save the object to the
+database only if the object is valid:
* `create`
* `create!`
@@ -70,11 +120,14 @@ 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 objects.
+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.
### 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.
+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`
@@ -88,13 +141,17 @@ The following methods skip validations, and will save the object to the database
* `update_columns`
* `update_counters`
-Note that `save` also has the ability to skip validations if passed `validate: false` as argument. This technique should be used with caution.
+Note that `save` also has the ability to skip validations if passed `validate:
+false` as argument. This technique should be used with caution.
* `save(validate: false)`
### `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 found in the object, and false otherwise.
+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 found in the object, and false otherwise.
+As you saw above:
```ruby
class Person < ActiveRecord::Base
@@ -105,9 +162,13 @@ Person.create(name: "John Doe").valid? # => true
Person.create(name: nil).valid? # => false
```
-After Active Record has performed validations, any errors found can be accessed through the `errors` instance method, which returns a collection of errors. By definition, an object is valid if this collection is empty after running validations.
+After Active Record has performed validations, any errors found can be accessed
+through the `errors` instance method, which returns a collection of errors. 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`.
+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`.
```ruby
class Person < ActiveRecord::Base
@@ -139,13 +200,21 @@ end
#=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
```
-`invalid?` is simply the inverse of `valid?`. It triggers your validations, returning true if any errors were found in the object, and false otherwise.
+`invalid?` is simply the inverse of `valid?`. It triggers your validations,
+returning true if any errors were found in the object, and false otherwise.
### `errors[]`
-To verify whether or not a particular attribute of an object is valid, you can use `errors[:attribute]`. It returns an array of all the errors for `:attribute`. If there are no errors on the specified attribute, an empty array is returned.
+To verify whether or not a particular attribute of an object is valid, you can
+use `errors[:attribute]`. It returns an array of all the errors for
+`:attribute`. If 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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -156,20 +225,38 @@ end
>> 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.
+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.
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 attribute being validated.
+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 attribute 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.
+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.
+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.
### `acceptance`
-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).
+This method 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).
```ruby
class Person < ActiveRecord::Base
@@ -179,7 +266,8 @@ end
The default error message for this helper is "_must be accepted_".
-It can receive an `:accept` option, which determines the value that will be considered acceptance. It defaults to "1" and can be easily changed.
+It can receive an `:accept` option, which determines the value that will be
+considered acceptance. It defaults to "1" and can be easily changed.
```ruby
class Person < ActiveRecord::Base
@@ -189,7 +277,9 @@ end
### `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.
+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.
```ruby
class Library < ActiveRecord::Base
@@ -200,13 +290,19 @@ 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.
+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.
+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.
### `confirmation`
-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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -221,7 +317,9 @@ In your view template you could use something like
<%= 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 `presence` later on this guide):
+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 `presence` later on this guide):
```ruby
class Person < ActiveRecord::Base
@@ -234,7 +332,8 @@ The default error message for this helper is "_doesn't match confirmation_".
### `exclusion`
-This helper validates that the attributes' values are not included in a given set. In fact, this set can be any enumerable object.
+This helper validates that the attributes' values are not included in a given
+set. In fact, this set can be any enumerable object.
```ruby
class Account < ActiveRecord::Base
@@ -243,13 +342,18 @@ class Account < ActiveRecord::Base
end
```
-The `exclusion` 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 `exclusion` 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 is "_is reserved_".
### `format`
-This helper validates the attributes' values by testing whether they match a given regular expression, which is specified using the `:with` option.
+This helper validates the attributes' values by testing whether they match a
+given regular expression, which is specified using the `:with` option.
```ruby
class Product < ActiveRecord::Base
@@ -262,7 +366,8 @@ The default error message is "_is invalid_".
### `inclusion`
-This helper validates that the attributes' values are included in a given set. In fact, this set can be any enumerable object.
+This helper validates that the attributes' values are included in a given set.
+In fact, this set can be any enumerable object.
```ruby
class Coffee < ActiveRecord::Base
@@ -271,13 +376,17 @@ class Coffee < ActiveRecord::Base
end
```
-The `inclusion` 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 `inclusion` 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 this helper is "_is not included in the list_".
### `length`
-This helper validates the length of the attributes' values. It provides a variety of options, so you can specify length constraints in different ways:
+This helper validates the length of the attributes' values. It provides a
+variety of options, so you can specify length constraints in different ways:
```ruby
class Person < ActiveRecord::Base
@@ -292,10 +401,15 @@ 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.
+* `: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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -304,7 +418,8 @@ class Person < ActiveRecord::Base
end
```
-This helper counts characters by default, but you can split the value in a different way using the `:tokenizer` option:
+This helper counts characters by default, but you can split the value in a
+different way using the `:tokenizer` option:
```ruby
class Essay < ActiveRecord::Base
@@ -318,13 +433,20 @@ class Essay < ActiveRecord::Base
end
```
-Note that the default error messages are plural (e.g., "is too short (minimum is %{count} characters)"). For this reason, when `:minimum` is 1 you should provide a personalized message or use `validates_presence_of` instead. When `:in` or `:within` have a lower limit of 1, you should either provide a personalized message or call `presence` prior to `length`.
+Note that the default error messages are plural (e.g., "is too short (minimum
+is %{count} characters)"). For this reason, when `:minimum` is 1 you should
+provide a personalized message or use `validates_presence_of` instead. When
+`:in` or `:within` have a lower limit of 1, you should either provide a
+personalized message or call `presence` prior to `length`.
The `size` helper is an alias for `length`.
### `numericality`
-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.
+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
@@ -332,9 +454,11 @@ 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`.
+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.
+WARNING. Note that the regular expression above allows a trailing newline
+character.
```ruby
class Player < ActiveRecord::Base
@@ -343,21 +467,34 @@ class Player < ActiveRecord::Base
end
```
-Besides `:only_integer`, this 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_".
+Besides `:only_integer`, this 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 is "_is not a number_".
### `presence`
-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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -365,7 +502,9 @@ class Person < ActiveRecord::Base
end
```
-If you want to be sure that an association is present, you'll need to test the associated object itself, and not whether the foreign key used to map the association is present:
+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.
```ruby
class LineItem < ActiveRecord::Base
@@ -382,15 +521,22 @@ class Order < ActiveRecord::Base
end
```
-If you validate the presence of an object associated via a `has_one` or `has_many` relationship, it will check that the object is neither `blank?` nor `marked_for_destruction?`.
+If you validate the presence of an object associated via a `has_one` or
+`has_many` relationship, it will check that the object is neither `blank?` nor
+`marked_for_destruction?`.
-Since `false.blank?` is true, if you want to validate the presence of a boolean field you should use `validates :field_name, inclusion: { in: [true, false] }`.
+Since `false.blank?` is true, if you want to validate the presence of a boolean
+field you should use `validates :field_name, inclusion: { in: [true, false] }`.
The default error message is "_can't be empty_".
### `uniqueness`
-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.
+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.
```ruby
class Account < ActiveRecord::Base
@@ -398,9 +544,11 @@ class Account < ActiveRecord::Base
end
```
-The validation happens by performing an SQL query into the model's table, searching for an existing record with the same value in that attribute.
+The validation happens by performing an 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:
+There is a `:scope` option that you can use to specify other attributes that
+are used to limit the uniqueness check:
```ruby
class Holiday < ActiveRecord::Base
@@ -409,7 +557,9 @@ class Holiday < ActiveRecord::Base
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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -417,7 +567,8 @@ class Person < ActiveRecord::Base
end
```
-WARNING. Note that some databases are configured to perform case-insensitive searches anyway.
+WARNING. Note that some databases are configured to perform case-insensitive
+searches anyway.
The default error message is "_has already been taken_".
@@ -439,13 +590,19 @@ class GoodnessValidator < ActiveModel::Validator
end
```
-NOTE: Errors added to `record.errors[:base]` relate to the state of the record as a whole, and not to a specific attribute.
+NOTE: Errors added to `record.errors[:base]` relate to the state of the record
+as a whole, and not to a specific attribute.
-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.
-To implement the validate method, you must have a `record` parameter defined, which is the record to be validated.
+To implement the validate method, you must have a `record` parameter defined,
+which is the record to be validated.
-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`:
```ruby
class Person < ActiveRecord::Base
@@ -463,7 +620,10 @@ end
### `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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -473,7 +633,10 @@ class Person < ActiveRecord::Base
end
```
-The block receives the record, 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 should add an error message to the model, therefore making it invalid.
+The block receives the record, 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 should add an error message to the model, therefore
+making it invalid.
Common Validation Options
-------------------------
@@ -482,7 +645,8 @@ These are common validation options:
### `:allow_nil`
-The `:allow_nil` option skips the validation when the value being validated is `nil`.
+The `:allow_nil` option skips the validation when the value being validated is
+`nil`.
```ruby
class Coffee < ActiveRecord::Base
@@ -495,7 +659,9 @@ TIP: `:allow_nil` is ignored by the presence validator.
### `: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.
+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.
```ruby
class Topic < ActiveRecord::Base
@@ -510,11 +676,19 @@ TIP: `:allow_blank` is ignored by the presence validator.
### `: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.
+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.
### `: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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -532,7 +706,8 @@ end
Strict Validations
------------------
-You can also specify validations to be strict and raise `ActiveModel::StrictValidationFailed` when the object is invalid.
+You can also specify validations to be strict and raise
+`ActiveModel::StrictValidationFailed` when the object is invalid.
```ruby
class Person < ActiveRecord::Base
@@ -555,11 +730,18 @@ Person.new.valid? #=> TokenGenerationException: Token can't be blank
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, a `Proc` or an `Array`. 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.
+Sometimes it will make sense to validate an object 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, a `Proc` or an `Array`. 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.
### 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.
+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.
```ruby
class Order < ActiveRecord::Base
@@ -573,7 +755,9 @@ end
### 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.
+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.
```ruby
class Person < ActiveRecord::Base
@@ -583,7 +767,10 @@ end
### 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.
+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.
```ruby
class Account < ActiveRecord::Base
@@ -594,7 +781,8 @@ end
### Grouping conditional validations
-Sometimes it is useful to have multiple validations use one condition, it can be easily achieved using `with_options`.
+Sometimes it is useful to have multiple validations use one condition, it can
+be easily achieved using `with_options`.
```ruby
class User < ActiveRecord::Base
@@ -605,11 +793,14 @@ class User < ActiveRecord::Base
end
```
-All validations inside of `with_options` block will have automatically passed the condition `if: :is_admin?`
+All validations inside of `with_options` block will have automatically passed
+the condition `if: :is_admin?`
### Combining validation conditions
-On the other hand, when multiple conditions define whether or not a validation should happen, an `Array` can be used. Moreover, you can apply both `:if` and `:unless` to the same validation.
+On the other hand, when multiple conditions define whether or not a validation
+should happen, an `Array` can be used. Moreover, you can apply both `:if` and
+`:unless` to the same validation.
```ruby
class Computer < ActiveRecord::Base
@@ -619,16 +810,21 @@ class Computer < ActiveRecord::Base
end
```
-The validation only runs when all the `:if` conditions and none of the `:unless` conditions are evaluated to `true`.
+The validation only runs when all the `:if` conditions and none of the
+`:unless` conditions are evaluated to `true`.
Performing Custom Validations
-----------------------------
-When the built-in validation helpers are not enough for your needs, you can write your own validators or validation methods as you prefer.
+When the built-in validation helpers are not enough for your needs, you can
+write your own validators or validation methods as you prefer.
### Custom Validators
-Custom validators are classes that extend `ActiveModel::Validator`. These classes must implement a `validate` method which takes a record as an argument and performs the validation on it. The custom validator is called using the `validates_with` method.
+Custom validators are classes that extend `ActiveModel::Validator`. These
+classes must implement a `validate` method which takes a record as an argument
+and performs the validation on it. The custom validator is called using the
+`validates_with` method.
```ruby
class MyValidator < ActiveModel::Validator
@@ -645,7 +841,12 @@ class Person
end
```
-The easiest way to add custom validators for validating individual attributes is with the convenient `ActiveModel::EachValidator`. In this case, the custom validator class must implement a `validate_each` method which takes three arguments: record, attribute and value which correspond to the instance, the attribute to be validated and the value of the attribute in the passed instance.
+The easiest way to add custom validators for validating individual attributes
+is with the convenient `ActiveModel::EachValidator`. In this case, the custom
+validator class must implement a `validate_each` method which takes three
+arguments: record, attribute and value which correspond to the instance, the
+attribute to be validated and the value of the attribute in the passed
+instance.
```ruby
class EmailValidator < ActiveModel::EachValidator
@@ -661,13 +862,18 @@ class Person < ActiveRecord::Base
end
```
-As shown in the example, you can also combine standard validations with your own custom validators.
+As shown in the example, you can also combine standard validations with your
+own custom validators.
### Custom Methods
-You can also 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 the `validate` class method, passing in the symbols for the validation methods' names.
+You can also 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 the `validate` class method, 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.
+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.
```ruby
class Invoice < ActiveRecord::Base
@@ -688,7 +894,9 @@ class Invoice < ActiveRecord::Base
end
```
-By default such validations will run every time you call `valid?`. It is also possible to control when to run these custom validations by giving an `:on` option to the `validate` method, with either: `:create` or `:update`.
+By default such validations will run every time you call `valid?`. It is also
+possible to control when to run these custom validations by giving an `:on`
+option to the `validate` method, with either: `:create` or `:update`.
```ruby
class Invoice < ActiveRecord::Base
@@ -700,269 +908,56 @@ 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 it useful to express that a certain field corresponds to a set of choices:
+Displaying Validation Errors in Views
+-------------------------------------
-```ruby
-ActiveRecord::Base.class_eval do
- def self.validates_as_choice(attr_name, n, options={})
- validates attr_name, inclusion: { { in: 1..n }.merge!(options) }
- end
-end
-```
+Once you've created a model and added validations, if that model is created via
+a web form, you probably want to display an error message when one of the
+validations fail.
-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:
+Because every application handles this kind of thing differently, Rails does
+not include any view helpers to help you generate these messages directly.
+However, due to the rich number of methods Rails gives you to interact with
+validations in general, it's fairly easy to build your own. In addition, when
+generating a scaffold, Rails will put some ERB into the `_form.html.erb` that
+it generates that displays the full list of errors on that model.
-```ruby
-class Movie < ActiveRecord::Base
- validates_as_choice :rating, 5
-end
-```
-
-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 `ActiveModel::Errors` documentation for a list of all the available methods.
-
-### `errors`
-
-Returns an instance of the class `ActiveModel::Errors` containing all errors. Each key is the attribute name and the value is an array of strings with all errors.
+Assuming we have a model that's been saved in an instance variable named
+`@post`, it looks like this:
```ruby
-class Person < ActiveRecord::Base
- validates :name, presence: true, length: { 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 # => []
-```
-
-### `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.
+<% if @post.errors.any? %>
+ <div id="error_explanation">
+ <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
-```ruby
-class Person < ActiveRecord::Base
- validates :name, presence: true, length: { 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)"]
-```
-
-### `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.
-
-```ruby
-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
-
-```ruby
- 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 !@#%*()_-+="]
-```
-
-### `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 it and it will be used as an error message.
-
-```ruby
-class Person < ActiveRecord::Base
- def a_method_used_for_validation_purposes
- errors[:base] << "This person is invalid because ..."
- end
-end
-```
-
-### `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.
-
-```ruby
-class Person < ActiveRecord::Base
- validates :name, presence: true, length: { 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)"]
-```
-
-### `errors.size`
-
-The `size` method returns the total number of error messages for the object.
-
-```ruby
-class Person < ActiveRecord::Base
- validates :name, presence: true, length: { minimum: 3 }
-end
-
-person = Person.new
-person.valid? # => false
-person.errors.size # => 2
-
-person = Person.new(name: "Andrea", email: "andrea@example.com")
-person.valid? # => true
-person.errors.size # => 0
-```
-
-Displaying Validation Errors in the View
-----------------------------------------
-
-[DynamicForm](https://github.com/joelmoss/dynamic_form) provides helpers to display the error messages of your models in your view templates.
-
-You can install it as a gem by adding this line to your Gemfile:
-
-```ruby
-gem "dynamic_form"
-```
-
-Now you will have access to the two helper methods `error_messages` and `error_messages_for` in your view templates.
-
-### `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.
-
-```ruby
-class Product < ActiveRecord::Base
- validates :description, :value, presence: true
- validates :value, numericality: true, allow_nil: true
-end
-```
-
-```erb
-<%= form_for(@product) do |f| %>
- <%= f.error_messages %>
- <p>
- <%= f.label :description %><br />
- <%= f.text_field :description %>
- </p>
- <p>
- <%= f.label :value %><br />
- <%= f.text_field :value %>
- </p>
- <p>
- <%= f.submit "Create" %>
- </p>
+ <ul>
+ <% @post.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
<% end %>
```
-If you submit the form with empty fields, the result will be similar to the one shown below:
-
-![Error messages](images/error_messages.png)
+Furthermore, if you use the Rails form helpers to generate your forms, when
+a validation error occurs on a field, it will generate an extra `<div>` around
+the entry.
-NOTE: The appearance of the generated HTML will be different from the one shown, unless you have used scaffolding. See [Customizing the Error Messages CSS](#customizing-the-error-messages-css).
-
-You can also use the `error_messages_for` helper to display the error messages of a model assigned to a view template. It is very similar to the previous example and will achieve exactly the same result.
-
-```erb
-<%= 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, change the header text, change the message below the header, and specify the tag used for the header element. For example,
-
-```erb
-<%= f.error_messages header_message: "Invalid product!",
- message: "You'll need to fix the following fields:",
- header_tag: :h3 %>
+<div class="field_with_errors">
+ <input id="post_title" name="post[title]" size="30" type="text" value="">
+</div>
```
-results in:
-
-![Customized error messages](images/customized_error_messages.png)
+You can then style this div however you'd like. The default scaffold that
+Rails generates, for example, adds this CSS rule:
-If you pass `nil` in any of these options, the corresponding section of the `div` will be discarded.
-
-### Customizing the Error Messages CSS
-
-The selectors used to customize the style of error messages are:
-
-* `.field_with_errors` - Style for the form fields and labels with errors.
-* `#error_explanation` - Style for the `div` element with the error messages.
-* `#error_explanation h2` - Style for the header of the `div` element.
-* `#error_explanation p` - Style for the paragraph holding the message that appears right below the header of the `div` element.
-* `#error_explanation ul li` - Style for the list items with individual error messages.
-
-If scaffolding was used, file `app/assets/stylesheets/scaffolds.css.scss` will have been generated automatically. This file defines the red-based styles you saw in the examples above.
-
-The name of the class and the id can be changed with the `:class` and `:id` options, accepted by both helpers.
-
-### Customizing the Error Messages HTML
-
-By default, form fields with errors are displayed enclosed by a `div` element with the `field_with_errors` CSS class. However, it's possible to override that.
-
-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`.
-
-Below is a simple example where we change the Rails behavior to always display the error messages in front of each of the form fields in error. 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.
-
-```ruby
-ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
- if html_tag =~ /\<label/
- html_tag
- else
- errors = Array(instance.error_message).join(',')
- %(#{html_tag}<span class="validation-error">&nbsp;#{errors}</span>).html_safe
- end
-end
+```
+.field_with_errors {
+ padding: 2px;
+ background-color: red;
+ display: table;
+}
```
-The result looks like the following:
-
-![Validation error messages](images/validation_error_messages.png)
+This means that any field with an error ends up with a 2 pixel red border.
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index 43aef85e8d..829cbf2873 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -15,36 +15,25 @@ After reading this guide, you will know:
--------------------------------------------------------------------------------
-What are Migrations?
---------------------
+Migration Overview
+------------------
-Migrations are a convenient way for you to alter your database in a structured
-and organized manner. You could edit fragments of SQL by hand but you would then
-be responsible for telling other developers that they need to go and run them.
-You'd also have to keep track of which changes need to be run against the
-production machines next time you deploy.
+Migrations are a convenient way to alter your database schema over time in a
+consistent and easy way. They use a Ruby DSL so that you don't have to write
+SQL by hand, allowing your schema and changes to be database independent.
-Active Record tracks which migrations have already been run so all you have to
-do is update your source and run `rake db:migrate`. Active Record will work out
-which migrations should be run. Active Record will also update your
+You can think of each migration as being a new 'version' of the database. A
+schema starts off with nothing in it, and each migration modifies it to add or
+remove tables, columns, or entries. Active Record knows how to update your
+schema along this timeline, bringing it from whatever point it is in the
+history to the latest version. Active Record will also update your
`db/schema.rb` file to match the up-to-date structure of your database.
-Migrations also allow you to describe these transformations using Ruby. The
-great thing about this is that (like most of Active Record's functionality) it
-is database independent: you don't need to worry about the precise syntax of
-`CREATE TABLE` any more than you worry about variations on `SELECT *` (you can
-drop down to raw SQL for database specific features). For example, you could use
-SQLite3 in development, but MySQL in production.
-
-Anatomy of a Migration
-----------------------
-
-Before we dive into the details of a migration, here are a few examples of the
-sorts of things you can do:
+Here's an example of a migration:
```ruby
class CreateProducts < ActiveRecord::Migration
- def up
+ def change
create_table :products do |t|
t.string :name
t.text :description
@@ -52,102 +41,49 @@ class CreateProducts < ActiveRecord::Migration
t.timestamps
end
end
-
- def down
- drop_table :products
- end
end
```
-This migration adds a table called `products` with a string column called `name`
-and a text column called `description`. A primary key column called `id` will
-also be added, however since this is the default we do not need to explicitly specify it.
-The timestamp columns `created_at` and `updated_at` which Active Record
-populates automatically will also be added. Reversing this migration is as
-simple as dropping the table.
+This migration adds a table called `products` with a string column called
+`name` and a text column called `description`. A primary key column called `id`
+will also be added implicitly, as it's the default primary key for all Active
+Record models. The `timestamps` macro adds two columns, `created_at` and
+`updated_at`. These special columns are automatically managed by Active Record
+if they exist.
+
+Note that we define the change that we want to happen moving forward in time.
+Before this migration is run, there will be no table. After, the table will
+exist. Active Record knows how to reverse this migration as well: if we roll
+this migration back, it will remove the table.
+
+On databases that support transactions with statements that change the schema ,
+migrations are wrapped in a transaction. If the database does not support this
+then when a migration fails the parts of it that succeeded will not be rolled
+back. You will have to rollback the changes that were made by hand.
-Migrations are not limited to changing the schema. You can also use them to fix
-bad data in the database or populate new fields:
+If you wish for a migration to do something that Active Record doesn't know how
+to reverse, you can use `up` and `down` instead of `change`:
```ruby
-class AddReceiveNewsletterToUsers < ActiveRecord::Migration
+class ChangeProductsPrice < ActiveRecord::Migration
def up
- change_table :users do |t|
- t.boolean :receive_newsletter, default: false
+ change_table :products do |t|
+ t.string :price, null: false
end
- User.update_all receive_newsletter: true
end
-
+
def down
- remove_column :users, :receive_newsletter
- end
-end
-```
-
-NOTE: Some [caveats](#using-models-in-your-migrations) apply to using models in
-your migrations.
-
-This migration adds a `receive_newsletter` column to the `users` table. We want
-it to default to `false` for new users, but existing users are considered to
-have already opted in, so we use the User model to set the flag to `true` for
-existing users.
-
-### Using the change method
-
-Rails 3.1 and up makes migrations smarter by providing a `change` method.
-This method is preferred for writing constructive migrations (adding columns or
-tables). The migration knows how to migrate your database and reverse it when
-the migration is rolled back without the need to write a separate `down` method.
-
-```ruby
-class CreateProducts < ActiveRecord::Migration
- def change
- create_table :products do |t|
- t.string :name
- t.text :description
-
- t.timestamps
+ change_table :products do |t|
+ t.integer :price, null: false
end
end
end
```
-### Migrations are Classes
-
-A migration is a subclass of `ActiveRecord::Migration` that implements
-two methods: `up` (perform the required transformations) and `down` (revert
-them).
-
-Active Record provides methods that perform common data definition tasks in a
-database independent way (you'll read about them in detail later):
-
-* `add_column`
-* `add_reference`
-* `add_index`
-* `change_column`
-* `change_table`
-* `create_table`
-* `create_join_table`
-* `drop_table`
-* `remove_column`
-* `remove_index`
-* `rename_column`
-* `remove_reference`
-
-If you need to perform tasks specific to your database (e.g., create a
-[foreign key](#active-record-and-referential-integrity) constraint) then the
-`execute` method allows you to execute arbitrary SQL. A migration is just a
-regular Ruby class so you're not limited to these functions. For example, after
-adding a column you could write code to set the value of that column for
-existing records (if necessary using your models).
-
-On databases that support transactions with statements that change the schema
-(such as PostgreSQL or SQLite3), migrations are wrapped in a transaction. If the
-database does not support this (for example MySQL) then when a migration fails
-the parts of it that succeeded will not be rolled back. You will have to rollback
-the changes that were made by hand.
+Creating a Migration
+--------------------
-### What's in a Name
+### Creating a Standalone Migration
Migrations are stored as files in the `db/migrate` directory, one for each
migration class. The name of the file is of the form
@@ -157,119 +93,10 @@ of the migration. The name of the migration class (CamelCased version)
should match the latter part of the file name. For example
`20080906120000_create_products.rb` should define class `CreateProducts` and
`20080906120001_add_details_to_products.rb` should define
-`AddDetailsToProducts`. If you do feel the need to change the file name then you
-<em>have to</em> update the name of the class inside or Rails will complain
-about a missing class.
-
-Internally Rails only uses the migration's number (the timestamp) to identify
-them. Prior to Rails 2.1 the migration number started at 1 and was incremented
-each time a migration was generated. With multiple developers it was easy for
-these to clash requiring you to rollback migrations and renumber them. With
-Rails 2.1+ this is largely avoided by using the creation time of the migration
-to identify them. You can revert to the old numbering scheme by adding the
-following line to `config/application.rb`.
-
-```ruby
-config.active_record.timestamped_migrations = false
-```
-
-The combination of timestamps and recording which migrations have been run
-allows Rails to handle common situations that occur with multiple developers.
-
-For example, Alice adds migrations `20080906120000` and `20080906123000` and Bob
-adds `20080906124500` and runs it. Alice finishes her changes and checks in her
-migrations and Bob pulls down the latest changes. When Bob runs `rake db:migrate`,
-Rails knows that it has not run Alice's two migrations so it executes the `up` method for each migration.
-
-Of course this is no substitution for communication within the team. For
-example, if Alice's migration removed a table that Bob's migration assumed to
-exist, then trouble would certainly strike.
-
-### Changing Migrations
+`AddDetailsToProducts`.
-Occasionally you will make a mistake when writing a migration. If you have
-already run the migration then you cannot just edit the migration and run the
-migration again: Rails thinks it has already run the migration and so will do
-nothing when you run `rake db:migrate`. You must rollback the migration (for
-example with `rake db:rollback`), edit your migration and then run `rake db:migrate` to run the corrected version.
-
-In general, editing existing migrations is not a good idea. You will be creating
-extra work for yourself and your co-workers and cause major headaches if the
-existing version of the migration has already been run on production machines.
-Instead, you should write a new migration that performs the changes you require.
-Editing a freshly generated migration that has not yet been committed to source
-control (or, more generally, which has not been propagated beyond your
-development machine) is relatively harmless.
-
-### Supported Types
-
-Active Record supports the following database column types:
-
-* `:binary`
-* `:boolean`
-* `:date`
-* `:datetime`
-* `:decimal`
-* `:float`
-* `:integer`
-* `:primary_key`
-* `:string`
-* `:text`
-* `:time`
-* `:timestamp`
-
-These will be mapped onto an appropriate underlying database type. For example,
-with MySQL the type `:string` is mapped to `VARCHAR(255)`. You can create
-columns of types not supported by Active Record when using the non-sexy syntax such as
-
-```ruby
-create_table :products do |t|
- t.column :name, 'polygon', null: false
-end
-```
-
-This may however hinder portability to other databases.
-
-Creating a Migration
---------------------
-
-### Creating a Model
-
-The model and scaffold generators will create migrations appropriate for adding
-a new model. This migration will already contain instructions for creating the
-relevant table. If you tell Rails what columns you want, then statements for
-adding these columns will also be created. For example, running
-
-```bash
-$ rails generate model Product name:string description:text
-```
-
-TIP: All lines starting with a dollar sign `$` are intended to be run on the command line.
-
-will create a migration that looks like this
-
-```ruby
-class CreateProducts < ActiveRecord::Migration
- def change
- create_table :products do |t|
- t.string :name
- t.text :description
-
- t.timestamps
- end
- end
-end
-```
-
-You can append as many column name/type pairs as you want. By default, the
-generated migration will include `t.timestamps` (which creates the
-`updated_at` and `created_at` columns that are automatically populated
-by Active Record).
-
-### Creating a Standalone Migration
-
-If you are creating migrations for other purposes (e.g., to add a column
-to an existing table) then you can also use the migration generator:
+Of course, calculating timestamps is no fun, so Active Record provides a
+generator to handle making it for you:
```bash
$ rails generate migration AddPartNumberToProducts
@@ -344,10 +171,11 @@ or remove from it as you see fit by editing the
`db/migrate/YYYYMMDDHHMMSS_add_details_to_products.rb` file.
NOTE: The generated migration file for destructive migrations will still be
-old-style using the `up` and `down` methods. This is because Rails needs to know
-the original data types defined when you made the original changes.
+old-style using the `up` and `down` methods. This is because Rails needs to
+know the original data types defined when you made the original changes.
-Also, the generator accepts column type as `references`(also available as `belongs_to`). For instance
+Also, the generator accepts column type as `references`(also available as
+`belongs_to`). For instance
```bash
$ rails generate migration AddUserRefToProducts user:references
@@ -363,12 +191,40 @@ class AddUserRefToProducts < ActiveRecord::Migration
end
```
-This migration will create a user_id column and appropriate index.
+This migration will create a `user_id` column and appropriate index.
+
+### Model Generators
+
+The model and scaffold generators will create migrations appropriate for adding
+a new model. This migration will already contain instructions for creating the
+relevant table. If you tell Rails what columns you want, then statements for
+adding these columns will also be created. For example, running
+
+```bash
+$ rails generate model Product name:string description:text
+```
+
+will create a migration that looks like this
+
+```ruby
+class CreateProducts < ActiveRecord::Migration
+ def change
+ create_table :products do |t|
+ t.string :name
+ t.text :description
+
+ t.timestamps
+ end
+ end
+end
+```
+
+You can append as many column name/type pairs as you want.
### Supported Type Modifiers
-You can also specify some options just after the field type between curly braces. You can use the
-following modifiers:
+You can also specify some options just after the field type between curly
+braces. You can use the following modifiers:
* `limit` Sets the maximum size of the `string/text/binary/integer` fields
* `precision` Defines the precision for the `decimal` fields
@@ -400,8 +256,9 @@ get to work!
### Creating a Table
-Migration method `create_table` will be one of your workhorses. A typical use
-would be
+The `create_table` method is one of the most fundamental, but most of the time,
+will be generated for you from using a model or scaffold generator. A typical
+use would be
```ruby
create_table :products do |t|
@@ -412,31 +269,11 @@ end
which creates a `products` table with a column called `name` (and as discussed
below, an implicit `id` column).
-The object yielded to the block allows you to create columns on the table. There
-are two ways of doing it. The first (traditional) form looks like
-
-```ruby
-create_table :products do |t|
- t.column :name, :string, null: false
-end
-```
-
-The second form, the so called "sexy" migration, drops the somewhat redundant
-`column` method. Instead, the `string`, `integer`, etc. methods create a column
-of that type. Subsequent parameters are the same.
-
-```ruby
-create_table :products do |t|
- t.string :name, null: false
-end
-```
-
By default, `create_table` will create a primary key called `id`. You can change
the name of the primary key with the `:primary_key` option (don't forget to
-update the corresponding model) or, if you don't want a primary key at all (for
-example for a HABTM join table), you can pass the option `id: false`. If you
-need to pass database specific options you can place an SQL fragment in the
-`:options` option. For example,
+update the corresponding model) or, if you don't want a primary key at all, you
+can pass the option `id: false`. If you need to pass database specific options
+you can place an SQL fragment in the `:options` option. For example,
```ruby
create_table :products, options: "ENGINE=BLACKHOLE" do |t|
@@ -456,10 +293,12 @@ would be
create_join_table :products, :categories
```
-which creates a `categories_products` table with two columns called `category_id` and `product_id`.
-These columns have the option `:null` set to `false` by default.
+which creates a `categories_products` table with two columns called
+`category_id` and `product_id`. These columns have the option `:null` set to
+`false` by default.
-You can pass the option `:table_name` with you want to customize the table name. For example,
+You can pass the option `:table_name` with you want to customize the table
+name. For example,
```ruby
create_join_table :products, :categories, table_name: :categorization
@@ -467,20 +306,21 @@ create_join_table :products, :categories, table_name: :categorization
will create a `categorization` table.
-By default, `create_join_table` will create two columns with no options, but you can specify these
-options using the `:column_options` option. For example,
+By default, `create_join_table` will create two columns with no options, but
+you can specify these options using the `:column_options` option. For example,
```ruby
create_join_table :products, :categories, column_options: {null: true}
```
-will create the `product_id` and `category_id` with the `:null` option as `true`.
+will create the `product_id` and `category_id` with the `:null` option as
+`true`.
### Changing Tables
A close cousin of `create_table` is `change_table`, used for changing existing
-tables. It is used in a similar fashion to `create_table` but the object yielded
-to the block knows more tricks. For example
+tables. It is used in a similar fashion to `create_table` but the object
+yielded to the block knows more tricks. For example
```ruby
change_table :products do |t|
@@ -494,67 +334,15 @@ end
removes the `description` and `name` columns, creates a `part_number` string
column and adds an index on it. Finally it renames the `upccode` column.
-### Special Helpers
-
-Active Record provides some shortcuts for common functionality. It is for
-example very common to add both the `created_at` and `updated_at` columns and so
-there is a method that does exactly that:
-
-```ruby
-create_table :products do |t|
- t.timestamps
-end
-```
-
-will create a new products table with those two columns (plus the `id` column)
-whereas
-
-```ruby
-change_table :products do |t|
- t.timestamps
-end
-```
-adds those columns to an existing table.
-
-Another helper is called `references` (also available as `belongs_to`). In its
-simplest form it just adds some readability.
-
-```ruby
-create_table :products do |t|
- t.references :category
-end
-```
-
-will create a `category_id` column of the appropriate type. Note that you pass
-the model name, not the column name. Active Record adds the `_id` for you. If
-you have polymorphic `belongs_to` associations then `references` will add both
-of the columns required:
+### When Helpers Aren't Enough
-```ruby
-create_table :products do |t|
- t.references :attachment, polymorphic: {default: 'Photo'}
-end
-```
-
-will add an `attachment_id` column and a string `attachment_type` column with
-a default value of 'Photo'. `references` also allows you to define an
-index directly, instead of using `add_index` after the `create_table` call:
+If the helpers provided by Active Record aren't enough you can use the `execute`
+method to execute arbitrary SQL:
```ruby
-create_table :products do |t|
- t.references :category, index: true
-end
+Products.connection.execute('UPDATE `products` SET `price`=`free` WHERE 1')
```
-will create an index identical to calling `add_index :products, :category_id`.
-
-NOTE: The `references` helper does not actually create foreign key constraints
-for you. You will need to use `execute` or a plugin that adds [foreign key
-support](#active-record-and-referential-integrity).
-
-If the helpers provided by Active Record aren't enough you can use the `execute`
-method to execute arbitrary SQL.
-
For more details and examples of individual methods, check the API documentation.
In particular the documentation for
[`ActiveRecord::ConnectionAdapters::SchemaStatements`](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html)
@@ -567,9 +355,10 @@ and
### Using the `change` Method
-The `change` method removes the need to write both `up` and `down` methods in
-those cases that Rails knows how to revert the changes automatically. Currently,
-the `change` method supports only these migration definitions:
+The `change` method is the primary way of writing migrations. It works for the
+majority of cases, where Active Record knows how to reverse the migration
+automatically. Currently, the `change` method supports only these migration
+definitions:
* `add_column`
* `add_index`
@@ -585,12 +374,13 @@ If you're going to need to use any other methods, you'll have to write the
### Using the `up`/`down` Methods
-The `down` method of your migration should revert the transformations done by
-the `up` method. In other words, the database schema should be unchanged if you
-do an `up` followed by a `down`. For example, if you create a table in the `up`
-method, you should drop it in the `down` method. It is wise to reverse the
-transformations in precisely the reverse order they were made in the `up`
-method. For example,
+The `up` method should describe the transformation you'd like to make to your
+schema, and the `down` method of your migration should revert the
+transformations done by the `up` method. In other words, the database schema
+should be unchanged if you do an `up` followed by a `down`. For example, if you
+create a table in the `up` method, you should drop it in the `down` method. It
+is wise to reverse the transformations in precisely the reverse order they were
+made in the `up` method. For example,
```ruby
class ExampleMigration < ActiveRecord::Migration
@@ -598,6 +388,7 @@ class ExampleMigration < ActiveRecord::Migration
create_table :products do |t|
t.references :category
end
+
#add a foreign key
execute <<-SQL
ALTER TABLE products
@@ -605,6 +396,7 @@ class ExampleMigration < ActiveRecord::Migration
FOREIGN KEY (category_id)
REFERENCES categories(id)
SQL
+
add_column :users, :home_page_url, :string
rename_column :users, :email, :email_address
end
@@ -612,10 +404,12 @@ class ExampleMigration < ActiveRecord::Migration
def down
rename_column :users, :email_address, :email
remove_column :users, :home_page_url
+
execute <<-SQL
ALTER TABLE products
DROP FOREIGN KEY fk_products_categories
SQL
+
drop_table :products
end
end
@@ -630,10 +424,9 @@ can't be done.
Running Migrations
------------------
-Rails provides a set of rake tasks to work with migrations which boil down to
-running certain sets of migrations.
+Rails provides a set of Rake tasks to run certain sets of migrations.
-The very first migration related rake task you will use will probably be
+The very first migration related Rake task you will use will probably be
`rake db:migrate`. In its most basic form it just runs the `up` or `change`
method for all the migrations that have not yet been run. If there are
no such migrations, it exits. It will run these migrations in order based
@@ -693,9 +486,10 @@ version to migrate to.
The `rake db:reset` task will drop the database, recreate it and load the
current schema into it.
-NOTE: This is not the same as running all the migrations. It will only use the contents
-of the current `schema.rb` file. If a migration can't be rolled back, `rake db:reset`
-may not help you. To find out more about dumping the schema see [schema.rb](#schema-dumping-and-you).
+NOTE: This is not the same as running all the migrations. It will only use the
+contents of the current schema.rb file. If a migration can't be rolled back,
+'rake db:reset' may not help you. To find out more about dumping the schema see
+'[schema dumping and you](#schema-dumping-and-you).'
### Running Specific Migrations
@@ -708,13 +502,16 @@ example,
$ rake db:migrate:up VERSION=20080906120000
```
-will run the `up` method from the 20080906120000 migration. This task will first
-check whether the migration is already performed and will do nothing if Active Record believes
-that it has already been run.
+will run the `up` method from the 20080906120000 migration. This task will
+first check whether the migration is already performed and will do nothing if
+Active Record believes that it has already been run.
### Running Migrations in Different Environments
-By default running `rake db:migrate` will run in the `development` environment. To run migrations against another environment you can specify it using the `RAILS_ENV` environment variable while running the command. For example to run migrations against the `test` environment you could run:
+By default running `rake db:migrate` will run in the `development` environment.
+To run migrations against another environment you can specify it using the
+`RAILS_ENV` environment variable while running the command. For example to run
+migrations against the `test` environment you could run:
```bash
$ rake db:migrate RAILS_ENV=test
@@ -752,9 +549,12 @@ class CreateProducts < ActiveRecord::Migration
t.timestamps
end
end
+
say "Created a table"
+
suppress_messages {add_index :products, :name}
say "and an index!", true
+
say_with_time 'Waiting for a while' do
sleep 10
250
@@ -778,11 +578,29 @@ generates the following output
If you want Active Record to not output anything, then running `rake db:migrate
VERBOSE=false` will suppress all output.
+Changing Existing Migrations
+----------------------------
+
+Occasionally you will make a mistake when writing a migration. If you have
+already run the migration then you cannot just edit the migration and run the
+migration again: Rails thinks it has already run the migration and so will do
+nothing when you run `rake db:migrate`. You must rollback the migration (for
+example with `rake db:rollback`), edit your migration and then run `rake
+db:migrate` to run the corrected version.
+
+In general, editing existing migrations is not a good idea. You will be
+creating extra work for yourself and your co-workers and cause major headaches
+if the existing version of the migration has already been run on production
+machines. Instead, you should write a new migration that performs the changes
+you require. Editing a freshly generated migration that has not yet been
+committed to source control (or, more generally, which has not been propagated
+beyond your development machine) is relatively harmless.
+
Using Models in Your Migrations
-------------------------------
-When creating or updating data in a migration it is often tempting to use one of
-your models. After all, they exist to provide easy access to the underlying
+When creating or updating data in a migration it is often tempting to use one
+of your models. After all, they exist to provide easy access to the underlying
data. This can be done, but some caution should be observed.
For example, problems occur when the model uses database columns which are (1)
@@ -795,7 +613,7 @@ which contains a `Product` model:
Bob goes on vacation.
Alice creates a migration for the `products` table which adds a new column and
-initializes it. She also adds a validation to the `Product` model for the new
+initializes it. She also adds a validation to the `Product` model for the new
column.
```ruby
@@ -844,8 +662,8 @@ Both migrations work for Alice.
Bob comes back from vacation and:
-* Updates the source - which contains both migrations and the latest version of
- the Product model.
+* Updates the source - which contains both migrations and the latest version
+ of the Product model.
* Runs outstanding migrations with `rake db:migrate`, which
includes the one that updates the `Product` model.
@@ -860,10 +678,10 @@ An error has occurred, this and all later migrations canceled:
undefined method `fuzz' for #<Product:0x000001049b14a0>
```
-A fix for this is to create a local model within the migration. This keeps Rails
-from running the validations, so that the migrations run to completion.
+A fix for this is to create a local model within the migration. This keeps
+Rails from running the validations, so that the migrations run to completion.
-When using a faux model, it's a good idea to call
+When using a local model, it's a good idea to call
`Product.reset_column_information` to refresh the `ActiveRecord` cache for the
`Product` model prior to updating data in the database.
@@ -902,20 +720,20 @@ end
There are other ways in which the above example could have gone badly.
For example, imagine that Alice creates a migration that selectively
-updates the +description+ field on certain products. She runs the
+updates the `description` field on certain products. She runs the
migration, commits the code, and then begins working on the next feature,
-which is to add a new column +fuzz+ to the products table.
+which is to add a new column `fuzz` to the products table.
She creates two migrations for this new feature, one which adds the new
-column, and a second which selectively updates the +fuzz+ column based on
+column, and a second which selectively updates the `fuzz` column based on
other product attributes.
These migrations run just fine, but when Bob comes back from his vacation
and calls `rake db:migrate` to run all the outstanding migrations, he gets a
-subtle bug: The descriptions have defaults, and the +fuzz+ column is present,
-but +fuzz+ is nil on all products.
+subtle bug: The descriptions have defaults, and the `fuzz` column is present,
+but `fuzz` is nil on all products.
-The solution is again to use +Product.reset_column_information+ before
+The solution is again to use `Product.reset_column_information` before
referencing the Product model in a migration, ensuring the Active Record's
knowledge of the table structure is current before manipulating data in those
records.
@@ -948,12 +766,13 @@ you desire that functionality.
### Types of Schema Dumps
-There are two ways to dump the schema. This is set in `config/application.rb` by
-the `config.active_record.schema_format` setting, which may be either `:sql` or
-`:ruby`.
+There are two ways to dump the schema. This is set in `config/application.rb`
+by the `config.active_record.schema_format` setting, which may be either `:sql`
+or `:ruby`.
If `:ruby` is selected then the schema is stored in `db/schema.rb`. If you look
-at this file you'll find that it looks an awful lot like one very big migration:
+at this file you'll find that it looks an awful lot like one very big
+migration:
```ruby
ActiveRecord::Schema.define(version: 20080906171750) do
@@ -976,8 +795,8 @@ end
In many ways this is exactly what it is. This file is created by inspecting the
database and expressing its structure using `create_table`, `add_index`, and so
on. Because this is database-independent, it could be loaded into any database
-that Active Record supports. This could be very useful if you were to distribute
-an application that is able to run against multiple databases.
+that Active Record supports. This could be very useful if you were to
+distribute an application that is able to run against multiple databases.
There is however a trade-off: `db/schema.rb` cannot express database specific
items such as foreign key constraints, triggers, or stored procedures. While in
@@ -985,11 +804,11 @@ a migration you can execute custom SQL statements, the schema dumper cannot
reconstitute those statements from the database. If you are using features like
this, then you should set the schema format to `:sql`.
-Instead of using Active Record's schema dumper, the database's structure will be
-dumped using a tool specific to the database (via the `db:structure:dump` Rake task)
-into `db/structure.sql`. For example, for the PostgreSQL RDBMS, the
-`pg_dump` utility is used. For MySQL, this file will contain the output of
-`SHOW CREATE TABLE` for the various tables.
+Instead of using Active Record's schema dumper, the database's structure will
+be dumped using a tool specific to the database (via the `db:structure:dump`
+Rake task) into `db/structure.sql`. For example, for PostgreSQL, the `pg_dump`
+utility is used. For MySQL, this file will contain the output of `SHOW CREATE
+TABLE` for the various tables.
Loading these schemas is simply a question of executing the SQL statements they
contain. By definition, this will create a perfect copy of the database's
@@ -1010,14 +829,47 @@ which push some of that intelligence back into the database, are not heavily
used.
Validations such as `validates :foreign_key, uniqueness: true` are one way in
-which models can enforce data integrity. The `:dependent` option on associations
-allows models to automatically destroy child objects when the parent is
-destroyed. Like anything which operates at the application level, these cannot
-guarantee referential integrity and so some people augment them with foreign key
-constraints in the database.
-
-Although Active Record does not provide any tools for working directly with such
-features, the `execute` method can be used to execute arbitrary SQL. You could
-also use some plugin like [foreigner](https://github.com/matthuhiggins/foreigner)
-which add foreign key support to Active Record (including support for dumping
-foreign keys in `db/schema.rb`).
+which models can enforce data integrity. The `:dependent` option on
+associations allows models to automatically destroy child objects when the
+parent is destroyed. Like anything which operates at the application level,
+these cannot guarantee referential integrity and so some people augment them
+with foreign key constraints in the database.
+
+Although Active Record does not provide any tools for working directly with
+such features, the `execute` method can be used to execute arbitrary SQL. You
+could also use some plugin like
+[foreigner](https://github.com/matthuhiggins/foreigner) which add foreign key
+support to Active Record (including support for dumping foreign keys in
+`db/schema.rb`).
+
+Migrations and Seed Data
+------------------------
+
+Some people use migrations to add data to the database:
+
+```ruby
+class AddInitialProducts < ActiveRecord::Migration
+ def up
+ 5.times do |i|
+ Product.create(name: "Product ##{i}", description: "A product.")
+ end
+ end
+
+ def down
+ Product.delete_all
+ end
+end
+```
+
+However, Rails has a 'seeds' feature that should be used for seeding a database
+with initial data. It's a really simple feature: just fill up `db/seeds.rb`
+with some Ruby code, and run `rake db:seed`:
+
+```ruby
+5.times do |i|
+ Product.create(name: "Product ##{i}", description: "A product.")
+end
+```
+
+This is generally a much cleaner way to set up the database of a blank
+application.
diff --git a/guides/source/performance_testing.md b/guides/source/performance_testing.md
index b84c5d1732..a07f64ec29 100644
--- a/guides/source/performance_testing.md
+++ b/guides/source/performance_testing.md
@@ -559,9 +559,9 @@ Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]
Default: 1
-o, --output PATH Directory to use when writing the results.
Default: tmp/performance
- --metrics a,b,c Metrics to use.
+ -m, --metrics a,b,c Metrics to use.
Default: process_time,memory,objects
- -m, --formats x,y,z Formats to output to.
+ -f, --formats x,y,z Formats to output to.
Default: flat,graph_html,call_tree
```
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 7a68cf0a2e..c3da3094dc 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* Add `db` to list of folders included by `rake notes` and `rake notes:custom`. *Antonio Cangiano*
+
* Engines with a dummy app include the rake tasks of dependencies in the app namespace.
Fix #8229
diff --git a/railties/lib/rails/commands/profiler.rb b/railties/lib/rails/commands/profiler.rb
index 3f6966b4f0..315bcccf61 100644
--- a/railties/lib/rails/commands/profiler.rb
+++ b/railties/lib/rails/commands/profiler.rb
@@ -8,7 +8,7 @@ def options
defaults = ActiveSupport::Testing::Performance::DEFAULTS
OptionParser.new do |opt|
- opt.banner = "Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]"
+ opt.banner = "Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]"
opt.on('-r', '--runs N', Numeric, 'Number of runs.', "Default: #{defaults[:runs]}") { |r| options[:runs] = r }
opt.on('-o', '--output PATH', String, 'Directory to use when writing the results.', "Default: #{defaults[:output]}") { |o| options[:output] = o }
opt.on('-m', '--metrics a,b,c', Array, 'Metrics to use.', "Default: #{defaults[:metrics].join(",")}") { |m| options[:metrics] = m.map(&:to_sym) }
diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt
index 7342bffd9d..6645f40afa 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt
@@ -13,6 +13,8 @@
<% unless options[:skip_javascript] -%>
//= require <%= options[:javascript] %>
//= require <%= options[:javascript] %>_ujs
-//= require turbolinks
<% end -%>
//= require_tree .
+<% unless options[:skip_javascript] -%>
+//= require turbolinks
+<% end -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
index e0539aa8bb..d87c7b7268 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt
@@ -2,8 +2,8 @@
<html>
<head>
<title><%= camelized %></title>
- <%%= stylesheet_link_tag "application", media: "all" %>
- <%%= javascript_include_tag "application" %>
+ <%%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
+ <%%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%%= csrf_meta_tags %>
</head>
<body>
diff --git a/railties/lib/rails/generators/rails/app/templates/gitignore b/railties/lib/rails/generators/rails/app/templates/gitignore
index 8910bf5a06..52abb32479 100644
--- a/railties/lib/rails/generators/rails/app/templates/gitignore
+++ b/railties/lib/rails/generators/rails/app/templates/gitignore
@@ -2,7 +2,7 @@
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
-# git config --global core.excludesfile ~/.gitignore_global
+# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config
/.bundle
diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb
index 3474b02af4..ac806e8006 100644
--- a/railties/lib/rails/source_annotation_extractor.rb
+++ b/railties/lib/rails/source_annotation_extractor.rb
@@ -15,7 +15,7 @@
class SourceAnnotationExtractor
class Annotation < Struct.new(:line, :tag, :text)
def self.directories
- @@directories ||= %w(app config lib script test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',')
+ @@directories ||= %w(app config db lib script test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',')
end
# Returns a representation of the annotation that looks like this:
diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb
index 7a227098ba..744bb93671 100644
--- a/railties/test/application/rake/notes_test.rb
+++ b/railties/test/application/rake/notes_test.rb
@@ -60,6 +60,7 @@ module ApplicationTests
test 'notes finds notes in default directories' do
app_file "app/controllers/some_controller.rb", "# TODO: note in app directory"
app_file "config/initializers/some_initializer.rb", "# TODO: note in config directory"
+ app_file "db/some_seeds.rb", "# TODO: note in db directory"
app_file "lib/some_file.rb", "# TODO: note in lib directory"
app_file "script/run_something.rb", "# TODO: note in script directory"
app_file "test/some_test.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in test directory"
@@ -80,12 +81,13 @@ module ApplicationTests
assert_match(/note in app directory/, output)
assert_match(/note in config directory/, output)
+ assert_match(/note in db directory/, output)
assert_match(/note in lib directory/, output)
assert_match(/note in script directory/, output)
assert_match(/note in test directory/, output)
assert_no_match(/note in some_other directory/, output)
- assert_equal 5, lines.size
+ assert_equal 6, lines.size
lines.each do |line_number|
assert_equal 4, line_number.size
@@ -96,6 +98,7 @@ module ApplicationTests
test 'notes finds notes in custom directories' do
app_file "app/controllers/some_controller.rb", "# TODO: note in app directory"
app_file "config/initializers/some_initializer.rb", "# TODO: note in config directory"
+ app_file "db/some_seeds.rb", "# TODO: note in db directory"
app_file "lib/some_file.rb", "# TODO: note in lib directory"
app_file "script/run_something.rb", "# TODO: note in script directory"
app_file "test/some_test.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in test directory"
@@ -116,13 +119,14 @@ module ApplicationTests
assert_match(/note in app directory/, output)
assert_match(/note in config directory/, output)
+ assert_match(/note in db directory/, output)
assert_match(/note in lib directory/, output)
assert_match(/note in script directory/, output)
assert_match(/note in test directory/, output)
assert_match(/note in some_other directory/, output)
- assert_equal 6, lines.size
+ assert_equal 7, lines.size
lines.each do |line_number|
assert_equal 4, line_number.size