aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
Diffstat (limited to 'actionview')
-rw-r--r--actionview/CHANGELOG.md5
-rw-r--r--actionview/MIT-LICENSE2
-rw-r--r--actionview/actionview.gemspec2
-rw-r--r--actionview/lib/action_view.rb2
-rw-r--r--actionview/lib/action_view/helpers/capture_helper.rb3
-rw-r--r--actionview/lib/action_view/helpers/tags/search_field.rb21
-rw-r--r--actionview/lib/action_view/helpers/tags/text_field.rb1
-rw-r--r--actionview/lib/action_view/helpers/text_helper.rb2
-rw-r--r--actionview/lib/action_view/helpers/url_helper.rb5
-rw-r--r--actionview/lib/action_view/lookup_context.rb9
-rw-r--r--actionview/lib/action_view/record_identifier.rb61
-rw-r--r--actionview/lib/action_view/renderer/partial_renderer.rb12
-rw-r--r--actionview/test/activerecord/polymorphic_routes_test.rb20
-rw-r--r--actionview/test/lib/controller/fake_models.rb25
-rw-r--r--actionview/test/template/record_identifier_test.rb44
-rw-r--r--actionview/test/template/render_test.rb20
-rw-r--r--actionview/test/template/url_helper_test.rb4
17 files changed, 169 insertions, 69 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 729717608f..d71f29d7b0 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1 +1,6 @@
+* Add an explicit error message, in `ActionView::PartialRenderer` for partial
+ `rendering`, when the value of option `as` has invalid characters.
+
+ *Angelo Capilleri*
+
Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/actionview/CHANGELOG.md) for previous changes.
diff --git a/actionview/MIT-LICENSE b/actionview/MIT-LICENSE
index d58dd9ed9b..3ec7a617cf 100644
--- a/actionview/MIT-LICENSE
+++ b/actionview/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2014 David Heinemeier Hansson
+Copyright (c) 2004-2015 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/actionview/actionview.gemspec b/actionview/actionview.gemspec
index fd4ffea33d..8f9194cda7 100644
--- a/actionview/actionview.gemspec
+++ b/actionview/actionview.gemspec
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
s.summary = 'Rendering framework putting the V in MVC (part of Rails).'
s.description = 'Simple, battle-tested conventions and helpers for building web pages.'
- s.required_ruby_version = '>= 2.1.0'
+ s.required_ruby_version = '>= 2.2.0'
s.license = 'MIT'
diff --git a/actionview/lib/action_view.rb b/actionview/lib/action_view.rb
index 6a1837c6e2..c3bbac27fd 100644
--- a/actionview/lib/action_view.rb
+++ b/actionview/lib/action_view.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2014 David Heinemeier Hansson
+# Copyright (c) 2004-2015 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionview/lib/action_view/helpers/capture_helper.rb b/actionview/lib/action_view/helpers/capture_helper.rb
index 75d1634b2e..5a3223968f 100644
--- a/actionview/lib/action_view/helpers/capture_helper.rb
+++ b/actionview/lib/action_view/helpers/capture_helper.rb
@@ -31,7 +31,8 @@ module ActionView
# <head><title><%= @greeting %></title></head>
# <body>
# <b><%= @greeting %></b>
- # </body></html>
+ # </body>
+ # </html>
#
def capture(*args)
value = nil
diff --git a/actionview/lib/action_view/helpers/tags/search_field.rb b/actionview/lib/action_view/helpers/tags/search_field.rb
index 4597cec6fa..a848aeabfa 100644
--- a/actionview/lib/action_view/helpers/tags/search_field.rb
+++ b/actionview/lib/action_view/helpers/tags/search_field.rb
@@ -3,18 +3,21 @@ module ActionView
module Tags # :nodoc:
class SearchField < TextField # :nodoc:
def render
- super do |options|
- if options["autosave"]
- if options["autosave"] == true
- options["autosave"] = request.host.split(".").reverse.join(".")
- end
- options["results"] ||= 10
- end
+ options = @options.stringify_keys
- if options["onsearch"]
- options["incremental"] = true unless options.has_key?("incremental")
+ if options["autosave"]
+ if options["autosave"] == true
+ options["autosave"] = request.host.split(".").reverse.join(".")
end
+ options["results"] ||= 10
+ end
+
+ if options["onsearch"]
+ options["incremental"] = true unless options.has_key?("incremental")
end
+
+ @options = options
+ super
end
end
end
diff --git a/actionview/lib/action_view/helpers/tags/text_field.rb b/actionview/lib/action_view/helpers/tags/text_field.rb
index 49fc81ec8c..5c576a20ca 100644
--- a/actionview/lib/action_view/helpers/tags/text_field.rb
+++ b/actionview/lib/action_view/helpers/tags/text_field.rb
@@ -11,7 +11,6 @@ module ActionView
options["size"] = options["maxlength"] unless options.key?("size")
options["type"] ||= field_type
options["value"] = options.fetch("value") { value_before_type_cast(object) } unless field_type == "file"
- yield options if block_given?
add_default_name_and_id(options)
tag("input", options)
end
diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb
index a9f1631586..2c40ed1832 100644
--- a/actionview/lib/action_view/helpers/text_helper.rb
+++ b/actionview/lib/action_view/helpers/text_helper.rb
@@ -309,7 +309,7 @@ module ActionView
# <table>
# <% @items.each do |item| %>
# <tr class="<%= cycle("odd", "even") -%>">
- # <td>item</td>
+ # <td><%= item %></td>
# </tr>
# <% end %>
# </table>
diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb
index 364414da05..8c2d5705f1 100644
--- a/actionview/lib/action_view/helpers/url_helper.rb
+++ b/actionview/lib/action_view/helpers/url_helper.rb
@@ -428,6 +428,7 @@ module ActionView
# * <tt>:body</tt> - Preset the body of the email.
# * <tt>:cc</tt> - Carbon Copy additional recipients on the email.
# * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
+ # * <tt>:reply_to</tt> - Preset the Reply-To field of the email.
#
# ==== Obfuscation
# Prior to Rails 4.0, +mail_to+ provided options for encoding the address
@@ -457,9 +458,9 @@ module ActionView
html_options, name = name, nil if block_given?
html_options = (html_options || {}).stringify_keys
- extras = %w{ cc bcc body subject }.map! { |item|
+ extras = %w{ cc bcc body subject reply_to }.map! { |item|
option = html_options.delete(item) || next
- "#{item}=#{Rack::Utils.escape_path(option)}"
+ "#{item.dasherize}=#{Rack::Utils.escape_path(option)}"
}.compact
extras = extras.empty? ? '' : '?' + extras.join('&')
diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb
index ea687d9cca..36855ec3d0 100644
--- a/actionview/lib/action_view/lookup_context.rb
+++ b/actionview/lib/action_view/lookup_context.rb
@@ -191,7 +191,6 @@ module ActionView
def initialize(view_paths, details = {}, prefixes = [])
@details, @details_key = {}, nil
- @skip_default_locale = false
@cache = true
@prefixes = prefixes
@rendered_format = nil
@@ -213,12 +212,6 @@ module ActionView
super(values)
end
- # Do not use the default locale on template lookup.
- def skip_default_locale!
- @skip_default_locale = true
- self.locale = nil
- end
-
# Override locale to return a symbol instead of array.
def locale
@details[:locale].first
@@ -233,7 +226,7 @@ module ActionView
config.locale = value
end
- super(@skip_default_locale ? I18n.locale : default_locale)
+ super(default_locale)
end
# Uses the first format in the formats array for layout lookup.
diff --git a/actionview/lib/action_view/record_identifier.rb b/actionview/lib/action_view/record_identifier.rb
index 63f645431a..c8484bed34 100644
--- a/actionview/lib/action_view/record_identifier.rb
+++ b/actionview/lib/action_view/record_identifier.rb
@@ -2,29 +2,54 @@ require 'active_support/core_ext/module'
require 'action_view/model_naming'
module ActionView
- # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or
- # pretty much any other model type that has an id. These patterns are then used to try elevate the view actions to
- # a higher logical level.
+ # RecordIdentifier encapsulates methods used by various ActionView helpers
+ # to associate records with DOM elements.
#
- # # routes
- # resources :posts
+ # Consider for example the following code that displays the body of a post:
#
- # # view
- # <%= div_for(post) do %> <div id="post_45" class="post">
- # <%= post.body %> What a wonderful world!
- # <% end %> </div>
+ # <%= div_for(post) do %>
+ # <%= post.body %>
+ # <% end %>
#
- # # controller
- # def update
- # post = Post.find(params[:id])
- # post.update(params[:post])
+ # When +post+ is a new, unsaved ActiveRecord::Base intance, the resulting HTML
+ # is:
#
- # redirect_to(post) # Calls polymorphic_url(post) which in turn calls post_url(post)
- # end
+ # <div id="new_post" class="post">
+ # </div>
+ #
+ # When +post+ is a persisted ActiveRecord::Base instance, the resulting HTML
+ # is:
+ #
+ # <div id="post_42" class="post">
+ # What a wonderful world!
+ # </div>
+ #
+ # In both cases, the +id+ and +class+ of the wrapping DOM element are
+ # automatically generated, following naming conventions encapsulated by the
+ # RecordIdentifier methods #dom_id and #dom_class:
+ #
+ # dom_id(Post.new) # => "new_post"
+ # dom_class(Post.new) # => "post"
+ # dom_id(Post.find 42) # => "post_42"
+ # dom_class(Post.find 42) # => "post"
#
- # As the example above shows, you can stop caring to a large extent what the actual id of the post is.
- # You just know that one is being assigned and that the subsequent calls in redirect_to expect that
- # same naming convention and allows you to write less code if you follow it.
+ # Note that these methods do not strictly require +Post+ to be a subclass of
+ # ActiveRecord::Base.
+ # Any +Post+ class will work as long as its instances respond to +to_key+
+ # and +model_name+, given that +model_name+ responds to +param_key+.
+ # For instance:
+ #
+ # class Post
+ # attr_accessor :to_key
+ #
+ # def model_name
+ # OpenStruct.new param_key: 'post'
+ # end
+ #
+ # def self.find(id)
+ # new.tap { |post| post.to_key = [id] }
+ # end
+ # end
module RecordIdentifier
extend self
extend ModelNaming
diff --git a/actionview/lib/action_view/renderer/partial_renderer.rb b/actionview/lib/action_view/renderer/partial_renderer.rb
index f627d5d40c..610396506f 100644
--- a/actionview/lib/action_view/renderer/partial_renderer.rb
+++ b/actionview/lib/action_view/renderer/partial_renderer.rb
@@ -384,7 +384,7 @@ module ActionView
end
if as = options[:as]
- raise_invalid_identifier(as) unless as.to_s =~ /\A[a-z_]\w*\z/
+ raise_invalid_option_as(as) unless as.to_s =~ /\A[a-z_]\w*\z/
as = as.to_sym
end
@@ -530,11 +530,19 @@ module ActionView
end
IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " +
- "make sure your partial name starts with a lowercase letter or underscore, " +
+ "make sure your partial name starts with underscore, " +
+ "and is followed by any combination of letters, numbers and underscores."
+
+ OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " +
+ "make sure it starts with lowercase letter, " +
"and is followed by any combination of letters, numbers and underscores."
def raise_invalid_identifier(path)
raise ArgumentError.new(IDENTIFIER_ERROR_MESSAGE % (path))
end
+
+ def raise_invalid_option_as(as)
+ raise ArgumentError.new(OPTION_AS_ERROR_MESSAGE % (as))
+ end
end
end
diff --git a/actionview/test/activerecord/polymorphic_routes_test.rb b/actionview/test/activerecord/polymorphic_routes_test.rb
index 5842b775bb..8e1ed2776d 100644
--- a/actionview/test/activerecord/polymorphic_routes_test.rb
+++ b/actionview/test/activerecord/polymorphic_routes_test.rb
@@ -25,15 +25,17 @@ class Series < ActiveRecord::Base
self.table_name = 'projects'
end
-class ModelDelegator < ActiveRecord::Base
- self.table_name = 'projects'
-
+class ModelDelegator
def to_model
ModelDelegate.new
end
end
class ModelDelegate
+ def persisted?
+ true
+ end
+
def model_name
ActiveModel::Name.new(self.class)
end
@@ -605,13 +607,18 @@ class PolymorphicRoutesTest < ActionController::TestCase
end
end
- def test_routing_a_to_model_delegate
+ def test_routing_to_a_model_delegate
with_test_routes do
- @delegator.save
assert_url "http://example.com/model_delegates/overridden", @delegator
end
end
+ def test_nested_routing_to_a_model_delegate
+ with_test_routes do
+ assert_url "http://example.com/foo/model_delegates/overridden", [:foo, @delegator]
+ end
+ end
+
def with_namespaced_routes(name)
with_routing do |set|
set.draw do
@@ -645,6 +652,9 @@ class PolymorphicRoutesTest < ActionController::TestCase
end
resources :series
resources :model_delegates
+ namespace :foo do
+ resources :model_delegates
+ end
end
extend @routes.url_helpers
diff --git a/actionview/test/lib/controller/fake_models.rb b/actionview/test/lib/controller/fake_models.rb
index a463a08bb6..789b1d198b 100644
--- a/actionview/test/lib/controller/fake_models.rb
+++ b/actionview/test/lib/controller/fake_models.rb
@@ -111,19 +111,6 @@ class CommentRelevance
end
end
-class Sheep
- extend ActiveModel::Naming
- include ActiveModel::Conversion
-
- attr_reader :id
- def to_key; id ? [id] : nil end
- def save; @id = 1 end
- def new_record?; @id.nil? end
- def name
- @id.nil? ? 'new sheep' : "sheep ##{@id}"
- end
-end
-
class TagRelevance
extend ActiveModel::Naming
include ActiveModel::Conversion
@@ -183,3 +170,15 @@ end
class Car < Struct.new(:color)
end
+
+class Plane
+ attr_reader :to_key
+
+ def model_name
+ OpenStruct.new param_key: 'airplane'
+ end
+
+ def save
+ @to_key = [1]
+ end
+end
diff --git a/actionview/test/template/record_identifier_test.rb b/actionview/test/template/record_identifier_test.rb
index 22038110a5..04898c0b0e 100644
--- a/actionview/test/template/record_identifier_test.rb
+++ b/actionview/test/template/record_identifier_test.rb
@@ -9,7 +9,6 @@ class RecordIdentifierTest < ActiveSupport::TestCase
@record = @klass.new
@singular = 'comment'
@plural = 'comments'
- @uncountable = Sheep
end
def test_dom_id_with_new_record
@@ -47,3 +46,46 @@ class RecordIdentifierTest < ActiveSupport::TestCase
assert_equal @singular, ActionView::RecordIdentifier.dom_class(@record)
end
end
+
+class RecordIdentifierWithoutActiveModelTest < ActiveSupport::TestCase
+ include ActionView::RecordIdentifier
+
+ def setup
+ @record = Plane.new
+ end
+
+ def test_dom_id_with_new_record
+ assert_equal "new_airplane", dom_id(@record)
+ end
+
+ def test_dom_id_with_new_record_and_prefix
+ assert_equal "custom_prefix_airplane", dom_id(@record, :custom_prefix)
+ end
+
+ def test_dom_id_with_saved_record
+ @record.save
+ assert_equal "airplane_1", dom_id(@record)
+ end
+
+ def test_dom_id_with_prefix
+ @record.save
+ assert_equal "edit_airplane_1", dom_id(@record, :edit)
+ end
+
+ def test_dom_class
+ assert_equal 'airplane', dom_class(@record)
+ end
+
+ def test_dom_class_with_prefix
+ assert_equal "custom_prefix_airplane", dom_class(@record, :custom_prefix)
+ end
+
+ def test_dom_id_as_singleton_method
+ @record.save
+ assert_equal "airplane_1", ActionView::RecordIdentifier.dom_id(@record)
+ end
+
+ def test_dom_class_as_singleton_method
+ assert_equal 'airplane', ActionView::RecordIdentifier.dom_class(@record)
+ end
+end
diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb
index 4e502bede9..e580a477a6 100644
--- a/actionview/test/template/render_test.rb
+++ b/actionview/test/template/render_test.rb
@@ -175,14 +175,14 @@ module RenderTestCases
def test_render_partial_with_invalid_name
e = assert_raises(ArgumentError) { @view.render(:partial => "test/200") }
assert_equal "The partial name (test/200) is not a valid Ruby identifier; " +
- "make sure your partial name starts with a lowercase letter or underscore, " +
+ "make sure your partial name starts with underscore, " +
"and is followed by any combination of letters, numbers and underscores.", e.message
end
def test_render_partial_with_missing_filename
e = assert_raises(ArgumentError) { @view.render(:partial => "test/") }
assert_equal "The partial name (test/) is not a valid Ruby identifier; " +
- "make sure your partial name starts with a lowercase letter or underscore, " +
+ "make sure your partial name starts with underscore, " +
"and is followed by any combination of letters, numbers and underscores.", e.message
end
@@ -194,7 +194,21 @@ module RenderTestCases
def test_render_partial_with_hyphen
e = assert_raises(ArgumentError) { @view.render(:partial => "test/a-in") }
assert_equal "The partial name (test/a-in) is not a valid Ruby identifier; " +
- "make sure your partial name starts with a lowercase letter or underscore, " +
+ "make sure your partial name starts with underscore, " +
+ "and is followed by any combination of letters, numbers and underscores.", e.message
+ end
+
+ def test_render_partial_with_invalid_option_as
+ e = assert_raises(ArgumentError) { @view.render(:partial => "test/partial_only", :as => 'a-in') }
+ assert_equal "The value (a-in) of the option `as` is not a valid Ruby identifier; " +
+ "make sure it starts with lowercase letter, " +
+ "and is followed by any combination of letters, numbers and underscores.", e.message
+ end
+
+ def test_render_partial_with_hyphen_and_invalid_option_as
+ e = assert_raises(ArgumentError) { @view.render(:partial => "test/a-in", :as => 'a-in') }
+ assert_equal "The value (a-in) of the option `as` is not a valid Ruby identifier; " +
+ "make sure it starts with lowercase letter, " +
"and is followed by any combination of letters, numbers and underscores.", e.message
end
diff --git a/actionview/test/template/url_helper_test.rb b/actionview/test/template/url_helper_test.rb
index e0678ae1f7..0d6f31af9b 100644
--- a/actionview/test/template/url_helper_test.rb
+++ b/actionview/test/template/url_helper_test.rb
@@ -493,8 +493,8 @@ class UrlHelperTest < ActiveSupport::TestCase
def test_mail_with_options
assert_dom_equal(
- %{<a href="mailto:me@example.com?cc=ccaddress%40example.com&amp;bcc=bccaddress%40example.com&amp;body=This%20is%20the%20body%20of%20the%20message.&amp;subject=This%20is%20an%20example%20email">My email</a>},
- mail_to("me@example.com", "My email", cc: "ccaddress@example.com", bcc: "bccaddress@example.com", subject: "This is an example email", body: "This is the body of the message.")
+ %{<a href="mailto:me@example.com?cc=ccaddress%40example.com&amp;bcc=bccaddress%40example.com&amp;body=This%20is%20the%20body%20of%20the%20message.&amp;subject=This%20is%20an%20example%20email&amp;reply-to=foo%40bar.com">My email</a>},
+ mail_to("me@example.com", "My email", cc: "ccaddress@example.com", bcc: "bccaddress@example.com", subject: "This is an example email", body: "This is the body of the message.", reply_to: "foo@bar.com")
)
end