diff options
25 files changed, 470 insertions, 314 deletions
diff --git a/.gitignore b/.gitignore index bc96284375..c3cb009140 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ debug.log .Gemfile /.bundle /.ruby-version -/Gemfile.lock pkg /dist /doc/rdoc diff --git a/.travis.yml b/.travis.yml index b38cb0032b..3130ee1b32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ sudo: false script: 'ci/travis.rb' before_install: - gem install bundler + - "rm ${BUNDLE_GEMFILE}.lock" before_script: - bundle update cache: bundler diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..d48bfc31b1 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,281 @@ +GIT + remote: git://github.com/bkeepers/qu.git + revision: d098e2657c92e89a6413bebd9c033930759c061f + branch: master + specs: + qu (0.2.0) + qu-rails (0.2.0) + qu (= 0.2.0) + railties (>= 3.2, < 5) + qu-redis (0.2.0) + qu (= 0.2.0) + redis-namespace + +GIT + remote: git://github.com/rails/arel.git + revision: aac9da257f291ad8d2d4f914528881c240848bb2 + branch: master + specs: + arel (7.0.0.alpha) + +GIT + remote: git://github.com/rails/jquery-rails.git + revision: 272abdd319bb3381b23182b928b25320590096b0 + branch: master + specs: + jquery-rails (4.0.3) + rails-dom-testing (~> 1.0) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + +PATH + remote: . + specs: + actionmailer (5.0.0.alpha) + actionpack (= 5.0.0.alpha) + actionview (= 5.0.0.alpha) + activejob (= 5.0.0.alpha) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (5.0.0.alpha) + actionview (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + rack (~> 1.6) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.1) + actionview (5.0.0.alpha) + activesupport (= 5.0.0.alpha) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.1) + activejob (5.0.0.alpha) + activesupport (= 5.0.0.alpha) + globalid (>= 0.3.0) + activemodel (5.0.0.alpha) + activesupport (= 5.0.0.alpha) + builder (~> 3.1) + activerecord (5.0.0.alpha) + activemodel (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + arel (= 7.0.0.alpha) + activesupport (5.0.0.alpha) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + rails (5.0.0.alpha) + actionmailer (= 5.0.0.alpha) + actionpack (= 5.0.0.alpha) + actionview (= 5.0.0.alpha) + activejob (= 5.0.0.alpha) + activemodel (= 5.0.0.alpha) + activerecord (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + bundler (>= 1.3.0, < 2.0) + railties (= 5.0.0.alpha) + sprockets-rails + railties (5.0.0.alpha) + actionpack (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + +GEM + remote: https://rubygems.org/ + specs: + amq-protocol (1.9.2) + backburner (0.4.6) + beaneater (~> 0.3.1) + dante (~> 0.1.5) + bcrypt (3.1.10) + beaneater (0.3.3) + benchmark-ips (2.1.1) + builder (3.2.2) + bunny (1.1.9) + amq-protocol (>= 1.9.2) + celluloid (0.16.0) + timers (~> 4.0.0) + coffee-rails (4.1.0) + coffee-script (>= 2.2.0) + railties (>= 4.0.0, < 5.0) + coffee-script (2.3.0) + coffee-script-source + execjs + coffee-script-source (1.9.0) + connection_pool (2.1.1) + dalli (2.7.2) + dante (0.1.5) + delayed_job (4.0.6) + activesupport (>= 3.0, < 5.0) + erubis (2.7.0) + execjs (2.3.0) + globalid (0.3.3) + activesupport (>= 4.1.0) + hike (1.2.3) + hitimes (1.2.2) + i18n (0.7.0) + json (1.8.2) + kindlerb (0.1.1) + mustache + nokogiri + loofah (2.0.1) + nokogiri (>= 1.5.9) + mail (2.6.3) + mime-types (>= 1.16, < 3) + metaclass (0.0.4) + mime-types (2.4.3) + mini_portile (0.6.2) + minitest (5.3.3) + mocha (0.14.0) + metaclass (~> 0.0.1) + mono_logger (1.1.0) + multi_json (1.10.1) + mustache (1.0.0) + mysql (2.9.1) + mysql2 (0.3.18) + nokogiri (1.6.6.2) + mini_portile (~> 0.6.0) + pg (0.18.1) + psych (2.0.13) + que (0.9.2) + queue_classic (3.1.0) + pg (>= 0.17, < 0.19) + racc (1.4.12) + rack (1.6.0) + rack-cache (1.2) + rack (>= 0.4) + rack-protection (1.5.3) + rack + rack-test (0.6.3) + rack (>= 1.0) + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.5) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.1) + loofah (~> 2.0) + rake (10.4.2) + rdoc (4.2.0) + redcarpet (3.2.2) + redis (3.2.1) + redis-namespace (1.5.1) + redis (~> 3.0, >= 3.0.4) + resque (1.25.2) + mono_logger (~> 1.0) + multi_json (~> 1.0) + redis-namespace (~> 1.3) + sinatra (>= 0.9.2) + vegas (~> 0.1.2) + resque-scheduler (4.0.0) + mono_logger (~> 1.0) + redis (~> 3.0) + resque (~> 1.25) + rufus-scheduler (~> 3.0) + ruby-prof (0.11.3) + rufus-scheduler (3.0.9) + tzinfo + sdoc (0.4.1) + json (~> 1.7, >= 1.7.7) + rdoc (~> 4.0) + sequel (4.19.0) + serverengine (1.5.10) + sigdump (~> 0.2.2) + sidekiq (3.3.2) + celluloid (>= 0.16.0) + connection_pool (>= 2.1.1) + json + redis (>= 3.0.6) + redis-namespace (>= 1.3.1) + sigdump (0.2.2) + sinatra (1.4.5) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (~> 1.3, >= 1.3.4) + sneakers (0.1.1.pre) + bunny (~> 1.1.3) + serverengine + thor + thread + sprockets (2.12.3) + hike (~> 1.2) + multi_json (~> 1.0) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + sprockets-rails (2.2.4) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (>= 2.8, < 4.0) + sqlite3 (1.3.10) + stackprof (0.2.7) + sucker_punch (1.3.2) + celluloid (~> 0.16.0) + thor (0.19.1) + thread (0.1.5) + thread_safe (0.3.4) + tilt (1.4.1) + timers (4.0.1) + hitimes + turbolinks (2.5.3) + coffee-rails + tzinfo (1.2.2) + thread_safe (~> 0.1) + uglifier (2.7.0) + execjs (>= 0.3.0) + json (>= 1.8.0) + vegas (0.1.11) + rack (>= 1.0.0) + w3c_validators (1.2) + json + nokogiri + +PLATFORMS + ruby + +DEPENDENCIES + activerecord-jdbcmysql-adapter (>= 1.3.0) + activerecord-jdbcpostgresql-adapter (>= 1.3.0) + activerecord-jdbcsqlite3-adapter (>= 1.3.0) + arel! + backburner + bcrypt (~> 3.1.7) + benchmark-ips + coffee-rails (~> 4.1.0) + dalli (>= 2.2.1) + delayed_job + jquery-rails! + json + kindlerb (= 0.1.1) + minitest (< 5.3.4) + mocha (~> 0.14) + mysql (>= 2.9.0) + mysql2 (>= 0.3.13) + nokogiri (>= 1.4.5) + pg (>= 0.18.0) + psych (~> 2.0) + qu-rails! + qu-redis + que + queue_classic + racc (>= 1.4.6) + rack-cache (~> 1.2) + rails! + rake (>= 10.3) + redcarpet (~> 3.2.2) + resque + resque-scheduler + ruby-prof (~> 0.11.2) + sdoc (~> 0.4.0) + sequel + sidekiq + sneakers (= 0.1.1.pre) + sqlite3 (~> 1.3.6) + stackprof + sucker_punch + turbolinks + uglifier (>= 1.3.0) + w3c_validators diff --git a/actionmailer/lib/rails/generators/mailer/USAGE b/actionmailer/lib/rails/generators/mailer/USAGE index d9d9d064d8..2b0a078109 100644 --- a/actionmailer/lib/rails/generators/mailer/USAGE +++ b/actionmailer/lib/rails/generators/mailer/USAGE @@ -12,6 +12,6 @@ Example: creates a Notifications mailer class, views, and test: Mailer: app/mailers/notifications_mailer.rb - Views: app/views/notifications/signup.text.erb [...] - Test: test/mailers/notifications_test.rb + Views: app/views/notifications_mailer/signup.text.erb [...] + Test: test/mailers/notifications_mailer_test.rb diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 268f037bfe..055d4b4f5b 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,8 @@ +* Non-string authenticity tokens do not raise NoMethodError when decoding + the masked token. + + *Ville Lautanala* + * Add http_cache_forever to Action Controller, so we can cache a response that never gets expired. *arthurnn* diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 7facbe79aa..367b736035 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -275,7 +275,9 @@ module ActionController #:nodoc: # session token. Essentially the inverse of # +masked_authenticity_token+. def valid_authenticity_token?(session, encoded_masked_token) - return false if encoded_masked_token.nil? || encoded_masked_token.empty? + if encoded_masked_token.nil? || encoded_masked_token.empty? || !encoded_masked_token.is_a?(String) + return false + end begin masked_token = Base64.strict_decode64(encoded_masked_token) diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 88155bb404..8887f291cf 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -374,6 +374,13 @@ module RequestForgeryProtectionTests end end + def test_should_not_raise_error_if_token_is_not_a_string + @controller.unstub(:valid_authenticity_token?) + assert_blocked do + patch :index, params: { custom_authenticity_token: { foo: 'bar' } } + end + end + def assert_blocked session[:something_like_user_id] = 1 yield diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 534124d208..5557285ef5 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +* Extracted `ActionView::Helpers::RecordTagHelper` to external gem + (`record_tag_helper`) and added removal notices. + + *Todd Bealmear* + * Allow to pass a string value to `size` option in `image_tag` and `video_tag`. This makes the behavior more consistent with `width` or `height` options. diff --git a/actionview/lib/action_view/base.rb b/actionview/lib/action_view/base.rb index 1feafc1094..43124bb904 100644 --- a/actionview/lib/action_view/base.rb +++ b/actionview/lib/action_view/base.rb @@ -70,6 +70,14 @@ module ActionView #:nodoc: # Headline: <%= headline %> # First name: <%= person.first_name %> # + # The local variables passed to sub templates can be accessed as a hash using the <tt>local_assigns</tt> hash. This lets you access the + # variables as: + # + # Headline: <%= local_assigns[:headline] %> + # + # This is useful in cases where you aren't sure if the local variable has been assigned. Alternately, you could also use + # <tt>defined? headline</tt> to first check if the variable has been assigned before using it. + # # === Template caching # # By default, Rails will compile each template to a method in order to render it. When you alter a template, diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb index 8d78ba13d5..cd52763f31 100644 --- a/actionview/lib/action_view/helpers/form_helper.rb +++ b/actionview/lib/action_view/helpers/form_helper.rb @@ -4,6 +4,7 @@ require 'action_view/helpers/tag_helper' require 'action_view/helpers/form_tag_helper' require 'action_view/helpers/active_model_helper' require 'action_view/model_naming' +require 'action_view/record_identifier' require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/string/output_safety' @@ -110,6 +111,7 @@ module ActionView include FormTagHelper include UrlHelper include ModelNaming + include RecordIdentifier # Creates a form that allows the user to create or update the attributes # of a specific model object. diff --git a/actionview/lib/action_view/helpers/record_tag_helper.rb b/actionview/lib/action_view/helpers/record_tag_helper.rb index 77c3e6d394..f7ee573035 100644 --- a/actionview/lib/action_view/helpers/record_tag_helper.rb +++ b/actionview/lib/action_view/helpers/record_tag_helper.rb @@ -1,108 +1,21 @@ -require 'action_view/record_identifier' - module ActionView - # = Action View Record Tag Helpers module Helpers module RecordTagHelper - include ActionView::RecordIdentifier - - # Produces a wrapper DIV element with id and class parameters that - # relate to the specified Active Record object. Usage example: - # - # <%= div_for(@person, class: "foo") do %> - # <%= @person.name %> - # <% end %> - # - # produces: - # - # <div id="person_123" class="person foo"> Joe Bloggs </div> - # - # You can also pass an array of Active Record objects, which will then - # get iterated over and yield each record as an argument for the block. - # For example: - # - # <%= div_for(@people, class: "foo") do |person| %> - # <%= person.name %> - # <% end %> - # - # produces: - # - # <div id="person_123" class="person foo"> Joe Bloggs </div> - # <div id="person_124" class="person foo"> Jane Bloggs </div> - # - def div_for(record, *args, &block) - content_tag_for(:div, record, *args, &block) + def div_for(*) + raise NoMethodError, "The `div_for` method has been removed from " \ + "Rails. To continue using it, add the `record_tag_helper` gem to " \ + "your Gemfile:\n" \ + " gem 'record_tag_helper', '~> 1.0'\n" \ + "Consult the Rails upgrade guide for details." end - # content_tag_for creates an HTML element with id and class parameters - # that relate to the specified Active Record object. For example: - # - # <%= content_tag_for(:tr, @person) do %> - # <td><%= @person.first_name %></td> - # <td><%= @person.last_name %></td> - # <% end %> - # - # would produce the following HTML (assuming @person is an instance of - # a Person object, with an id value of 123): - # - # <tr id="person_123" class="person">....</tr> - # - # If you require the HTML id attribute to have a prefix, you can specify it: - # - # <%= content_tag_for(:tr, @person, :foo) do %> ... - # - # produces: - # - # <tr id="foo_person_123" class="person">... - # - # You can also pass an array of objects which this method will loop through - # and yield the current object to the supplied block, reducing the need for - # having to iterate through the object (using <tt>each</tt>) beforehand. - # For example (assuming @people is an array of Person objects): - # - # <%= content_tag_for(:tr, @people) do |person| %> - # <td><%= person.first_name %></td> - # <td><%= person.last_name %></td> - # <% end %> - # - # produces: - # - # <tr id="person_123" class="person">...</tr> - # <tr id="person_124" class="person">...</tr> - # - # content_tag_for also accepts a hash of options, which will be converted to - # additional HTML attributes. If you specify a <tt>:class</tt> value, it will be combined - # with the default class name for your object. For example: - # - # <%= content_tag_for(:li, @person, class: "bar") %>... - # - # produces: - # - # <li id="person_123" class="person bar">... - # - def content_tag_for(tag_name, single_or_multiple_records, prefix = nil, options = nil, &block) - options, prefix = prefix, nil if prefix.is_a?(Hash) - - Array(single_or_multiple_records).map do |single_record| - content_tag_for_single_record(tag_name, single_record, prefix, options, &block) - end.join("\n").html_safe + def content_tag_for(*) + raise NoMethodError, "The `content_tag_for` method has been removed from " \ + "Rails. To continue using it, add the `record_tag_helper` gem to " \ + "your Gemfile:\n" \ + " gem 'record_tag_helper', '~> 1.0'\n" \ + "Consult the Rails upgrade guide for details." end - - private - - # Called by <tt>content_tag_for</tt> internally to render a content tag - # for each record. - def content_tag_for_single_record(tag_name, record, prefix, options, &block) - options = options ? options.dup : {} - options[:class] = [ dom_class(record, prefix), options[:class] ].compact - options[:id] = dom_id(record, prefix) - - if block_given? - content_tag(tag_name, capture(record, &block), options) - else - content_tag(tag_name, "", options) - end - end end end end diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index 6b61378a1f..305d9c6ee3 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -87,6 +87,19 @@ module ActionView # expected_encoding # ) + ## + # :method: local_assigns + # + # Returns a hash with the defined local variables. + # + # Given this sub template rendering: + # + # <%= render "shared/header", { headline: "Welcome", person: person } %> + # + # You can use +local_assigns+ in the sub templates to access the local variables: + # + # local_assigns[:headline] # => "Welcome" + eager_autoload do autoload :Error autoload :Handlers @@ -103,7 +116,7 @@ module ActionView # This finalizer is needed (and exactly with a proc inside another proc) # otherwise templates leak in development. - Finalizer = proc do |method_name, mod| + Finalizer = proc do |method_name, mod| # :nodoc: proc do mod.module_eval do remove_possible_method method_name diff --git a/actionview/test/template/record_tag_helper_test.rb b/actionview/test/template/record_tag_helper_test.rb index ab84bccb56..4b7b653916 100644 --- a/actionview/test/template/record_tag_helper_test.rb +++ b/actionview/test/template/record_tag_helper_test.rb @@ -24,94 +24,10 @@ class RecordTagHelperTest < ActionView::TestCase end def test_content_tag_for - expected = %(<li class="record_tag_post" id="record_tag_post_45"></li>) - actual = content_tag_for(:li, @post) - assert_dom_equal expected, actual + assert_raises(NoMethodError) { content_tag_for(:li, @post) } end - def test_content_tag_for_prefix - expected = %(<ul class="archived_record_tag_post" id="archived_record_tag_post_45"></ul>) - actual = content_tag_for(:ul, @post, :archived) - assert_dom_equal expected, actual - end - - def test_content_tag_for_with_extra_html_options - expected = %(<tr class="record_tag_post special" id="record_tag_post_45" style='background-color: #f0f0f0'></tr>) - actual = content_tag_for(:tr, @post, class: "special", style: "background-color: #f0f0f0") - assert_dom_equal expected, actual - end - - def test_content_tag_for_with_array_css_class - expected = %(<tr class="record_tag_post special odd" id="record_tag_post_45"></tr>) - actual = content_tag_for(:tr, @post, class: ["special", "odd"]) - assert_dom_equal expected, actual - end - - def test_content_tag_for_with_prefix_and_extra_html_options - expected = %(<tr class="archived_record_tag_post special" id="archived_record_tag_post_45" style='background-color: #f0f0f0'></tr>) - actual = content_tag_for(:tr, @post, :archived, class: "special", style: "background-color: #f0f0f0") - assert_dom_equal expected, actual - end - - def test_block_not_in_erb_multiple_calls - expected = %(<div class="record_tag_post special" id="record_tag_post_45">What a wonderful world!</div>) - actual = div_for(@post, class: "special") { @post.body } - assert_dom_equal expected, actual - actual = div_for(@post, class: "special") { @post.body } - assert_dom_equal expected, actual - end - - def test_block_works_with_content_tag_for_in_erb - expected = %(<tr class="record_tag_post" id="record_tag_post_45">What a wonderful world!</tr>) - actual = render_erb("<%= content_tag_for(:tr, @post) do %><%= @post.body %><% end %>") - assert_dom_equal expected, actual - end - - def test_div_for_in_erb - expected = %(<div class="record_tag_post special" id="record_tag_post_45">What a wonderful world!</div>) - actual = render_erb("<%= div_for(@post, class: 'special') do %><%= @post.body %><% end %>") - assert_dom_equal expected, actual - end - - def test_content_tag_for_collection - post_1 = RecordTagPost.new { |post| post.id = 101; post.body = "Hello!" } - post_2 = RecordTagPost.new { |post| post.id = 102; post.body = "World!" } - expected = %(<li class="record_tag_post" id="record_tag_post_101">Hello!</li>\n<li class="record_tag_post" id="record_tag_post_102">World!</li>) - actual = content_tag_for(:li, [post_1, post_2]) { |post| post.body } - assert_dom_equal expected, actual - end - - def test_content_tag_for_collection_without_given_block - post_1 = RecordTagPost.new.tap { |post| post.id = 101; post.body = "Hello!" } - post_2 = RecordTagPost.new.tap { |post| post.id = 102; post.body = "World!" } - expected = %(<li class="record_tag_post" id="record_tag_post_101"></li>\n<li class="record_tag_post" id="record_tag_post_102"></li>) - actual = content_tag_for(:li, [post_1, post_2]) - assert_dom_equal expected, actual - end - - def test_div_for_collection - post_1 = RecordTagPost.new { |post| post.id = 101; post.body = "Hello!" } - post_2 = RecordTagPost.new { |post| post.id = 102; post.body = "World!" } - expected = %(<div class="record_tag_post" id="record_tag_post_101">Hello!</div>\n<div class="record_tag_post" id="record_tag_post_102">World!</div>) - actual = div_for([post_1, post_2]) { |post| post.body } - assert_dom_equal expected, actual - end - - def test_content_tag_for_single_record_is_html_safe - result = div_for(@post, class: "special") { @post.body } - assert result.html_safe? - end - - def test_content_tag_for_collection_is_html_safe - post_1 = RecordTagPost.new { |post| post.id = 101; post.body = "Hello!" } - post_2 = RecordTagPost.new { |post| post.id = 102; post.body = "World!" } - result = content_tag_for(:li, [post_1, post_2]) { |post| post.body } - assert result.html_safe? - end - - def test_content_tag_for_does_not_change_options_hash - options = { class: "important" } - content_tag_for(:li, @post, options) - assert_equal({ class: "important" }, options) + def test_div_for + assert_raises(NoMethodError) { div_for(@post, class: "special") } end end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index c303bf5684..a3e00e4dc9 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +* Deprecate `ActiveModel::Errors#get`, `ActiveModel::Errors#set` and + `ActiveModel::Errors#[]=` methods that have inconsistent behaviour. + + *Wojciech Wnętrzak* + * Allow symbol as values for `tokenize` of `LengthValidator` *Kensuke Naito* diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index a809c72ccd..b1d090b830 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -3,6 +3,7 @@ require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/object/deep_dup' +require 'active_support/deprecation' module ActiveModel # == Active \Model \Errors @@ -72,7 +73,7 @@ module ActiveModel # end def initialize(base) @base = base - @messages = {} + @messages = Hash.new { |messages, attribute| messages[attribute] = [] } @details = Hash.new { |details, attribute| details[attribute] = [] } end @@ -110,8 +111,14 @@ module ActiveModel # # person.errors.messages # => {:name=>["cannot be nil"]} # person.errors.get(:name) # => ["cannot be nil"] - # person.errors.get(:age) # => nil + # person.errors.get(:age) # => [] def get(key) + ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) + ActiveModel::Errors#get is deprecated and will be removed in Rails 5.1 + + To achieve the same use messages[:#{key}] + MESSAGE + messages[key] end @@ -121,6 +128,12 @@ module ActiveModel # person.errors.set(:name, ["can't be nil"]) # person.errors.get(:name) # => ["can't be nil"] def set(key, value) + ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) + ActiveModel::Errors#set is deprecated and will be removed in Rails 5.1 + + To achieve the same use messages[:#{key}] = "#{value}" + MESSAGE + messages[key] = value end @@ -128,7 +141,7 @@ module ActiveModel # # person.errors.get(:name) # => ["cannot be nil"] # person.errors.delete(:name) # => ["cannot be nil"] - # person.errors.get(:name) # => nil + # person.errors.get(:name) # => [] def delete(key) messages.delete(key) details.delete(key) @@ -140,7 +153,7 @@ module ActiveModel # person.errors[:name] # => ["cannot be nil"] # person.errors['name'] # => ["cannot be nil"] def [](attribute) - get(attribute.to_sym) || set(attribute.to_sym, []) + messages[attribute.to_sym] end # Adds to the supplied attribute the supplied error message. @@ -148,7 +161,13 @@ module ActiveModel # person.errors[:name] = "must be set" # person.errors[:name] # => ['must be set'] def []=(attribute, error) - self[attribute] << error + ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) + ActiveModel::Errors#[]= is deprecated and will be removed in Rails 5.1 + + To achieve the same use messages[:#{attribute}] << "#{error}" + MESSAGE + + messages[attribute.to_sym] << error end # Iterates through each error key, value pair in the error messages hash. @@ -167,7 +186,7 @@ module ActiveModel # end def each messages.each_key do |attribute| - self[attribute].each { |error| yield attribute, error } + messages[attribute].each { |error| yield attribute, error } end end @@ -317,8 +336,8 @@ module ActiveModel raise exception, full_message(attribute, message) end - details[attribute.to_sym] << detail - self[attribute] << message + details[attribute.to_sym] << detail + messages[attribute.to_sym] << message end # Will add an error message to each of the attributes in +attributes+ @@ -384,7 +403,7 @@ module ActiveModel # person.errors.full_messages_for(:name) # # => ["Name is too short (minimum is 5 characters)", "Name can't be blank"] def full_messages_for(attribute) - (get(attribute) || []).map { |message| full_message(attribute, message) } + messages[attribute].map { |message| full_message(attribute, message) } end # Returns a full message for a given attribute. diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb index 17dbb817d0..e736ccf6a0 100644 --- a/activemodel/test/cases/errors_test.rb +++ b/activemodel/test/cases/errors_test.rb @@ -29,28 +29,28 @@ class ErrorsTest < ActiveModel::TestCase def test_delete errors = ActiveModel::Errors.new(self) - errors[:foo] = 'omg' + errors[:foo] << 'omg' errors.delete(:foo) assert_empty errors[:foo] end def test_include? errors = ActiveModel::Errors.new(self) - errors[:foo] = 'omg' + errors[:foo] << 'omg' assert errors.include?(:foo), 'errors should include :foo' end def test_dup errors = ActiveModel::Errors.new(self) - errors[:foo] = 'bar' + errors[:foo] << 'bar' errors_dup = errors.dup - errors_dup[:bar] = 'omg' + errors_dup[:bar] << 'omg' assert_not_same errors_dup.messages, errors.messages end def test_has_key? errors = ActiveModel::Errors.new(self) - errors[:foo] = 'omg' + errors[:foo] << 'omg' assert_equal true, errors.has_key?(:foo), 'errors should have key :foo' end @@ -61,7 +61,7 @@ class ErrorsTest < ActiveModel::TestCase def test_key? errors = ActiveModel::Errors.new(self) - errors[:foo] = 'omg' + errors[:foo] << 'omg' assert_equal true, errors.key?(:foo), 'errors should have key :foo' end @@ -81,37 +81,41 @@ class ErrorsTest < ActiveModel::TestCase test "get returns the errors for the provided key" do errors = ActiveModel::Errors.new(self) - errors[:foo] = "omg" + errors[:foo] << "omg" - assert_equal ["omg"], errors.get(:foo) + assert_deprecated do + assert_equal ["omg"], errors.get(:foo) + end end test "sets the error with the provided key" do errors = ActiveModel::Errors.new(self) - errors.set(:foo, "omg") + assert_deprecated do + errors.set(:foo, "omg") + end assert_equal({ foo: "omg" }, errors.messages) end test "error access is indifferent" do errors = ActiveModel::Errors.new(self) - errors[:foo] = "omg" + errors[:foo] << "omg" assert_equal ["omg"], errors["foo"] end test "values returns an array of messages" do errors = ActiveModel::Errors.new(self) - errors.set(:foo, "omg") - errors.set(:baz, "zomg") + errors.messages[:foo] = "omg" + errors.messages[:baz] = "zomg" assert_equal ["omg", "zomg"], errors.values end test "keys returns the error keys" do errors = ActiveModel::Errors.new(self) - errors.set(:foo, "omg") - errors.set(:baz, "zomg") + errors.messages[:foo] << "omg" + errors.messages[:baz] << "zomg" assert_equal [:foo, :baz], errors.keys end @@ -133,7 +137,9 @@ class ErrorsTest < ActiveModel::TestCase test "assign error" do person = Person.new - person.errors[:name] = 'should not be nil' + assert_deprecated do + person.errors[:name] = 'should not be nil' + end assert_equal ["should not be nil"], person.errors[:name] end diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index e16fe4dbeb..8f6676dc65 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -365,83 +365,6 @@ WIP: Not all the helpers are listed here. For a full list see the [API documenta The following is only a brief overview summary of the helpers available in Action View. It's recommended that you review the [API Documentation](http://api.rubyonrails.org/classes/ActionView/Helpers.html), which covers all of the helpers in more detail, but this should serve as a good starting point. -### RecordTagHelper - -This module provides methods for generating container tags, such as `div`, for your record. This is the recommended way of creating a container for render your Active Record object, as it adds an appropriate class and id attributes to that container. You can then refer to those containers easily by following the convention, instead of having to think about which class or id attribute you should use. - -#### content_tag_for - -Renders a container tag that relates to your Active Record Object. - -For example, given `@article` is the object of `Article` class, you can do: - -```html+erb -<%= content_tag_for(:tr, @article) do %> - <td><%= @article.title %></td> -<% end %> -``` - -This will generate this HTML output: - -```html -<tr id="article_1234" class="article"> - <td>Hello World!</td> -</tr> -``` - -You can also supply HTML attributes as an additional option hash. For example: - -```html+erb -<%= content_tag_for(:tr, @article, class: "frontpage") do %> - <td><%= @article.title %></td> -<% end %> -``` - -Will generate this HTML output: - -```html -<tr id="article_1234" class="article frontpage"> - <td>Hello World!</td> -</tr> -``` - -You can pass a collection of Active Record objects. This method will loop through your objects and create a container for each of them. For example, given `@articles` is an array of two `Article` objects: - -```html+erb -<%= content_tag_for(:tr, @articles) do |article| %> - <td><%= article.title %></td> -<% end %> -``` - -Will generate this HTML output: - -```html -<tr id="article_1234" class="article"> - <td>Hello World!</td> -</tr> -<tr id="article_1235" class="article"> - <td>Ruby on Rails Rocks!</td> -</tr> -``` - -#### div_for - -This is actually a convenient method which calls `content_tag_for` internally with `:div` as the tag name. You can pass either an Active Record object or a collection of objects. For example: - -```html+erb -<%= div_for(@article, class: "frontpage") do %> - <td><%= @article.title %></td> -<% end %> -``` - -Will generate this HTML output: - -```html -<div id="article_1234" class="article frontpage"> - <td>Hello World!</td> -</div> -``` - ### AssetTagHelper This module provides methods for generating HTML that links views to assets such as images, JavaScript files, stylesheets, and feeds. diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index e06706d750..32d1e2c6e7 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -173,12 +173,12 @@ $ git checkout -b my_new_branch It doesn't matter much what name you use, because this branch will only exist on your local computer and your personal repository on GitHub. It won't be part of the Rails Git repository. -### Bundle Update +### Bundle install -Update and install the required gems. +Install the required gems. ```bash -$ bundle update +$ bundle install ``` ### Running an Application Against Your Local Branch @@ -376,6 +376,10 @@ A CHANGELOG entry should summarize what was changed and should end with author's Your name can be added directly after the last word if you don't provide any code examples or don't need multiple paragraphs. Otherwise, it's best to make as a new paragraph. +### Updating the Gemfile.lock + +Some changes requires the dependencies to be upgraded. In these cases make sure you run `bundle update` to get the right version of the dependency and commit the `Gemfile.lock` file within your changes. + ### Sanity Check You should not be the only person who looks at the code before you submit it. diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md index b7fc580939..329d501ce0 100644 --- a/guides/source/layouts_and_rendering.md +++ b/guides/source/layouts_and_rendering.md @@ -1124,6 +1124,36 @@ You can also pass local variables into partials, making them even more powerful Although the same partial will be rendered into both views, Action View's submit helper will return "Create Zone" for the new action and "Update Zone" for the edit action. +To pass a local variable to a partial in only specific cases use the `local_assigns`. + +* `index.html.erb` + + ```erb + <%= render user.articles %> + ``` + +* `show.html.erb` + + ```erb + <%= render article, full: true %> + ``` + +* `_articles.html.erb` + + ```erb + <%= content_tag_for :article, article do |article| %> + <h2><%= article.title %></h2> + + <% if local_assigns[:full] %> + <%= simple_format article.body %> + <% else %> + <%= truncate article.body %> + <% end %> + <% end %> + ``` + +This way it is possible to use the partial without the need to declare all local variables. + Every partial also has a local variable with the same name as the partial (minus the underscore). You can pass an object in to this local variable via the `:object` option: ```erb diff --git a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb index 7d27321610..65563aa6db 100644 --- a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb +++ b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb @@ -6,7 +6,7 @@ module Erb # :nodoc: argument :actions, type: :array, default: [], banner: "method method" def copy_view_files - view_base_path = File.join("app/views", class_path, file_name) + view_base_path = File.join("app/views", class_path, file_name + '_mailer') empty_directory view_base_path if self.behavior == :invoke @@ -31,6 +31,10 @@ module Erb # :nodoc: def formats [:text, :html] end + + def file_name + @_file_name ||= super.gsub(/\_mailer/i, '') + end end end end diff --git a/railties/lib/rails/generators/rails/plugin/templates/gitignore b/railties/lib/rails/generators/rails/plugin/templates/gitignore index 547c9c7d89..d524fcbc4e 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/gitignore +++ b/railties/lib/rails/generators/rails/plugin/templates/gitignore @@ -1,7 +1,6 @@ .bundle/ log/*.log pkg/ -Gemfile.lock <% unless options[:skip_test] && options[:dummy_path] == 'test/dummy' -%> <%= dummy_path %>/db/*.sqlite3 <%= dummy_path %>/db/*.sqlite3-journal diff --git a/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb b/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb index ba131da79d..343c8a3949 100644 --- a/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb +++ b/railties/lib/rails/generators/test_unit/mailer/mailer_generator.rb @@ -16,6 +16,11 @@ module TestUnit # :nodoc: def create_preview_files template "preview.rb", File.join('test/mailers/previews', class_path, "#{file_name}_mailer_preview.rb") end + + protected + def file_name + @_file_name ||= super.gsub(/\_mailer/i, '') + end end end end diff --git a/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb index 3cee517db3..a2f2d30de5 100644 --- a/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb +++ b/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb @@ -4,7 +4,7 @@ require 'test_helper' class <%= class_name %>MailerTest < ActionMailer::TestCase <% actions.each do |action| -%> test "<%= action %>" do - mail = <%= class_name %>.<%= action %> + mail = <%= class_name %>Mailer.<%= action %> assert_equal <%= action.to_s.humanize.inspect %>, mail.subject assert_equal ["to@example.org"], mail.to assert_equal ["from@example.com"], mail.from diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb index febd2fd12e..584e7a82aa 100644 --- a/railties/test/generators/mailer_generator_test.rb +++ b/railties/test/generators/mailer_generator_test.rb @@ -78,13 +78,13 @@ class MailerGeneratorTest < Rails::Generators::TestCase def test_invokes_default_text_template_engine run_generator - assert_file "app/views/notifier/foo.text.erb" do |view| - assert_match(%r(\sapp/views/notifier/foo\.text\.erb), view) + assert_file "app/views/notifier_mailer/foo.text.erb" do |view| + assert_match(%r(\sapp/views/notifier_mailer/foo\.text\.erb), view) assert_match(/<%= @greeting %>/, view) end - assert_file "app/views/notifier/bar.text.erb" do |view| - assert_match(%r(\sapp/views/notifier/bar\.text\.erb), view) + assert_file "app/views/notifier_mailer/bar.text.erb" do |view| + assert_match(%r(\sapp/views/notifier_mailer/bar\.text\.erb), view) assert_match(/<%= @greeting %>/, view) end @@ -95,13 +95,13 @@ class MailerGeneratorTest < Rails::Generators::TestCase def test_invokes_default_html_template_engine run_generator - assert_file "app/views/notifier/foo.html.erb" do |view| - assert_match(%r(\sapp/views/notifier/foo\.html\.erb), view) + assert_file "app/views/notifier_mailer/foo.html.erb" do |view| + assert_match(%r(\sapp/views/notifier_mailer/foo\.html\.erb), view) assert_match(/<%= @greeting %>/, view) end - assert_file "app/views/notifier/bar.html.erb" do |view| - assert_match(%r(\sapp/views/notifier/bar\.html\.erb), view) + assert_file "app/views/notifier_mailer/bar.html.erb" do |view| + assert_match(%r(\sapp/views/notifier_mailer/bar\.html\.erb), view) assert_match(/<%= @greeting %>/, view) end @@ -112,7 +112,7 @@ class MailerGeneratorTest < Rails::Generators::TestCase def test_invokes_default_template_engine_even_with_no_action run_generator ["notifier"] - assert_file "app/views/notifier" + assert_file "app/views/notifier_mailer" assert_file "app/views/layouts/mailer.text.erb" assert_file "app/views/layouts/mailer.html.erb" end @@ -133,8 +133,8 @@ class MailerGeneratorTest < Rails::Generators::TestCase assert_match(/class Farm::AnimalMailerPreview < ActionMailer::Preview/, preview) assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/farm\/animal\/moos/, preview) end - assert_file "app/views/farm/animal/moos.text.erb" - assert_file "app/views/farm/animal/moos.html.erb" + assert_file "app/views/farm/animal_mailer/moos.text.erb" + assert_file "app/views/farm/animal_mailer/moos.html.erb" end def test_actions_are_turned_into_methods @@ -173,5 +173,14 @@ class MailerGeneratorTest < Rails::Generators::TestCase assert_no_file "app/mailers/notifier_mailer_mailer.rb" assert_file "app/mailers/notifier_mailer.rb" + + assert_no_file "app/views/notifier_mailer_mailer/" + assert_file "app/views/notifier_mailer/" + + assert_no_file "test/mailers/notifier_mailer_mailer_test.rb" + assert_file "test/mailers/notifier_mailer_test.rb" + + assert_no_file "test/mailers/previews/notifier_mailer_mailer_preview.rb" + assert_file "test/mailers/previews/notifier_mailer_preview.rb" end end diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb index d0ea01dfb0..e839b67960 100644 --- a/railties/test/generators/namespaced_generators_test.rb +++ b/railties/test/generators/namespaced_generators_test.rb @@ -173,20 +173,20 @@ class NamespacedMailerGeneratorTest < NamespacedGeneratorTestCase def test_invokes_default_template_engine run_generator - assert_file "app/views/test_app/notifier/foo.text.erb" do |view| - assert_match(%r(app/views/test_app/notifier/foo\.text\.erb), view) + assert_file "app/views/test_app/notifier_mailer/foo.text.erb" do |view| + assert_match(%r(app/views/test_app/notifier_mailer/foo\.text\.erb), view) assert_match(/<%= @greeting %>/, view) end - assert_file "app/views/test_app/notifier/bar.text.erb" do |view| - assert_match(%r(app/views/test_app/notifier/bar\.text\.erb), view) + assert_file "app/views/test_app/notifier_mailer/bar.text.erb" do |view| + assert_match(%r(app/views/test_app/notifier_mailer/bar\.text\.erb), view) assert_match(/<%= @greeting %>/, view) end end def test_invokes_default_template_engine_even_with_no_action run_generator ["notifier"] - assert_file "app/views/test_app/notifier" + assert_file "app/views/test_app/notifier_mailer" end end |