aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb11
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb3
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb9
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb5
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb12
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb5
-rw-r--r--actionpack/test/dispatch/routing_test.rb18
-rw-r--r--actionpack/test/template/form_helper_test.rb20
-rw-r--r--actionpack/test/template/html-scanner/sanitizer_test.rb18
-rw-r--r--activemodel/lib/active_model/lint.rb2
-rw-r--r--activemodel/lib/active_model/naming.rb36
-rw-r--r--activemodel/test/cases/attribute_methods_test.rb10
-rw-r--r--activerecord/lib/active_record/coders/yaml_column.rb8
-rw-r--r--activerecord/lib/active_record/schema_dumper.rb2
-rw-r--r--activerecord/test/cases/coders/yaml_column_test.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/class/delegating_attributes.rb2
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb6
-rw-r--r--activesupport/test/inflector_test_cases.rb4
-rw-r--r--railties/lib/rails/paths.rb101
-rw-r--r--railties/test/paths_test.rb2
21 files changed, 198 insertions, 85 deletions
diff --git a/Gemfile b/Gemfile
index b19f532b87..acfb1c8e80 100644
--- a/Gemfile
+++ b/Gemfile
@@ -22,8 +22,6 @@ end
# it being automatically loaded by sprockets
gem 'uglifier', '>= 1.0.3', :require => false
-gem 'sprockets-rails', :git => "git://github.com/rails/sprockets-rails.git"
-
gem 'rake', '>= 0.8.7'
gem 'mocha', '>= 0.9.8'
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
index 24ffc28710..e9b50ff8ce 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/sanitizer.rb
@@ -5,6 +5,7 @@ require 'active_support/core_ext/class/attribute'
module HTML
class Sanitizer
def sanitize(text, options = {})
+ validate_options(options)
return text unless sanitizeable?(text)
tokenize(text, options).join
end
@@ -27,6 +28,16 @@ module HTML
def process_node(node, result, options)
result << node.to_s
end
+
+ def validate_options(options)
+ if options[:tags] && !options[:tags].is_a?(Enumerable)
+ raise ArgumentError, "You should pass :tags as an Enumerable"
+ end
+
+ if options[:attributes] && !options[:attributes].is_a?(Enumerable)
+ raise ArgumentError, "You should pass :attributes as an Enumerable"
+ end
+ end
end
class FullSanitizer < Sanitizer
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 8ebf870b95..a4866f5a8f 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -59,7 +59,8 @@ module ActionDispatch
end
def set_session(env, sid, session_data, options)
- session_data.merge("session_id" => sid)
+ session_data["session_id"] = sid
+ session_data
end
def set_cookie(env, session_id, cookie)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index cdc29fb304..20cdf67cf0 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -880,17 +880,18 @@ module ActionDispatch
# CANONICAL_ACTIONS holds all actions that does not need a prefix or
# a path appended since they fit properly in their scope level.
VALID_ON_OPTIONS = [:new, :collection, :member]
- RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except]
+ RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except, :param]
CANONICAL_ACTIONS = %w(index create new show update destroy)
class Resource #:nodoc:
- attr_reader :controller, :path, :options
+ attr_reader :controller, :path, :options, :param
def initialize(entities, options = {})
@name = entities.to_s
@path = (options[:path] || @name).to_s
@controller = (options[:controller] || @name).to_s
@as = options[:as]
+ @param = options[:param] || :id
@options = options
end
@@ -935,7 +936,7 @@ module ActionDispatch
alias :collection_scope :path
def member_scope
- "#{path}/:id"
+ "#{path}/:#{param}"
end
def new_scope(new_path)
@@ -943,7 +944,7 @@ module ActionDispatch
end
def nested_scope
- "#{path}/:#{singular}_id"
+ "#{path}/:#{singular}_#{param}"
end
end
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 2bfc6371f5..45e5a862b6 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -977,7 +977,10 @@ module ActionView
# Returns the id attribute for the input tag.
# => "post_written_on_1i"
def input_id_from_type(type)
- input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
+ id = input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
+ id = @options[:namespace] + '_' + id if @options[:namespace]
+
+ id
end
# Given an ordering of datetime components, create the selection HTML
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 43d5cf1471..6219a7a924 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -9,6 +9,7 @@ require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/string/output_safety'
require 'active_support/core_ext/array/extract_options'
+require 'active_support/deprecation'
module ActionView
# = Action View Form Helpers
@@ -22,7 +23,7 @@ module ActionView
# being routed to the appropriate controller action (with the appropriate <tt>:id</tt>
# parameter in the case of an existing resource), (ii) input fields should
# be named in such a way that in the controller their values appear in the
- # appropriate places within the +params+ hash, and (iii) for an existing record,
+ # appropriate places within the +params+ hash, and (iii) for an existing record,
# when the form is initially displayed, input fields corresponding to attributes
# of the resource should show the current values of those attributes.
#
@@ -156,7 +157,7 @@ module ActionView
# if <tt>:person</tt> also happens to be the name of an instance variable
# <tt>@person</tt>, the default value of the field shown when the form is
# initially displayed (e.g. in the situation where you are editing an
- # existing record) will be the value of the corresponding attribute of
+ # existing record) will be the value of the corresponding attribute of
# <tt>@person</tt>.
#
# The rightmost argument to +form_for+ is an
@@ -1057,7 +1058,12 @@ module ActionView
self
end
- def initialize(object_name, object, template, options)
+ def initialize(object_name, object, template, options, block=nil)
+ if block
+ ActiveSupport::Deprecation.warn(
+ "Giving a block to FormBuilder is deprecated and has no effect anymore.")
+ end
+
@nested_child_index = {}
@object_name, @object, @template, @options = object_name, object, template, options
@parent_builder = options[:parent_builder]
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 29f556502b..4a641fada3 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -334,7 +334,7 @@ module ActionView
remote = html_options.delete('remote')
method = html_options.delete('method').to_s
- method_tag = %w{patch put delete}.include?(method) ? method_tag(method) : ""
+ method_tag = %w{patch put delete}.include?(method) ? method_tag(method) : ''.html_safe
form_method = method == 'get' ? 'get' : 'post'
form_options = html_options.delete('form') || {}
@@ -347,7 +347,8 @@ module ActionView
html_options = convert_options_to_data_attributes(options, html_options)
html_options.merge!("type" => "submit", "value" => name || url)
- "#{tag(:form, form_options, true)}<div>#{method_tag}#{tag("input", html_options)}#{request_token_tag}</div></form>".html_safe
+ inner_tags = method_tag.safe_concat tag('input', html_options).safe_concat request_token_tag
+ content_tag('form', content_tag('div', inner_tags), form_options)
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 700666600b..cc4279d9dd 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -475,6 +475,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get :preview, :on => :member
end
+ resources :profiles, :param => :username do
+ get :details, :on => :member
+ resources :messages
+ end
+
scope :as => "routes" do
get "/c/:id", :as => :collision, :to => "collision#show"
get "/collision", :to => "collision#show"
@@ -2183,6 +2188,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal "/posts/1/admin", post_admin_root_path(:post_id => '1')
end
+ def test_custom_param
+ get '/profiles/bob'
+ assert_equal 'profiles#show', @response.body
+ assert_equal 'bob', @request.params[:username]
+
+ get '/profiles/bob/details'
+ assert_equal 'bob', @request.params[:username]
+
+ get '/profiles/bob/messages/34'
+ assert_equal 'bob', @request.params[:profile_username]
+ assert_equal '34', @request.params[:id]
+ end
+
private
def with_https
old_https = https?
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 2bdb54bd5e..c5a32635f8 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -1063,6 +1063,14 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
+ def test_form_for_with_namespace_with_date_select
+ form_for(@post, :namespace => 'namespace') do |f|
+ concat f.date_select(:written_on)
+ end
+
+ assert_select 'select#namespace_post_written_on_1i'
+ end
+
def test_form_for_with_namespace_with_label
form_for(@post, :namespace => 'namespace') do |f|
concat f.label(:title)
@@ -2223,6 +2231,18 @@ class FormHelperTest < ActionView::TestCase
assert_equal "fields", output
end
+ def test_form_builder_block_argument_deprecation
+ builder_class = Class.new(ActionView::Helpers::FormBuilder) do
+ def initialize(object_name, object, template, options, block)
+ super
+ end
+ end
+
+ assert_deprecated(/Giving a block to FormBuilder is deprecated and has no effect anymore/) do
+ builder_class.new(:foo, nil, nil, {}, proc {})
+ end
+ end
+
protected
def hidden_fields(method = nil)
diff --git a/actionpack/test/template/html-scanner/sanitizer_test.rb b/actionpack/test/template/html-scanner/sanitizer_test.rb
index 32c655c5fd..324caef224 100644
--- a/actionpack/test/template/html-scanner/sanitizer_test.rb
+++ b/actionpack/test/template/html-scanner/sanitizer_test.rb
@@ -125,6 +125,24 @@ class SanitizerTest < ActionController::TestCase
assert_equal(text, sanitizer.sanitize(text, :attributes => ['foo']))
end
+ def test_should_raise_argument_error_if_tags_is_not_enumerable
+ sanitizer = HTML::WhiteListSanitizer.new
+ e = assert_raise(ArgumentError) do
+ sanitizer.sanitize('', :tags => 'foo')
+ end
+
+ assert_equal "You should pass :tags as an Enumerable", e.message
+ end
+
+ def test_should_raise_argument_error_if_attributes_is_not_enumerable
+ sanitizer = HTML::WhiteListSanitizer.new
+ e = assert_raise(ArgumentError) do
+ sanitizer.sanitize('', :attributes => 'foo')
+ end
+
+ assert_equal "You should pass :attributes as an Enumerable", e.message
+ end
+
[%w(img src), %w(a href)].each do |(tag, attr)|
define_method "test_should_strip_#{attr}_attribute_in_#{tag}_with_bad_protocols" do
assert_sanitized %(<#{tag} #{attr}="javascript:bang" title="1">boo</#{tag}>), %(<#{tag} title="1">boo</#{tag}>)
diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb
index a10fdefd1a..210f9a9468 100644
--- a/activemodel/lib/active_model/lint.rb
+++ b/activemodel/lib/active_model/lint.rb
@@ -78,7 +78,7 @@ module ActiveModel
def test_model_naming
assert model.class.respond_to?(:model_name), "The model should respond to model_name"
model_name = model.class.model_name
- assert_kind_of String, model_name
+ assert_kind_of ActiveModel::Name, model_name
assert_kind_of String, model_name.human
assert_kind_of String, model_name.singular
assert_kind_of String, model_name.plural
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
index b22d9539b0..adf000e53c 100644
--- a/activemodel/lib/active_model/naming.rb
+++ b/activemodel/lib/active_model/naming.rb
@@ -2,36 +2,40 @@ require 'active_support/inflector'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/module/introspection'
require 'active_support/core_ext/module/deprecation'
+require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/object/blank'
module ActiveModel
- class Name < String
+ class Name
+ include Comparable
+
attr_reader :singular, :plural, :element, :collection,
- :singular_route_key, :route_key, :param_key, :i18n_key
+ :singular_route_key, :route_key, :param_key, :i18n_key,
+ :name
alias_method :cache_key, :collection
- def initialize(klass, namespace = nil, name = nil)
- name ||= klass.name
+ delegate :==, :===, :<=>, :=~, :"!~", :eql?, :to_s,
+ :to_str, :to => :name
- raise ArgumentError, "Class name cannot be blank. You need to supply a name argument when anonymous class given" if name.blank?
+ def initialize(klass, namespace = nil, name = nil)
+ @name = name || klass.name
- super(name)
+ raise ArgumentError, "Class name cannot be blank. You need to supply a name argument when anonymous class given" if @name.blank?
- @unnamespaced = self.sub(/^#{namespace.name}::/, '') if namespace
+ @unnamespaced = @name.sub(/^#{namespace.name}::/, '') if namespace
@klass = klass
- @singular = _singularize(self).freeze
- @plural = ActiveSupport::Inflector.pluralize(@singular).freeze
- @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze
- @human = ActiveSupport::Inflector.humanize(@element).freeze
- @collection = ActiveSupport::Inflector.tableize(self).freeze
- @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze
- @i18n_key = self.underscore.to_sym
+ @singular = _singularize(@name)
+ @plural = ActiveSupport::Inflector.pluralize(@singular)
+ @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(@name))
+ @human = ActiveSupport::Inflector.humanize(@element)
+ @collection = ActiveSupport::Inflector.tableize(@name)
+ @param_key = (namespace ? _singularize(@unnamespaced) : @singular)
+ @i18n_key = @name.underscore.to_sym
@route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural.dup)
- @singular_route_key = ActiveSupport::Inflector.singularize(@route_key).freeze
+ @singular_route_key = ActiveSupport::Inflector.singularize(@route_key)
@route_key << "_index" if @plural == @singular
- @route_key.freeze
end
# Transform the model name into a more humane format, using I18n. By default,
diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb
index 9406328d3e..34298d31c2 100644
--- a/activemodel/test/cases/attribute_methods_test.rb
+++ b/activemodel/test/cases/attribute_methods_test.rb
@@ -188,6 +188,12 @@ class AttributeMethodsTest < ActiveModel::TestCase
assert_raises(NoMethodError) { m.protected_method }
end
+ class ClassWithProtected
+ protected
+ def protected_method
+ end
+ end
+
test 'should not interfere with respond_to? if the attribute has a private/protected method' do
m = ModelWithAttributes2.new
m.attributes = { 'private_method' => '<3', 'protected_method' => 'O_o' }
@@ -195,9 +201,11 @@ class AttributeMethodsTest < ActiveModel::TestCase
assert !m.respond_to?(:private_method)
assert m.respond_to?(:private_method, true)
+ c = ClassWithProtected.new
+
# This is messed up, but it's how Ruby works at the moment. Apparently it will be changed
# in the future.
- assert m.respond_to?(:protected_method)
+ assert_equal c.respond_to?(:protected_method), m.respond_to?(:protected_method)
assert m.respond_to?(:protected_method, true)
end
diff --git a/activerecord/lib/active_record/coders/yaml_column.rb b/activerecord/lib/active_record/coders/yaml_column.rb
index 77af540c3e..66a0c83c41 100644
--- a/activerecord/lib/active_record/coders/yaml_column.rb
+++ b/activerecord/lib/active_record/coders/yaml_column.rb
@@ -15,7 +15,13 @@ module ActiveRecord
end
def dump(obj)
- YAML.dump(obj) unless obj.nil?
+ return if obj.nil?
+
+ unless obj.is_a?(object_class)
+ raise SerializationTypeMismatch,
+ "Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
+ end
+ YAML.dump obj
end
def load(yaml)
diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb
index dcbd165e58..95fd33c1d1 100644
--- a/activerecord/lib/active_record/schema_dumper.rb
+++ b/activerecord/lib/active_record/schema_dumper.rb
@@ -40,7 +40,7 @@ module ActiveRecord
def header(stream)
define_params = @version ? ":version => #{@version}" : ""
- if stream.respond_to?(:external_encoding)
+ if stream.respond_to?(:external_encoding) && stream.external_encoding
stream.puts "# encoding: #{stream.external_encoding.name}"
end
diff --git a/activerecord/test/cases/coders/yaml_column_test.rb b/activerecord/test/cases/coders/yaml_column_test.rb
index c7dcc21809..b874adc081 100644
--- a/activerecord/test/cases/coders/yaml_column_test.rb
+++ b/activerecord/test/cases/coders/yaml_column_test.rb
@@ -9,6 +9,13 @@ module ActiveRecord
assert_equal Object, coder.object_class
end
+ def test_type_mismatch_on_different_classes_on_dump
+ coder = YAMLColumn.new(Array)
+ assert_raises(SerializationTypeMismatch) do
+ coder.dump("a")
+ end
+ end
+
def test_type_mismatch_on_different_classes
coder = YAMLColumn.new(Array)
assert_raises(SerializationTypeMismatch) do
diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
index 29bf7c0f3d..0634f20e3c 100644
--- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/object/blank'
-require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/remove_method'
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index 48ea5653c7..4cebad742f 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -1,3 +1,5 @@
+# encoding: utf-8
+
require 'active_support/inflector/inflections'
module ActiveSupport
@@ -112,7 +114,7 @@ module ActiveSupport
# "TheManWithoutAPast".titleize # => "The Man Without A Past"
# "raiders_of_the_lost_ark".titleize # => "Raiders Of The Lost Ark"
def titleize(word)
- humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
+ humanize(underscore(word)).gsub(/\b(['’`]?[a-z])/) { $1.capitalize }
end
# Create the name of a table like Rails does for models to table names. This method
@@ -209,7 +211,7 @@ module ActiveSupport
def constantize(camel_cased_word) #:nodoc:
names = camel_cased_word.split('::')
names.shift if names.empty? || names.first.empty?
-
+
names.inject(Object) do |constant, name|
constant.const_get(name, false)
end
diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb
index 809b8b46c9..879c3c1125 100644
--- a/activesupport/test/inflector_test_cases.rb
+++ b/activesupport/test/inflector_test_cases.rb
@@ -220,7 +220,9 @@ module InflectorTestCases
'Actionwebservice' => 'Actionwebservice',
"david's code" => "David's Code",
"David's code" => "David's Code",
- "david's Code" => "David's Code"
+ "david's Code" => "David's Code",
+ "Fred’s" => "Fred’s",
+ "Fred`s" => "Fred`s"
}
OrdinalNumbers = {
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index 4ac3d88dc2..9730ed16e9 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -16,13 +16,13 @@ module Rails
# path.eager_load? # => true
# path.is_a?(Rails::Paths::Path) # => true
#
- # The +Path+ object is simply an array and allows you to easily add extra paths:
+ # The +Path+ object is simply an enumerable and allows you to easily add extra paths:
#
- # path.is_a?(Array) # => true
- # path.inspect # => ["app/controllers"]
+ # path.is_a?(Enumerable) # => true
+ # path.to_ary.inspect # => ["app/controllers"]
#
# path << "lib/controllers"
- # path.inspect # => ["app/controllers", "lib/controllers"]
+ # path.to_ary.inspect # => ["app/controllers", "lib/controllers"]
#
# Notice that when you add a path using +add+, the path object created already
# contains the path with the same path value given to +add+. In some situations,
@@ -43,25 +43,40 @@ module Rails
# root["app/controllers"].existent # => ["/rails/app/controllers"]
#
# Check the <tt>Rails::Paths::Path</tt> documentation for more information.
- class Root < ::Hash
+ class Root
attr_accessor :path
def initialize(path)
raise "Argument should be a String of the physical root path" if path.is_a?(Array)
@current = nil
@path = path
- @root = self
- super()
+ @root = {}
end
def []=(path, value)
- value = Path.new(self, path, value) unless value.is_a?(Path)
- super(path, value)
+ value = Path.new(self, path, [value].flatten) unless value.is_a?(Path)
+ @root[path] = value
end
def add(path, options={})
with = options[:with] || path
- self[path] = Path.new(self, path, with, options)
+ @root[path] = Path.new(self, path, [with].flatten, options)
+ end
+
+ def [](path)
+ @root[path]
+ end
+
+ def values
+ @root.values
+ end
+
+ def keys
+ @root.keys
+ end
+
+ def values_at(*list)
+ @root.values_at(*list)
end
def all_paths
@@ -100,14 +115,14 @@ module Rails
end
end
- class Path < Array
+ class Path
+ include Enumerable
+
attr_reader :path
attr_accessor :glob
- def initialize(root, current, *paths)
- options = paths.last.is_a?(::Hash) ? paths.pop : {}
- super(paths.flatten)
-
+ def initialize(root, current, paths, options = {})
+ @paths = paths
@current = current
@root = root
@glob = options[:glob]
@@ -148,6 +163,27 @@ module Rails
RUBY
end
+ def each(&block)
+ @paths.each &block
+ end
+
+ def <<(path)
+ @paths << path
+ end
+ alias :push :<<
+
+ def concat(paths)
+ @paths.concat paths
+ end
+
+ def unshift(path)
+ @paths.unshift path
+ end
+
+ def to_ary
+ @paths
+ end
+
# Expands all paths against the root and return all unique values.
def expanded
raise "You need to set a path root" unless @root.path
@@ -156,26 +192,10 @@ module Rails
each do |p|
path = File.expand_path(p, @root.path)
- if @glob
- if File.directory? path
- result.concat expand_dir(path, @glob)
- else
- # FIXME: I think we can remove this branch, but I'm not sure.
- # Say the filesystem has this file:
- #
- # /tmp/foobar
- #
- # and someone adds this path:
- #
- # /tmp/foo
- #
- # with a glob of "*", then this function will return
- #
- # /tmp/foobar
- #
- # We need to figure out if that is desired behavior.
- result.concat expand_file(path, @glob)
- end
+ if @glob && File.directory?(path)
+ result.concat Dir.chdir(path) {
+ Dir.glob(@glob).map { |file| File.join path, file }.sort
+ }
else
result << path
end
@@ -195,17 +215,6 @@ module Rails
end
alias to_a expanded
-
- private
- def expand_file(path, glob)
- Dir[File.join(path, glob)].sort
- end
-
- def expand_dir(path, glob)
- Dir.chdir(path) do
- Dir.glob(@glob).map { |file| File.join path, file }.sort
- end
- end
end
end
end
diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb
index c0f3887263..f30bbbc6f5 100644
--- a/railties/test/paths_test.rb
+++ b/railties/test/paths_test.rb
@@ -22,7 +22,7 @@ class PathsTest < ActiveSupport::TestCase
root = Rails::Paths::Root.new(nil)
root.add "app"
root.path = "/root"
- assert_equal ["app"], root["app"]
+ assert_equal ["app"], root["app"].to_ary
assert_equal ["/root/app"], root["app"].to_a
end