diff options
Diffstat (limited to 'actionview')
-rw-r--r-- | actionview/CHANGELOG.md | 12 | ||||
-rw-r--r-- | actionview/README.rdoc | 2 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/asset_tag_helper.rb | 7 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/atom_feed_helper.rb | 4 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/cache_helper.rb | 22 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/form_helper.rb | 63 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/form_options_helper.rb | 2 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/translation_helper.rb | 12 | ||||
-rw-r--r-- | actionview/test/template/asset_tag_helper_test.rb | 8 | ||||
-rw-r--r-- | actionview/test/template/translation_helper_test.rb | 29 | ||||
-rw-r--r-- | actionview/test/template/url_helper_test.rb | 10 |
11 files changed, 112 insertions, 59 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 78ce230b3a..a6d5c08fe9 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,15 @@ +* Remove `:rescue_format` option for `translate` helper since it's no longer + supported by I18n. + + *Bernard Potocki* + +* `translate` should handle `raise` flag correctly in case of both main and default + translation is missing. + + Fixes #19967 + + *Bernard Potocki* + * Load the `default_form_builder` from the controller on initialization, which overrides the global config if it is present. diff --git a/actionview/README.rdoc b/actionview/README.rdoc index 5bb62c7562..8b1f85f748 100644 --- a/actionview/README.rdoc +++ b/actionview/README.rdoc @@ -9,7 +9,7 @@ used to inline short Ruby snippets inside HTML), and XML Builder. The latest version of Action View can be installed with RubyGems: - % [sudo] gem install actionview + % gem install actionview Source code can be downloaded as part of the Rails project on GitHub diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb index 60fc9ee1a2..e32f8e219e 100644 --- a/actionview/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb @@ -207,6 +207,7 @@ module ActionView # # => <img alt="Icon" class="menu_icon" src="/icons/icon.gif" /> def image_tag(source, options={}) options = options.symbolize_keys + check_for_image_tag_errors(options) src = options[:src] = path_to_image(source) @@ -325,6 +326,12 @@ module ActionView [size, size] end end + + def check_for_image_tag_errors(options) + if options[:size] && (options[:height] || options[:width]) + raise ArgumentError, "Cannot pass a :size option with a :height or :width option" + end + end end end end diff --git a/actionview/lib/action_view/helpers/atom_feed_helper.rb b/actionview/lib/action_view/helpers/atom_feed_helper.rb index d8be4e5678..bb1cdd0f8d 100644 --- a/actionview/lib/action_view/helpers/atom_feed_helper.rb +++ b/actionview/lib/action_view/helpers/atom_feed_helper.rb @@ -16,7 +16,7 @@ module ActionView # end # # app/controllers/posts_controller.rb: - # class PostsController < ApplicationController::Base + # class PostsController < ApplicationController # # GET /posts.html # # GET /posts.atom # def index @@ -51,7 +51,7 @@ module ActionView # * <tt>:language</tt>: Defaults to "en-US". # * <tt>:root_url</tt>: The HTML alternative that this feed is doubling for. Defaults to / on the current host. # * <tt>:url</tt>: The URL for this feed. Defaults to the current URL. - # * <tt>:id</tt>: The id for this feed. Defaults to "tag:#{request.host},#{options[:schema_date]}:#{request.fullpath.split(".")[0]}" + # * <tt>:id</tt>: The id for this feed. Defaults to "tag:localhost,2005:/posts", in this case. # * <tt>:schema_date</tt>: The date at which the tag scheme for the feed was first used. A good default is the year you # created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information. If not specified, # 2005 is used (as an "I don't care" value). diff --git a/actionview/lib/action_view/helpers/cache_helper.rb b/actionview/lib/action_view/helpers/cache_helper.rb index 0e2a5f90f4..251764a8de 100644 --- a/actionview/lib/action_view/helpers/cache_helper.rb +++ b/actionview/lib/action_view/helpers/cache_helper.rb @@ -75,7 +75,8 @@ module ActionView # render(topics) => render("topics/topic") # render(message.topics) => render("topics/topic") # - # It's not possible to derive all render calls like that, though. Here are a few examples of things that can't be derived: + # It's not possible to derive all render calls like that, though. + # Here are a few examples of things that can't be derived: # # render group_of_attachments # render @project.documents.where(published: true).order('created_at') @@ -97,19 +98,21 @@ module ActionView # <%# Template Dependency: todolists/todolist %> # <%= render_sortable_todolists @project.todolists %> # - # The pattern used to match these is /# Template Dependency: ([^ ]+)/, so it's important that you type it out just so. + # The pattern used to match these is /# Template Dependency: ([^ ]+)/, + # so it's important that you type it out just so. # You can only declare one template dependency per line. # # === External dependencies # - # If you use a helper method, for example, inside of a cached block and you then update that helper, - # you'll have to bump the cache as well. It doesn't really matter how you do it, but the md5 of the template file + # If you use a helper method, for example, inside a cached block and + # you then update that helper, you'll have to bump the cache as well. + # It doesn't really matter how you do it, but the md5 of the template file # must change. One recommendation is to simply be explicit in a comment, like: # # <%# Helper Dependency Updated: May 6, 2012 at 6pm %> # <%= some_helper_method(person) %> # - # Now all you'll have to do is change that timestamp when the helper method changes. + # Now all you have to do is change that timestamp when the helper method changes. # # === Automatic Collection Caching # @@ -118,7 +121,7 @@ module ActionView # <%= render @notifications %> # <%= render partial: 'notifications/notification', collection: @notifications %> # - # If the notifications/_notification partial starts with a cache call like so: + # If the notifications/_notification partial starts with a cache call as: # # <% cache notification do %> # <%= notification.name %> @@ -127,14 +130,15 @@ module ActionView # The collection can then automatically use any cached renders for that # template by reading them at once instead of one by one. # - # See ActionView::Template::Handlers::ERB.resource_cache_call_pattern for more - # information on what cache calls make a template eligible for this collection caching. + # See ActionView::Template::Handlers::ERB.resource_cache_call_pattern for + # more information on what cache calls make a template eligible for this + # collection caching. # # The automatic cache multi read can be turned off like so: # # <%= render @notifications, cache: false %> def cache(name = {}, options = nil, &block) - if controller.perform_caching + if controller.respond_to?(:perform_caching) && controller.perform_caching safe_concat(fragment_for(cache_fragment_name(name, options), options, &block)) else yield diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb index 7fdeca5ea8..3a9acafaa2 100644 --- a/actionview/lib/action_view/helpers/form_helper.rb +++ b/actionview/lib/action_view/helpers/form_helper.rb @@ -1631,7 +1631,7 @@ module ActionView # target labels for radio_button tags (where the value is used in the ID of the input tag). # # ==== Examples - # label(:post, :title) + # label(:title) # # => <label for="post_title">Title</label> # # You can localize your labels based on model and attribute names. @@ -1644,7 +1644,7 @@ module ActionView # # Which then will result in # - # label(:post, :body) + # label(:body) # # => <label for="post_body">Write your entire text here</label> # # Localization can also be based purely on the translation of the attribute-name @@ -1655,21 +1655,22 @@ module ActionView # post: # cost: "Total cost" # - # label(:post, :cost) + # label(:cost) # # => <label for="post_cost">Total cost</label> # - # label(:post, :title, "A short title") + # label(:title, "A short title") # # => <label for="post_title">A short title</label> # - # label(:post, :title, "A short title", class: "title_label") + # label(:title, "A short title", class: "title_label") # # => <label for="post_title" class="title_label">A short title</label> # - # label(:post, :privacy, "Public Post", value: "public") + # label(:privacy, "Public Post", value: "public") # # => <label for="post_privacy_public">Public Post</label> # - # label(:post, :terms) do + # label(:terms) do # 'Accept <a href="/terms">Terms</a>.'.html_safe # end + # # => <label for="post_terms">Accept <a href="/terms">Terms</a>.</label> def label(method, text = nil, options = {}, &block) @template.label(@object_name, method, text, objectify_options(options), &block) end @@ -1718,16 +1719,17 @@ module ActionView # hashes instead of arrays. # # # Let's say that @post.validated? is 1: - # check_box("post", "validated") + # check_box("validated") # # => <input name="post[validated]" type="hidden" value="0" /> # # <input checked="checked" type="checkbox" id="post_validated" name="post[validated]" value="1" /> # # # Let's say that @puppy.gooddog is "no": - # check_box("puppy", "gooddog", {}, "yes", "no") + # check_box("gooddog", {}, "yes", "no") # # => <input name="puppy[gooddog]" type="hidden" value="no" /> # # <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" /> # - # check_box("eula", "accepted", { class: 'eula_check' }, "yes", "no") + # # Let's say that @eula.accepted is "no": + # check_box("accepted", { class: 'eula_check' }, "yes", "no") # # => <input name="eula[accepted]" type="hidden" value="no" /> # # <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" /> def check_box(method, options = {}, checked_value = "1", unchecked_value = "0") @@ -1742,13 +1744,14 @@ module ActionView # +options+ hash. You may pass HTML options there as well. # # # Let's say that @post.category returns "rails": - # radio_button("post", "category", "rails") - # radio_button("post", "category", "java") + # radio_button("category", "rails") + # radio_button("category", "java") # # => <input type="radio" id="post_category_rails" name="post[category]" value="rails" checked="checked" /> # # <input type="radio" id="post_category_java" name="post[category]" value="java" /> # - # radio_button("user", "receive_newsletter", "yes") - # radio_button("user", "receive_newsletter", "no") + # # Let's say that @user.category returns "no": + # radio_button("receive_newsletter", "yes") + # radio_button("receive_newsletter", "no") # # => <input type="radio" id="user_receive_newsletter_yes" name="user[receive_newsletter]" value="yes" /> # # <input type="radio" id="user_receive_newsletter_no" name="user[receive_newsletter]" value="no" checked="checked" /> def radio_button(method, tag_value, options = {}) @@ -1761,14 +1764,17 @@ module ActionView # shown. # # ==== Examples - # hidden_field(:signup, :pass_confirm) - # # => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" /> + # # Let's say that @signup.pass_confirm returns true: + # hidden_field(:pass_confirm) + # # => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="true" /> # - # hidden_field(:post, :tag_list) - # # => <input type="hidden" id="post_tag_list" name="post[tag_list]" value="#{@post.tag_list}" /> + # # Let's say that @post.tag_list returns "blog, ruby": + # hidden_field(:tag_list) + # # => <input type="hidden" id="post_tag_list" name="post[tag_list]" value="blog, ruby" /> # - # hidden_field(:user, :token) - # # => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" /> + # # Let's say that @user.token returns "abcde": + # hidden_field(:token) + # # => <input type="hidden" id="user_token" name="user[token]" value="abcde" /> # def hidden_field(method, options = {}) @emitted_hidden_id = true if method == :id @@ -1789,19 +1795,24 @@ module ActionView # * <tt>:accept</tt> - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations. # # ==== Examples - # file_field(:user, :avatar) + # # Let's say that @user has avatar: + # file_field(:avatar) # # => <input type="file" id="user_avatar" name="user[avatar]" /> # - # file_field(:post, :image, :multiple => true) - # # => <input type="file" id="post_image" name="post[image]" multiple="true" /> + # # Let's say that @post has image: + # file_field(:image, :multiple => true) + # # => <input type="file" id="post_image" name="post[image][]" multiple="multiple" /> # - # file_field(:post, :attached, accept: 'text/html') + # # Let's say that @post has attached: + # file_field(:attached, accept: 'text/html') # # => <input accept="text/html" type="file" id="post_attached" name="post[attached]" /> # - # file_field(:post, :image, accept: 'image/png,image/gif,image/jpeg') + # # Let's say that @post has image: + # file_field(:image, accept: 'image/png,image/gif,image/jpeg') # # => <input type="file" id="post_image" name="post[image]" accept="image/png,image/gif,image/jpeg" /> # - # file_field(:attachment, :file, class: 'file_input') + # # Let's say that @attachment has file: + # file_field(:file, class: 'file_input') # # => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" /> def file_field(method, options = {}) self.multipart = true diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index 8a5928477f..38fee3b314 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -80,7 +80,7 @@ module ActionView # # When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled. # - # collection_select(:post, :category_id, Category.all, :id, :name, {disabled: lambda{|category| category.archived? }}) + # collection_select(:post, :category_id, Category.all, :id, :name, {disabled: -> (category) { category.archived? }}) # # If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return: # <select name="post[category_id]" id="post_category_id"> diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb index 089627a221..0615bd2e0d 100644 --- a/actionview/lib/action_view/helpers/translation_helper.rb +++ b/actionview/lib/action_view/helpers/translation_helper.rb @@ -60,12 +60,12 @@ module ActionView # If the user has explicitly decided to NOT raise errors, pass that option to I18n. # Otherwise, tell I18n to raise an exception, which we rescue further in this method. # Note: `raise_error` refers to us re-raising the error in this method. I18n is forced to raise by default. - if options[:raise] == false || (options.key?(:rescue_format) && options[:rescue_format].nil?) + if options[:raise] == false raise_error = false - options[:raise] = false + i18n_raise = false else - raise_error = options[:raise] || options[:rescue_format] || ActionView::Base.raise_on_missing_translations - options[:raise] = true + raise_error = options[:raise] || ActionView::Base.raise_on_missing_translations + i18n_raise = true end if html_safe_translation_key?(key) @@ -75,11 +75,11 @@ module ActionView html_safe_options[name] = ERB::Util.html_escape(value.to_s) end end - translation = I18n.translate(scope_key_by_partial(key), html_safe_options) + translation = I18n.translate(scope_key_by_partial(key), html_safe_options.merge(raise: i18n_raise)) translation.respond_to?(:html_safe) ? translation.html_safe : translation else - I18n.translate(scope_key_by_partial(key), options) + I18n.translate(scope_key_by_partial(key), options.merge(raise: i18n_raise)) end rescue I18n::MissingTranslationData => e if remaining_defaults.present? diff --git a/actionview/test/template/asset_tag_helper_test.rb b/actionview/test/template/asset_tag_helper_test.rb index 02dce71496..6e6ce20924 100644 --- a/actionview/test/template/asset_tag_helper_test.rb +++ b/actionview/test/template/asset_tag_helper_test.rb @@ -464,6 +464,14 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal({:size => '16x10'}, options) end + def test_image_tag_raises_an_error_for_competing_size_arguments + exception = assert_raise(ArgumentError) do + image_tag("gold.png", :height => "100", :width => "200", :size => "45x70") + end + + assert_equal("Cannot pass a :size option with a :height or :width option", exception.message) + end + def test_favicon_link_tag FaviconLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb index df096b3c3a..5dc281adb2 100644 --- a/actionview/test/template/translation_helper_test.rb +++ b/actionview/test/template/translation_helper_test.rb @@ -41,8 +41,8 @@ class TranslationHelperTest < ActiveSupport::TestCase I18n.backend.reload! end - def test_delegates_to_i18n_setting_the_rescue_format_option_to_html - I18n.expects(:translate).with(:foo, :locale => 'en', :raise=>true).returns("") + def test_delegates_setting_to_i18n + I18n.expects(:translate).with(:foo, :locale => 'en', :raise => true).returns("") translate :foo, :locale => 'en' end @@ -58,12 +58,6 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal true, translate(:"translations.missing").html_safe? end - def test_returns_missing_translation_message_using_nil_as_rescue_format - expected = 'translation missing: en.translations.missing' - assert_equal expected, translate(:"translations.missing", :rescue_format => nil) - assert_equal false, translate(:"translations.missing", :rescue_format => nil).html_safe? - end - def test_raises_missing_translation_message_with_raise_config_option ActionView::Base.raise_on_missing_translations = true @@ -96,12 +90,6 @@ class TranslationHelperTest < ActiveSupport::TestCase I18n.exception_handler = old_exception_handler end - def test_i18n_translate_defaults_to_nil_rescue_format - expected = 'translation missing: en.translations.missing' - assert_equal expected, I18n.translate(:"translations.missing") - assert_equal false, I18n.translate(:"translations.missing").html_safe? - end - def test_translation_returning_an_array expected = %w(foo bar) assert_equal expected, translate(:"translations.array") @@ -157,6 +145,19 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal true, translation.html_safe? end + def test_translate_with_missing_default + translation = translate(:'translations.missing', :default => :'translations.missing_html') + expected = '<span class="translation_missing" title="translation missing: en.translations.missing_html">Missing Html</span>' + assert_equal expected, translation + assert_equal true, translation.html_safe? + end + + def test_translate_with_missing_default_and_raise_option + assert_raise(I18n::MissingTranslationData) do + translate(:'translations.missing', :default => :'translations.missing_html', :raise => true) + end + end + def test_translate_with_two_defaults_named_html translation = translate(:'translations.missing', :default => [:'translations.missing_html', :'translations.hello_html']) assert_equal '<a>Hello World</a>', translation diff --git a/actionview/test/template/url_helper_test.rb b/actionview/test/template/url_helper_test.rb index ef4df0407a..0e35c67516 100644 --- a/actionview/test/template/url_helper_test.rb +++ b/actionview/test/template/url_helper_test.rb @@ -379,6 +379,11 @@ class UrlHelperTest < ActiveSupport::TestCase assert_dom_equal %{<a href="/">Listing</a>}, link_to_if(true, "Listing", url_hash) end + def test_link_to_if_with_block + assert_equal "Fallback", link_to_if(false, "Showing", url_hash) { "Fallback" } + assert_dom_equal %{<a href="/">Listing</a>}, link_to_if(true, "Listing", url_hash) { "Fallback" } + end + def request_for_url(url, opts = {}) env = Rack::MockRequest.env_for("http://www.example.com#{url}", opts) ActionDispatch::Request.new(env) @@ -479,6 +484,11 @@ class UrlHelperTest < ActiveSupport::TestCase link_to_unless_current("Listing", "http://www.example.com/") end + def test_link_to_unless_with_block + assert_dom_equal %{<a href="/">Showing</a>}, link_to_unless(false, "Showing", url_hash) { "Fallback" } + assert_equal "Fallback", link_to_unless(true, "Listing", url_hash) { "Fallback" } + end + def test_mail_to assert_dom_equal %{<a href="mailto:david@loudthinking.com">david@loudthinking.com</a>}, mail_to("david@loudthinking.com") assert_dom_equal %{<a href="mailto:david@loudthinking.com">David Heinemeier Hansson</a>}, mail_to("david@loudthinking.com", "David Heinemeier Hansson") |