From 626881577949ffce8370e097aa3efb3fec47d4f5 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Sep 2010 12:40:01 -0300 Subject: Initialize @view_context_class and cache view_context_class value. --- actionpack/lib/abstract_controller/rendering.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 5d9b35d297..918def3e81 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -66,7 +66,7 @@ module AbstractController attr_writer :view_context_class def view_context_class - @view_context_class || self.class.view_context_class + @view_context_class ||= self.class.view_context_class end def initialize(*) -- cgit v1.2.3 From bc0e7f4e374d4f72d1254f51e8c116f358826855 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Sep 2010 11:10:38 -0300 Subject: Test correct method behaviour. --- actionpack/test/controller/capture_test.rb | 6 +++++- actionpack/test/fixtures/test/proper_block_detection.erb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/actionpack/test/controller/capture_test.rb b/actionpack/test/controller/capture_test.rb index eb426e855b..d78acb8ce8 100644 --- a/actionpack/test/controller/capture_test.rb +++ b/actionpack/test/controller/capture_test.rb @@ -25,6 +25,10 @@ class CaptureController < ActionController::Base render :layout => "talk_from_action" end + def proper_block_detection + @todo = "some todo" + end + def rescue_action(e) raise end end @@ -66,8 +70,8 @@ class CaptureTest < ActionController::TestCase end def test_proper_block_detection - @todo = "some todo" get :proper_block_detection + assert_equal "some todo", @response.body end private diff --git a/actionpack/test/fixtures/test/proper_block_detection.erb b/actionpack/test/fixtures/test/proper_block_detection.erb index 23564dbcee..b55efbb25d 100644 --- a/actionpack/test/fixtures/test/proper_block_detection.erb +++ b/actionpack/test/fixtures/test/proper_block_detection.erb @@ -1 +1 @@ -<%= @todo %> +<%= @todo %> \ No newline at end of file -- cgit v1.2.3 From 152580ee00205b42de45950d69349c6eab6dd291 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Sep 2010 11:37:08 -0300 Subject: Don't try to interpolate string if there's no interpolation point at all. --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0cb02c5b80..189da138d8 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -349,7 +349,7 @@ module ActionDispatch options = args.last.is_a?(Hash) ? args.pop : {} path = args.shift || block - path_proc = path.is_a?(Proc) ? path : proc { |params| params.empty? ? path : (path % params) } + path_proc = path.is_a?(Proc) ? path : proc { |params| (params.empty? || !path.match(/%{\w*}/)) ? path : (path % params) } status = options[:status] || 301 lambda do |env| -- cgit v1.2.3 From 8823b85010a217df555b981a453384e24ce7da47 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Sep 2010 12:13:58 -0300 Subject: Remove redundant conditional. --- actionpack/lib/action_dispatch/testing/assertions/response.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index 10b122557a..e381b9abdf 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -84,11 +84,7 @@ module ActionDispatch when %r{^\w[\w\d+.-]*:.*} fragment when String - if fragment =~ %r{^\w[\w\d+.-]*:.*} - fragment - else - @request.protocol + @request.host_with_port + fragment - end + @request.protocol + @request.host_with_port + fragment when :back raise RedirectBackError unless refer = @request.headers["Referer"] refer -- cgit v1.2.3 From c37800aae123d21d53a49433cac2e0a2479c6bbd Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Sep 2010 12:55:43 -0300 Subject: _ is not a valid scheme name character, \w includes it and also is redundant with \d. 'The scheme name consists of a letter followed by any combination of letters, digits, and the plus ("+"), period ("."), or hyphen ("-") characters; and is terminated by a colon (":").' --- actionpack/lib/action_dispatch/testing/assertions/response.rb | 2 +- actionpack/test/controller/action_pack_assertions_test.rb | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index e381b9abdf..1558c3ae05 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -81,7 +81,7 @@ module ActionDispatch def normalize_argument_to_redirection(fragment) case fragment - when %r{^\w[\w\d+.-]*:.*} + when %r{^\w[A-Za-z\d+.-]*:.*} fragment when String @request.protocol + @request.host_with_port + fragment diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index d9d258e593..5a8b763717 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -32,6 +32,8 @@ class ActionPackAssertionsController < ActionController::Base def redirect_to_path() redirect_to '/some/path' end + def redirect_invalid_external_route() redirect_to 'ht_tp://www.rubyonrails.org' end + def redirect_to_named_route() redirect_to route_one_url end def redirect_external() redirect_to "http://www.rubyonrails.org"; end @@ -368,6 +370,11 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase end end + def test_redirect_invalid_external_route + process :redirect_invalid_external_route + assert_redirected_to "http://test.hostht_tp://www.rubyonrails.org" + end + def test_redirected_to_url_full_url process :redirect_to_path assert_redirected_to 'http://test.host/some/path' -- cgit v1.2.3 From 6371e5b99f933ebe462784b5272fdf12e9602e5a Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Sep 2010 14:35:24 -0300 Subject: We can't assign @view_context_class here, define super() in test instead if we want to avoid warnings. --- actionpack/lib/abstract_controller/rendering.rb | 2 +- actionpack/test/controller/filters_test.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 918def3e81..5d9b35d297 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -66,7 +66,7 @@ module AbstractController attr_writer :view_context_class def view_context_class - @view_context_class ||= self.class.view_context_class + @view_context_class || self.class.view_context_class end def initialize(*) diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index d13ebc705a..dfc90943e1 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -314,6 +314,7 @@ class FilterTest < ActionController::TestCase def initialize @@execution_log = "" + super() end before_filter { |c| c.class.execution_log << " before procfilter " } -- cgit v1.2.3 From 61cf11247bfdb243625cda93fb08afaacebe1381 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 29 Sep 2010 13:23:05 -0300 Subject: Use detect instead select to avoid "sh: [mysqldump]: command not found". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/examples/performance.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/examples/performance.rb b/activerecord/examples/performance.rb index ccd60c6c69..c4ce361b5d 100644 --- a/activerecord/examples/performance.rb +++ b/activerecord/examples/performance.rb @@ -88,7 +88,7 @@ else ) end - mysqldump_bin = %w[mysqldump mysqldump5].select { |bin| `which #{bin}`.length > 0 } + mysqldump_bin = %w[mysqldump mysqldump5].detect { |bin| `which #{bin}`.length > 0 } `#{mysqldump_bin} -u #{conn[:username]} #{"-p#{conn[:password]}" unless conn[:password].blank?} #{conn[:database]} exhibits users > #{sqlfile}` end -- cgit v1.2.3 From 1c0be7baac8e736e2ddd659ac2d6ef1845f756c7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 11:34:51 -0700 Subject: fixing space error --- actionpack/test/controller/log_subscriber_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index b5bc0e9e9a..10873708fe 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -23,7 +23,7 @@ module Another def with_fragment_cache render :inline => "<%= cache('foo'){ 'bar' } %>" end - + def with_fragment_cache_and_percent_in_key render :inline => "<%= cache('foo%bar'){ 'Contains % sign in key' } %>" end -- cgit v1.2.3 From a5f8f5908116081a3461409eda53e62d997d5b40 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 11:47:27 -0700 Subject: dry up action_methods --- actionpack/lib/abstract_controller/base.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 85270d84d8..ce88803a9c 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -61,13 +61,13 @@ module AbstractController def action_methods @action_methods ||= begin # All public instance methods of this class, including ancestors - methods = public_instance_methods(true).map { |m| m.to_s }.to_set - + methods = (public_instance_methods(true) - # Except for public instance methods of Base and its ancestors - internal_methods.map { |m| m.to_s } + + internal_methods + # Be sure to include shadowed public instance methods of this class - public_instance_methods(false).map { |m| m.to_s } - + public_instance_methods(false)).map { |x| x.to_s } - # And always exclude explicitly hidden actions - hidden_actions + hidden_actions.to_a # Clear out AS callback method pollution methods.reject { |method| method =~ /_one_time_conditions/ } -- cgit v1.2.3 From 1d9a219307ec5cc506635ee0bd3d368955d5b4a6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 11:53:34 -0700 Subject: oops, missed a uniq --- actionpack/lib/abstract_controller/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index ce88803a9c..f9f6eb945e 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -65,7 +65,7 @@ module AbstractController # Except for public instance methods of Base and its ancestors internal_methods + # Be sure to include shadowed public instance methods of this class - public_instance_methods(false)).map { |x| x.to_s } - + public_instance_methods(false)).uniq.map { |x| x.to_s } - # And always exclude explicitly hidden actions hidden_actions.to_a -- cgit v1.2.3 From 4d7b2ee52481078228ac0283024a72b7d80a39db Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 15:07:33 -0700 Subject: dry up method missing --- actionmailer/lib/action_mailer/base.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 6ae3940e6d..2901add71d 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -421,11 +421,8 @@ module ActionMailer #:nodoc: end def method_missing(method, *args) #:nodoc: - if action_methods.include?(method.to_s) - new(method, *args).message - else - super - end + return super unless respond_to?(method) + new(method, *args).message end end -- cgit v1.2.3 From e8c9cac1c3c3e04481418e6dbe5b0eb479c70dae Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 15:16:44 -0700 Subject: self is implied, so remove self --- actionmailer/lib/action_mailer/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 2901add71d..0bf60a2c24 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -409,7 +409,7 @@ module ActionMailer #:nodoc: protected def set_payload_for_mail(payload, mail) #:nodoc: - payload[:mailer] = self.name + payload[:mailer] = name payload[:message_id] = mail.message_id payload[:subject] = mail.subject payload[:to] = mail.to -- cgit v1.2.3 From 2437356cdacf2b774147b4da38de1d137e0a8b26 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 15:37:38 -0700 Subject: removing lollerject --- actionpack/lib/action_controller/metal/http_authentication.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 6a7e170306..53444f31a8 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -214,7 +214,7 @@ module ActionController def encode_credentials(http_method, credentials, password, password_is_ha1) credentials[:response] = expected_response(http_method, credentials[:uri], credentials, password, password_is_ha1) - "Digest " + credentials.sort_by {|x| x[0].to_s }.inject([]) {|a, v| a << "#{v[0]}='#{v[1]}'" }.join(', ') + "Digest " + credentials.sort_by {|x| x[0].to_s }.map {|v| "#{v[0]}='#{v[1]}'" }.join(', ') end def decode_credentials_header(request) -- cgit v1.2.3 From 3f88f26d1e17277dfa85a22bb01c1db558b6addf Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 15:41:06 -0700 Subject: removing more lolinject --- .../lib/action_controller/metal/http_authentication.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 53444f31a8..e0c5eaca84 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -423,14 +423,13 @@ module ActionController # Returns nil if no token is found. def token_and_options(request) if header = request.authorization.to_s[/^Token (.*)/] - values = $1.split(','). - inject({}) do |memo, value| - value.strip! # remove any spaces between commas and values - key, value = value.split(/\=\"?/) # split key=value pairs - value.chomp!('"') # chomp trailing " in value - value.gsub!(/\\\"/, '"') # unescape remaining quotes - memo.update(key => value) - end + values = Hash[$1.split(',').map do |value| + value.strip! # remove any spaces between commas and values + key, value = value.split(/\=\"?/) # split key=value pairs + value.chomp!('"') # chomp trailing " in value + value.gsub!(/\\\"/, '"') # unescape remaining quotes + [key, value] + end] [values.delete("token"), values.with_indifferent_access] end end -- cgit v1.2.3 From ab0d216b670e13d6f65e82dfdeb3d08c75101274 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 15:43:27 -0700 Subject: reduce function calls on Array --- actionpack/lib/action_controller/metal/http_authentication.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index e0c5eaca84..547cec7081 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -441,9 +441,8 @@ module ActionController # # Returns String. def encode_credentials(token, options = {}) - values = ["token=#{token.to_s.inspect}"] - options.each do |key, value| - values << "#{key}=#{value.to_s.inspect}" + values = ["token=#{token.to_s.inspect}"] + options.map do |key, value| + "#{key}=#{value.to_s.inspect}" end "Token #{values * ", "}" end -- cgit v1.2.3 From 78ac9c2be738ff48c847a26ae8fc4464e881e184 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 16:09:58 -0700 Subject: dry up method checking in the request object --- actionpack/lib/action_dispatch/http/request.rb | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 7a28228817..09d6ba8223 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -54,11 +54,7 @@ module ActionDispatch # the application should use), this \method returns the overridden # value, not the original. def request_method - @request_method ||= begin - method = env["REQUEST_METHOD"] - HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") - method - end + @request_method ||= check_method(env["REQUEST_METHOD"]) end # Returns a symbol form of the #request_method @@ -70,11 +66,7 @@ module ActionDispatch # even if it was overridden by middleware. See #request_method for # more information. def method - @method ||= begin - method = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'] - HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") - method - end + @method ||= check_method(env["rack.methodoverride.original_method"] || env['REQUEST_METHOD']) end # Returns a symbol form of the #method @@ -246,5 +238,12 @@ module ActionDispatch def local? LOCALHOST.any? { |local_ip| local_ip === remote_addr && local_ip === remote_ip } end + + private + + def check_method(name) + HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") + name + end end end -- cgit v1.2.3 From 2eef53b163353898a0f96d559e3f80600eb6ba15 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 16:17:56 -0700 Subject: removing useless code --- actionpack/lib/action_view/helpers/form_options_helper.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 83434a9340..7d6aca0470 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -297,7 +297,6 @@ module ActionView def options_for_select(container, selected = nil) return container if String === container - container = container.to_a if Hash === container selected, disabled = extract_selected_and_disabled(selected).map do | r | Array.wrap(r).map(&:to_s) end -- cgit v1.2.3 From a40e3c1a9604ab3737ad2465c8f6a6db0fe0cc78 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 16:40:47 -0700 Subject: removing crazy finalizer code until there is proof that we need it --- actionpack/lib/action_view/template.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index a999a0b7d7..405e1736ba 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -101,14 +101,6 @@ module ActionView attr_reader :source, :identifier, :handler, :virtual_path, :formats, :original_encoding - Finalizer = proc do |method_name, mod| - proc do - mod.module_eval do - remove_possible_method method_name - end - end - end - def initialize(source, identifier, handler, details) @source = source @identifier = identifier @@ -253,7 +245,6 @@ module ActionView begin mod.module_eval(source, identifier, 0) - ObjectSpace.define_finalizer(self, Finalizer[method_name, mod]) method_name rescue Exception => e # errors from template code -- cgit v1.2.3 From 299e9f692798f502bd74d16655b611bccf520620 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 29 Sep 2010 14:17:59 -0400 Subject: no need of nil check --- .../active_record/associations/belongs_to_polymorphic_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb index 38454ec242..e429806b0c 100644 --- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb @@ -39,7 +39,7 @@ module ActiveRecord def set_inverse_instance(record, instance) return if record.nil? || !we_can_set_the_inverse_on_this?(record) inverse_relationship = @reflection.polymorphic_inverse_of(record.class) - unless inverse_relationship.nil? + if inverse_relationship record.send(:"set_#{inverse_relationship.name}_target", instance) end end -- cgit v1.2.3 From 8efdffeda31b520b9b534dc614c6039404288c26 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 30 Sep 2010 02:22:00 +0800 Subject: no need of nil check --- actionpack/lib/action_controller/test_case.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 70a5de7f30..1af75fc2d7 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -394,7 +394,7 @@ module ActionController parameters ||= {} @request.assign_parameters(@routes, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) - @request.session = ActionController::TestSession.new(session) unless session.nil? + @request.session = ActionController::TestSession.new(session) if session @request.session["flash"] = @request.flash.update(flash || {}) @request.session["flash"].sweep -- cgit v1.2.3 From 692f5184c405b3b0f9b6ac02c37aaefb7d2ffb62 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 30 Sep 2010 02:24:47 +0800 Subject: no need to check for nil? --- actionpack/lib/action_dispatch/middleware/session/abstract_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index ea49b30630..db0187c015 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -165,7 +165,7 @@ module ActionDispatch return response unless value cookie = { :value => value } - unless options[:expire_after].nil? + if options[:expire_after] cookie[:expires] = Time.now + options.delete(:expire_after) end -- cgit v1.2.3 From 08a08d97dd1307ab9544cc55fbd398c6acdc4c89 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 30 Sep 2010 02:26:22 +0800 Subject: no need to check for nil? --- actionpack/lib/action_view/helpers/form_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index c47fac05ef..cabe272cc7 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1015,7 +1015,7 @@ module ActionView module ClassMethods def value(object, method_name) - object.send method_name unless object.nil? + object.send method_name if object end def value_before_type_cast(object, method_name) @@ -1055,7 +1055,7 @@ module ActionView private def add_default_name_and_id_for_value(tag_value, options) - unless tag_value.nil? + if tag_value pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase specified_id = options["id"] add_default_name_and_id(options) -- cgit v1.2.3 From 618407db56b39a4130e05779339534ae2ebf883e Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 30 Sep 2010 02:27:13 +0800 Subject: another case of extra nil? check --- actionpack/lib/action_view/helpers/text_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 3bc5afc2c4..94348cf9fa 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -365,7 +365,7 @@ module ActionView # <% end %> def current_cycle(name = "default") cycle = get_cycle(name) - cycle.current_value unless cycle.nil? + cycle.current_value if cycle end # Resets a cycle so that it starts from the first element the next time -- cgit v1.2.3 From 396f3a28f175dcdae6fdcd5139b9dd5defde18de Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 30 Sep 2010 02:30:33 +0800 Subject: double negative is not good --- activerecord/lib/active_record/serialization.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb index ad3f7afd6f..398eb1534a 100644 --- a/activerecord/lib/active_record/serialization.rb +++ b/activerecord/lib/active_record/serialization.rb @@ -45,7 +45,7 @@ module ActiveRecord #:nodoc: send(association) end - unless records.nil? + if records association_options = include_has_options ? include_associations[association] : base_only_or_except opts = options.merge(association_options) yield(association, records, opts) -- cgit v1.2.3 From 29c32e832908e13f0e360bbe47c80d5578bffba1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 17:57:39 -0700 Subject: tag value can be false, so nil? check is necessary --- actionpack/lib/action_view/helpers/form_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index cabe272cc7..1836baaf12 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1055,7 +1055,7 @@ module ActionView private def add_default_name_and_id_for_value(tag_value, options) - if tag_value + unless tag_value.nil? pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase specified_id = options["id"] add_default_name_and_id(options) -- cgit v1.2.3 From 7e057d11aa21383394e570d0de8f4d5f3729d024 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 18:23:33 -0700 Subject: fixing regexp warnings --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 189da138d8..0c6e1b37a7 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -349,7 +349,7 @@ module ActionDispatch options = args.last.is_a?(Hash) ? args.pop : {} path = args.shift || block - path_proc = path.is_a?(Proc) ? path : proc { |params| (params.empty? || !path.match(/%{\w*}/)) ? path : (path % params) } + path_proc = path.is_a?(Proc) ? path : proc { |params| (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params) } status = options[:status] || 301 lambda do |env| -- cgit v1.2.3 From 31752f3516e5977b459cc713ae50515b20fda67b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 29 Sep 2010 18:32:51 -0700 Subject: avoid creating a block if possible --- actionpack/lib/action_dispatch/routing/mapper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0c6e1b37a7..0a888505d2 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -345,10 +345,10 @@ module ActionDispatch # Redirect any path to another path: # # match "/stories" => redirect("/posts") - def redirect(*args, &block) + def redirect(*args) options = args.last.is_a?(Hash) ? args.pop : {} - path = args.shift || block + path = args.shift || Proc.new path_proc = path.is_a?(Proc) ? path : proc { |params| (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params) } status = options[:status] || 301 -- cgit v1.2.3 From 69f97f469747777ed1c457715f5361f6b8a0ab7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 30 Sep 2010 07:25:06 +0200 Subject: Use .find here as it is simpler and faster. --- actionpack/lib/action_dispatch/routing/mapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0a888505d2..47aed0273c 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1130,7 +1130,7 @@ module ActionDispatch end candidate = name.select(&:present?).join("_").presence - candidate unless as.nil? && @set.routes.map(&:name).include?(candidate) + candidate unless as.nil? && @set.routes.find { |r| r.name == candidate } end end -- cgit v1.2.3 From 74598fe7e9097484c4029e2731e462c6c82836f9 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 25 Sep 2010 19:02:14 +0200 Subject: Do not overwrite _railtie method on namespace while creating isolated engine or application. In order to run Engine as standalone application, you will need Rails::Application instance in the same namespace that engine one. It's very important to leave _railtie bound to whatever used "namespace" method first. --- railties/lib/rails/engine.rb | 25 +++++++++++++------------ railties/test/railties/engine_test.rb | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 0620b8608e..ababf6a242 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -333,21 +333,22 @@ module Rails def namespace(mod) engine_name(generate_railtie_name(mod)) - _railtie = self name = engine_name - mod.singleton_class.instance_eval do - define_method(:_railtie) do - _railtie - end - - define_method(:table_name_prefix) do - "#{name}_" - end - end - self.routes.default_scope = {:module => name} - self.namespaced = true + + unless mod.respond_to?(:_railtie) + _railtie = self + mod.singleton_class.instance_eval do + define_method(:_railtie) do + _railtie + end + + define_method(:table_name_prefix) do + "#{name}_" + end + end + end end def namespaced? diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index a9dd7d4c1b..17bffe05e1 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -643,5 +643,25 @@ module RailtiesTest Bukkits::Engine.load_seed assert Bukkits::Engine.config.bukkits_seeds_loaded end + + test "using namespace more than once on one module should not overwrite _railtie method" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module AppTemplate + class Engine < ::Rails::Engine + namespace(AppTemplate) + end + end + RUBY + + add_to_config "namespace AppTemplate" + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do end + RUBY + + boot_rails + + assert_equal AppTemplate._railtie, AppTemplate::Engine + end end end -- cgit v1.2.3 From 22b11a41cc764bc0f7b0c0f518a5289230428597 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 25 Sep 2010 19:22:32 +0200 Subject: Allow mounting engines at '/' Without that commit script_name always become '/', which results in paths like //posts/1 instead of /posts/1 --- .../lib/action_dispatch/routing/route_set.rb | 2 +- actionpack/test/dispatch/prefix_generation_test.rb | 93 ++++++++++++++++++---- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 5d18dfe369..99a3019f3a 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -511,7 +511,7 @@ module ActionDispatch end script_name = options.delete(:script_name) - path = (script_name.blank? ? _generate_prefix(options) : script_name).to_s + path = (script_name.blank? ? _generate_prefix(options) : script_name.chomp('/')).to_s path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 26d76557dd..18f28deee4 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -1,8 +1,23 @@ require 'abstract_unit' +require 'rack/test' module TestGenerationPrefix + class Post + extend ActiveModel::Naming + + def to_param + "1" + end + + def self.model_name + klass = "Post" + def klass.name; self end + + ActiveModel::Name.new(klass) + end + end + class WithMountedEngine < ActionDispatch::IntegrationTest - require 'rack/test' include Rack::Test::Methods class BlogEngine @@ -55,21 +70,6 @@ module TestGenerationPrefix # force draw RailsApplication.routes - class Post - extend ActiveModel::Naming - - def to_param - "1" - end - - def self.model_name - klass = "Post" - def klass.name; self end - - ActiveModel::Name.new(klass) - end - end - class ::InsideEngineGeneratingController < ActionController::Base include BlogEngine.routes.url_helpers include RailsApplication.routes.mounted_helpers @@ -253,4 +253,65 @@ module TestGenerationPrefix assert_equal "http://www.example.com/awesome/blog/posts/1", path end end + + class EngineMountedAtRoot < ActionDispatch::IntegrationTest + include Rack::Test::Methods + + class BlogEngine + def self.routes + @routes ||= begin + routes = ActionDispatch::Routing::RouteSet.new + routes.draw do + match "/posts/:id", :to => "posts#show", :as => :post + end + + routes + end + end + + def self.call(env) + env['action_dispatch.routes'] = routes + routes.call(env) + end + end + + class RailsApplication + def self.routes + @routes ||= begin + routes = ActionDispatch::Routing::RouteSet.new + routes.draw do + mount BlogEngine => "/" + end + + routes + end + end + + def self.call(env) + env['action_dispatch.routes'] = routes + routes.call(env) + end + end + + # force draw + RailsApplication.routes + + class ::PostsController < ActionController::Base + include BlogEngine.routes.url_helpers + include RailsApplication.routes.mounted_helpers + + def show + render :text => post_path(:id => params[:id]) + end + end + + def app + RailsApplication + end + + test "generating path inside engine" do + get "/posts/1" + assert_equal "/posts/1", last_response.body + end + end end -- cgit v1.2.3 From ec5d846ac6137e60d81257041e4fde82c0480b32 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sun, 26 Sep 2010 00:17:06 +0200 Subject: Properly reload routes defined in class definition Sometimes it's easier to define routes inside Engine or Application class definition (e.g. one file applications). The problem with such case is that if there is a plugin that has config/routes.rb file, it will trigger routes reload on application. Since routes definition for application is not in config/routes.rb file routes_reloader will fail to reload application's routes properly. With this commit you can pass routes definition as a block to routes method, which will allow to properly reload it: class MyApp::Application < Rails::Application routes do resources :users end end --- .../lib/action_dispatch/routing/route_set.rb | 1 + railties/lib/rails/application.rb | 21 +++++++++--- railties/lib/rails/engine.rb | 7 +++- railties/test/railties/engine_test.rb | 40 ++++++++++++++++++++++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 99a3019f3a..32f41934f1 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -1,6 +1,7 @@ require 'rack/mount' require 'forwardable' require 'active_support/core_ext/object/to_query' +require 'active_support/core_ext/hash/slice' module ActionDispatch module Routing diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 0e85e6d1d5..2db131261c 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -85,13 +85,24 @@ module Rails end def reload_routes! - _routes = self.routes - _routes.disable_clear_and_finalize = true - _routes.clear! + routes_to_reload.each do |_routes, draw_block| + _routes = self.routes + _routes.disable_clear_and_finalize = true + _routes.clear! + _routes.draw(&draw_block) if draw_block + end routes_reloader.paths.each { |path| load(path) } - ActiveSupport.on_load(:action_controller) { _routes.finalize! } + routes_to_reload.each do |_routes, draw_block| + ActiveSupport.on_load(:action_controller) { _routes.finalize! } + end ensure - _routes.disable_clear_and_finalize = false + routes_to_reload.each do |_routes, draw_block| + _routes.disable_clear_and_finalize = false + end + end + + def routes_to_reload + @routes_to_reload ||= {} end def initialize! diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index ababf6a242..aa82a82b19 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -399,8 +399,10 @@ module Rails } end - def routes + def routes(&block) @routes ||= ActionDispatch::Routing::RouteSet.new + self.routes_draw_block = block if block_given? + @routes end def initializers @@ -447,6 +449,7 @@ module Rails end initializer :add_routing_paths do |app| + app.routes_to_reload[self.routes] = routes_draw_block paths.config.routes.to_a.each do |route| app.routes_reloader.paths.unshift(route) if File.exists?(route) end @@ -499,6 +502,8 @@ module Rails end protected + attr_accessor :routes_draw_block + def find_root_with_flag(flag, default=nil) root_path = self.class.called_from diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 17bffe05e1..2b9d728b0c 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -663,5 +663,45 @@ module RailtiesTest assert_equal AppTemplate._railtie, AppTemplate::Engine end + + test "properly reload routes" do + # when routes are inside application class definition + # they should not be reloaded when engine's routes + # file has changed + add_to_config <<-RUBY + routes do + mount lambda{|env| [200, {}, ["foo"]]} => "/foo" + mount Bukkits::Engine => "/bukkits" + end + RUBY + + FileUtils.rm(File.join(app_path, "config/routes.rb")) + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + mount lambda{|env| [200, {}, ["bar"]]} => "/bar" + end + RUBY + + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + namespace(Bukkits) + end + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + + boot_rails + + require "#{rails_root}/config/environment" + get "/foo" + assert_equal "foo", last_response.body + + get "/bukkits/bar" + assert_equal "bar", last_response.body + end end end -- cgit v1.2.3 From 57aa79e6bedeffcff899688546ef0a508948b4a5 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 28 Sep 2010 23:42:29 +0200 Subject: Move routes_reloader to a class: RoutesReloader --- railties/lib/rails/application.rb | 24 ++-------------- railties/lib/rails/engine.rb | 2 +- railties/lib/rails/routes_reloader.rb | 54 +++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 railties/lib/rails/routes_reloader.rb diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 2db131261c..8170be2f65 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/hash/reverse_merge' require 'active_support/file_update_checker' require 'fileutils' +require 'rails/routes_reloader' require 'rails/plugin' require 'rails/engine' @@ -81,28 +82,7 @@ module Rails end def routes_reloader - @routes_reloader ||= ActiveSupport::FileUpdateChecker.new([]){ reload_routes! } - end - - def reload_routes! - routes_to_reload.each do |_routes, draw_block| - _routes = self.routes - _routes.disable_clear_and_finalize = true - _routes.clear! - _routes.draw(&draw_block) if draw_block - end - routes_reloader.paths.each { |path| load(path) } - routes_to_reload.each do |_routes, draw_block| - ActiveSupport.on_load(:action_controller) { _routes.finalize! } - end - ensure - routes_to_reload.each do |_routes, draw_block| - _routes.disable_clear_and_finalize = false - end - end - - def routes_to_reload - @routes_to_reload ||= {} + @routes_reloader ||= Rails::RoutesReloader.new end def initialize! diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index aa82a82b19..9ae235b818 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -449,7 +449,7 @@ module Rails end initializer :add_routing_paths do |app| - app.routes_to_reload[self.routes] = routes_draw_block + app.routes_reloader.blocks[routes] = routes_draw_block paths.config.routes.to_a.each do |route| app.routes_reloader.paths.unshift(route) if File.exists?(route) end diff --git a/railties/lib/rails/routes_reloader.rb b/railties/lib/rails/routes_reloader.rb new file mode 100644 index 0000000000..9cfc38630d --- /dev/null +++ b/railties/lib/rails/routes_reloader.rb @@ -0,0 +1,54 @@ +module Rails + class RoutesReloader < ::ActiveSupport::FileUpdateChecker + def initialize + super([]) { reload! } + end + + def blocks + @blocks ||= {} + end + private + def reload! + clear! + load_blocks + load_paths + finalize! + ensure + revert + end + + def clear! + routers.each do |routes| + routes.disable_clear_and_finalize = true + routes.clear! + end + end + + def load_blocks + blocks.each do |routes, block| + routes.draw(&block) if block + end + end + + def load_paths + paths.each { |path| load(path) } + end + + def finalize! + routers.each do |routes| + ActiveSupport.on_load(:action_controller) { routes.finalize! } + end + end + + def revert + routers.each do |routes| + routes.disable_clear_and_finalize = false + end + end + + def routers + blocks.keys + end + end +end + -- cgit v1.2.3 From f851352318c7468db310e5fbea0d86dc8b731c6d Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 29 Sep 2010 17:41:30 +0200 Subject: Added config.app_generators to allow configuring application's generators from railties. With config.generators becomes a way to configure generators for current instance only. For example: module Blog class Engine < Rails::Engine config.generators do |g| g.orm :active_record end config.app_generators do |g| g.test_framework :rspec end end end such definition sets :active_record as orm for engine and :rspec as test_framework for application. The values set with app_generators can be overwritten in application using config.generators as you would normally do: module MyApp class Application < Rails::Application config.generators do |g| g.test_framework :test_unit end end end --- activerecord/lib/active_record/railtie.rb | 2 +- railties/lib/rails/application/configuration.rb | 1 + railties/lib/rails/railtie/configuration.rb | 19 ++++++++++-- railties/lib/rails/test_unit/railtie.rb | 2 +- railties/test/railties/engine_test.rb | 39 +++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 94dda4e413..868fd6c3ff 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -13,7 +13,7 @@ module ActiveRecord class Railtie < Rails::Railtie config.active_record = ActiveSupport::OrderedOptions.new - config.generators.orm :active_record, :migration => true, + config.app_generators.orm :active_record, :migration => true, :timestamps => true config.app_middleware.insert_after "::ActionDispatch::Callbacks", diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index a0ecbc0fc8..f902c3ded2 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -24,6 +24,7 @@ module Rails @time_zone = "UTC" @middleware = app_middleware @asset_path = '/' + @generators = app_generators end def asset_path=(value) diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index f09e3940cc..e0e4324a4a 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -17,6 +17,19 @@ module Rails @@app_middleware ||= Rails::Configuration::MiddlewareStackProxy.new end + # This allows you to modify application's generators from Railties. + # + # Values set on app_generators will become defaults for applicaiton, unless + # application overwrites them. + def app_generators + @@app_generators ||= Rails::Configuration::Generators.new + if block_given? + yield @@app_generators + else + @@app_generators + end + end + # Holds generators configuration: # # config.generators do |g| @@ -30,11 +43,11 @@ module Rails # config.generators.colorize_logging = false # def generators - @@generators ||= Rails::Configuration::Generators.new + @generators ||= Rails::Configuration::Generators.new if block_given? - yield @@generators + yield @generators else - @@generators + @generators end end diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb index e3fafc4b9d..2b6170ebfb 100644 --- a/railties/lib/rails/test_unit/railtie.rb +++ b/railties/lib/rails/test_unit/railtie.rb @@ -1,6 +1,6 @@ module Rails class TestUnitRailtie < Rails::Railtie - config.generators do |c| + config.app_generators do |c| c.test_framework :test_unit, :fixture => true, :fixture_replacement => nil diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 2b9d728b0c..c75639d740 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -703,5 +703,44 @@ module RailtiesTest get "/bukkits/bar" assert_equal "bar", last_response.body end + + test "setting generators for engine and overriding app generator's" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + config.generators do |g| + g.orm :datamapper + g.template_engine :haml + g.test_framework :rspec + end + + config.app_generators do |g| + g.orm :mongoid + g.template_engine :liquid + g.test_framework :shoulda + end + end + end + RUBY + + add_to_config <<-RUBY + config.generators do |g| + g.test_framework :test_unit + end + RUBY + + boot_rails + require "#{rails_root}/config/environment" + + app_generators = Rails.application.config.generators.options[:rails] + assert_equal :mongoid , app_generators[:orm] + assert_equal :liquid , app_generators[:template_engine] + assert_equal :test_unit, app_generators[:test_framework] + + generators = Bukkits::Engine.config.generators.options[:rails] + assert_equal :datamapper, generators[:orm] + assert_equal :haml , generators[:template_engine] + assert_equal :rspec , generators[:test_framework] + end end end -- cgit v1.2.3 From 6648babdedb8cb9494dec69d2f7efac3da1d239c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 29 Sep 2010 17:46:59 +0200 Subject: Allow running generators for Engine with usage of other application. After that commit, developers can set ENGINE_PATH in ENGINE/scripts/rails file and load application's ./script/rails (most of the time it will be dummy application used for testing). When running ./script/rails g it will use application to boot up, but then it will use Engine's root and configuration for generators. --- railties/lib/rails/commands.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 60a93c9848..acabdcac93 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -11,7 +11,17 @@ command = ARGV.shift command = aliases[command] || command case command -when 'generate', 'destroy', 'plugin', 'benchmarker', 'profiler' +when 'generate', 'destroy', 'plugin' + require APP_PATH + Rails.application.require_environment! + + if defined?(ENGINE_PATH) + engine = Rails.application.railties.engines.find { |r| r.root.to_s == ENGINE_PATH } + Rails.application = engine + end + require "rails/commands/#{command}" + +when 'benchmarker', 'profiler' require APP_PATH Rails.application.require_environment! require "rails/commands/#{command}" -- cgit v1.2.3 From 3049e645e5037cd923d0bad3c41c105dd9d791f8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 29 Sep 2010 20:05:34 +0200 Subject: Moved Rails::RoutesReloader to Rails::Application::RoutesReloader --- railties/lib/rails/application.rb | 4 +- railties/lib/rails/application/routes_reloader.rb | 55 +++++++++++++++++++++++ railties/lib/rails/routes_reloader.rb | 54 ---------------------- 3 files changed, 57 insertions(+), 56 deletions(-) create mode 100644 railties/lib/rails/application/routes_reloader.rb delete mode 100644 railties/lib/rails/routes_reloader.rb diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 8170be2f65..aafbbc29ee 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,7 +1,6 @@ require 'active_support/core_ext/hash/reverse_merge' require 'active_support/file_update_checker' require 'fileutils' -require 'rails/routes_reloader' require 'rails/plugin' require 'rails/engine' @@ -40,6 +39,7 @@ module Rails autoload :Configuration, 'rails/application/configuration' autoload :Finisher, 'rails/application/finisher' autoload :Railties, 'rails/application/railties' + autoload :RoutesReloader, 'rails/application/routes_reloader' class << self def inherited(base) @@ -82,7 +82,7 @@ module Rails end def routes_reloader - @routes_reloader ||= Rails::RoutesReloader.new + @routes_reloader ||= RoutesReloader.new end def initialize! diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb new file mode 100644 index 0000000000..23b72a0ec6 --- /dev/null +++ b/railties/lib/rails/application/routes_reloader.rb @@ -0,0 +1,55 @@ +module Rails + class Application + class RoutesReloader < ::ActiveSupport::FileUpdateChecker + def initialize + super([]) { reload! } + end + + def blocks + @blocks ||= {} + end + private + def reload! + clear! + load_blocks + load_paths + finalize! + ensure + revert + end + + def clear! + routers.each do |routes| + routes.disable_clear_and_finalize = true + routes.clear! + end + end + + def load_blocks + blocks.each do |routes, block| + routes.draw(&block) if block + end + end + + def load_paths + paths.each { |path| load(path) } + end + + def finalize! + routers.each do |routes| + ActiveSupport.on_load(:action_controller) { routes.finalize! } + end + end + + def revert + routers.each do |routes| + routes.disable_clear_and_finalize = false + end + end + + def routers + blocks.keys + end + end + end +end diff --git a/railties/lib/rails/routes_reloader.rb b/railties/lib/rails/routes_reloader.rb deleted file mode 100644 index 9cfc38630d..0000000000 --- a/railties/lib/rails/routes_reloader.rb +++ /dev/null @@ -1,54 +0,0 @@ -module Rails - class RoutesReloader < ::ActiveSupport::FileUpdateChecker - def initialize - super([]) { reload! } - end - - def blocks - @blocks ||= {} - end - private - def reload! - clear! - load_blocks - load_paths - finalize! - ensure - revert - end - - def clear! - routers.each do |routes| - routes.disable_clear_and_finalize = true - routes.clear! - end - end - - def load_blocks - blocks.each do |routes, block| - routes.draw(&block) if block - end - end - - def load_paths - paths.each { |path| load(path) } - end - - def finalize! - routers.each do |routes| - ActiveSupport.on_load(:action_controller) { routes.finalize! } - end - end - - def revert - routers.each do |routes| - routes.disable_clear_and_finalize = false - end - end - - def routers - blocks.keys - end - end -end - -- cgit v1.2.3 From 9f569c60adb3505cd7ca1723481199bf26619038 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 29 Sep 2010 22:31:58 +0200 Subject: Try to guess application's directory while trying to run the server, but only if config.ru is not present in current dir --- railties/lib/rails/commands.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index acabdcac93..60b9a55d80 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -33,8 +33,13 @@ when 'console' Rails::Console.start(Rails.application) when 'server' + # try to guess application's path if there is no config.ru file in current dir + # it allows to run script/rails server from other directories + Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru")) + require 'rails/commands/server' Rails::Server.new.tap { |server| + # we need to require application after the server sets environment require APP_PATH Dir.chdir(Rails.application.root) server.start -- cgit v1.2.3 From 6b248f6ea56b318d39b8c28b2a9f69a7d420f1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 30 Sep 2010 10:33:31 +0200 Subject: Add more information to comments. --- railties/lib/rails/commands.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 60b9a55d80..e3aa6d7c3e 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -33,13 +33,15 @@ when 'console' Rails::Console.start(Rails.application) when 'server' - # try to guess application's path if there is no config.ru file in current dir - # it allows to run script/rails server from other directories + # Change to the application's path if there is no config.ru file in current dir. + # This allows us to run script/rails server from other directories, but still get + # the main config.ru and properly set the tmp directory. Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru")) require 'rails/commands/server' Rails::Server.new.tap { |server| - # we need to require application after the server sets environment + # We need to require application after the server sets environment, + # otherwise the --environment option given to the server won't propagate. require APP_PATH Dir.chdir(Rails.application.root) server.start -- cgit v1.2.3 From 6a55ca346e543e4e112648cca2a01230c32b21ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 30 Sep 2010 11:40:51 +0200 Subject: Revert "removing crazy finalizer code until there is proof that we need it" This reverts commit a40e3c1a9604ab3737ad2465c8f6a6db0fe0cc78. --- actionpack/lib/action_view/template.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 405e1736ba..164d177dcc 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -101,6 +101,16 @@ module ActionView attr_reader :source, :identifier, :handler, :virtual_path, :formats, :original_encoding + # This finalizer is needed (and exactly with a proc inside another proc) + # otherwise templates leak in development. + Finalizer = proc do |method_name, mod| + proc do + mod.module_eval do + remove_possible_method method_name + end + end + end + def initialize(source, identifier, handler, details) @source = source @identifier = identifier @@ -245,6 +255,7 @@ module ActionView begin mod.module_eval(source, identifier, 0) + ObjectSpace.define_finalizer(self, Finalizer[method_name, mod]) method_name rescue Exception => e # errors from template code -- cgit v1.2.3 From 0495736339df48a625fd58f4304b7b497b02d859 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 30 Sep 2010 22:38:04 +0800 Subject: assert on empty array is always true. fixing test. --- activeresource/test/cases/format_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activeresource/test/cases/format_test.rb b/activeresource/test/cases/format_test.rb index c3733e13d8..bed95ef524 100644 --- a/activeresource/test/cases/format_test.rb +++ b/activeresource/test/cases/format_test.rb @@ -33,7 +33,7 @@ class FormatTest < Test::Unit::TestCase ActiveResource::HttpMock.respond_to.get "/people.#{format}", {'Accept' => ActiveResource::Formats[format].mime_type}, ActiveResource::Formats[format].encode(@programmers) remote_programmers = Person.find(:all) assert_equal 2, remote_programmers.size - assert remote_programmers.select { |p| p.name == 'David' } + assert remote_programmers.map { |p| p.name }.include? 'David' end end end -- cgit v1.2.3 From 33733d5d1de0eae6e25ee3f28aa69727f782086c Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 30 Sep 2010 22:40:59 +0800 Subject: no need to check for nil --- railties/lib/rails/commands/plugin.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb index 7bb4a1c054..8b2cd1bdba 100644 --- a/railties/lib/rails/commands/plugin.rb +++ b/railties/lib/rails/commands/plugin.rb @@ -58,7 +58,7 @@ class RailsEnvironment else plugin = name_uri_or_plugin end - unless plugin.nil? + if plugin plugin.install else puts "Plugin not found: #{name_uri_or_plugin}" -- cgit v1.2.3 From 91deff08c940f16ed149e7628694faff0393fe0a Mon Sep 17 00:00:00 2001 From: yalab Date: Fri, 1 Oct 2010 01:26:22 +0900 Subject: Fix 'rake db:create' is ignore encoding when using postgres [#5717 state:resolved] Signed-off-by: Santiago Pastorino --- activerecord/lib/active_record/railties/databases.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 389a5d5884..58c705c8b2 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -108,7 +108,7 @@ namespace :db do end end when 'postgresql' - @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8' + @encoding = config['encoding'] || ENV['CHARSET'] || 'utf8' begin ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding)) -- cgit v1.2.3 From ab9622ee62e4ae6372fab69b9b148875be573a22 Mon Sep 17 00:00:00 2001 From: oleg dashevskii Date: Wed, 25 Aug 2010 15:52:00 +0700 Subject: Tests proving #5441 --- activerecord/test/cases/calculations_test.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index afef31396e..3f963fc89a 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -275,6 +275,17 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal 2, Account.count(:firm_id, :conditions => "credit_limit = 50 AND firm_id IS NOT NULL") end + def test_should_count_field_in_joined_table + assert_equal 5, Account.count('companies.id', :joins => :firm) + assert_equal 4, Account.count('companies.id', :joins => :firm, :distinct => true) + end + + def test_should_count_field_in_joined_table_with_group_by + c = Account.count('companies.id', :group => :firm_id, :joins => :firm) + + [1,6,2,9].each { |firm_id| assert c.keys.include?(firm_id) } + end + def test_count_with_no_parameters_isnt_deprecated assert_not_deprecated { Account.count } end @@ -335,5 +346,4 @@ class CalculationsTest < ActiveRecord::TestCase def test_from_option_with_table_different_than_class assert_equal Account.count(:all), Company.count(:all, :from => 'accounts') end - end -- cgit v1.2.3 From cc18034c8c182df51a4fcb1a0a9b662f97d1f53d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 09:37:17 -0700 Subject: group clause must be more specific --- activerecord/test/cases/calculations_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 3f963fc89a..7ec40906d4 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -281,7 +281,7 @@ class CalculationsTest < ActiveRecord::TestCase end def test_should_count_field_in_joined_table_with_group_by - c = Account.count('companies.id', :group => :firm_id, :joins => :firm) + c = Account.count('companies.id', :group => 'accounts.firm_id', :joins => :firm) [1,6,2,9].each { |firm_id| assert c.keys.include?(firm_id) } end -- cgit v1.2.3 From a8a62f87f6777b1bad8f38cc4b0239b74a4f8a7a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 10:16:35 -0700 Subject: [#5441 state:resolved] refactoring code to determine aggregate column --- .../lib/active_record/relation/calculations.rb | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 03862c78e4..d79ef78b4d 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -183,12 +183,16 @@ module ActiveRecord end end - def execute_simple_calculation(operation, column_name, distinct) #:nodoc: - column = if @klass.column_names.include?(column_name.to_s) + def aggregate_column(column_name) + if @klass.column_names.include?(column_name.to_s) Arel::Attribute.new(@klass.unscoped.table, column_name) else - Arel::SqlLiteral.new(column_name == :all ? "*" : column_name.to_s) + Arel.sql(column_name == :all ? "*" : column_name.to_s) end + end + + def execute_simple_calculation(operation, column_name, distinct) #:nodoc: + column = aggregate_column(column_name) # Postgresql doesn't like ORDER BY when there are no GROUP BY relation = except(:order) @@ -209,18 +213,17 @@ module ActiveRecord group = @klass.connection.adapter_name == 'FrontBase' ? group_alias : group_field - aggregate_alias = column_alias_for(operation, column_name) - - select_statement = if operation == 'count' && column_name == :all - ["COUNT(*) AS count_all"] + if operation == 'count' && column_name == :all + aggregate_alias = 'count_all' else - [Arel::Attribute.new(@klass.unscoped.table, column_name).send(operation).as(aggregate_alias)] + aggregate_alias = column_alias_for(operation, column_name) end - select_statement << "#{group_field} AS #{group_alias}" - relation = except(:group).group(group) - relation.select_values = select_statement + relation.select_values = [ + aggregate_column(column_name).send(operation).as(aggregate_alias), + "#{group_field} AS #{group_alias}" + ] calculated_data = @klass.connection.select_all(relation.to_sql) -- cgit v1.2.3 From ef8ce78ba1d37c7d4246f0c6b2cf13140c2898f8 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 11:00:14 -0700 Subject: changing map and include to find --- activeresource/test/cases/format_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activeresource/test/cases/format_test.rb b/activeresource/test/cases/format_test.rb index bed95ef524..fc1a7b8c6f 100644 --- a/activeresource/test/cases/format_test.rb +++ b/activeresource/test/cases/format_test.rb @@ -33,7 +33,7 @@ class FormatTest < Test::Unit::TestCase ActiveResource::HttpMock.respond_to.get "/people.#{format}", {'Accept' => ActiveResource::Formats[format].mime_type}, ActiveResource::Formats[format].encode(@programmers) remote_programmers = Person.find(:all) assert_equal 2, remote_programmers.size - assert remote_programmers.map { |p| p.name }.include? 'David' + assert remote_programmers.find { |p| p.name == 'David' } end end end -- cgit v1.2.3 From 505b532605bd3b9b8a444be10911f0864f1d42ba Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 12:13:12 -0700 Subject: speeding up object instantiation by eliminating instance_eval --- activerecord/lib/active_record/base.rb | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 2157a0aded..9204295d8c 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -884,13 +884,9 @@ module ActiveRecord #:nodoc: # single-table inheritance model that makes it possible to create # objects of different types from the same table. def instantiate(record) - find_sti_class(record[inheritance_column]).allocate.instance_eval do - @attributes, @attributes_cache, @previously_changed, @changed_attributes = record, {}, {}, {} - @new_record = @readonly = @destroyed = @marked_for_destruction = false - _run_find_callbacks - _run_initialize_callbacks - self - end + model = find_sti_class(record[inheritance_column]).allocate + model.init_with('attributes' => record) + model end def find_sti_class(type_name) @@ -1416,6 +1412,24 @@ MSG populate_with_current_scope_attributes end + # Initialize an empty model object from +coder+. +coder+ must contain + # the attributes necessary for initializing an empty model object. For + # example: + # + # class Post < ActiveRecord::Base + # end + # + # post = Post.allocate + # post.init_with('attributes' => { 'title' => 'hello world' }) + # post.title # => 'hello world' + def init_with(coder) + @attributes = coder['attributes'] + @attributes_cache, @previously_changed, @changed_attributes = {}, {}, {} + @new_record = @readonly = @destroyed = @marked_for_destruction = false + _run_find_callbacks + _run_initialize_callbacks + end + # Returns a String, which Action Pack uses for constructing an URL to this # object. The default implementation returns this record's id as a String, # or nil if this record's unsaved. -- cgit v1.2.3 From ef6df93a8ddb675f1298973bb347825c554e95f9 Mon Sep 17 00:00:00 2001 From: Marcelo Giorgi Date: Thu, 30 Sep 2010 14:56:11 -0300 Subject: AssociationCollection#include? working properly for objects added with build method [#3472 state:resolved] --- .../active_record/associations/association_collection.rb | 13 +++++++++++++ .../has_and_belongs_to_many_associations_test.rb | 6 ++++++ .../test/cases/associations/has_many_associations_test.rb | 6 ++++++ .../associations/has_many_through_associations_test.rb | 14 ++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index 91e0a9f2f8..a617a0fb36 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -363,6 +363,7 @@ module ActiveRecord def include?(record) return false unless record.is_a?(@reflection.klass) + return include_in_memory?(record) if record.new_record? load_target if @reflection.options[:finder_sql] && !loaded? return @target.include?(record) if loaded? exists?(record) @@ -554,6 +555,18 @@ module ActiveRecord args.first.kind_of?(Hash) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] || @target.any? { |record| record.new_record? } || args.first.kind_of?(Integer)) end + + def include_in_memory?(record) + if @reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) + @owner.send(proxy_reflection.through_reflection.name.to_sym).map do |source| + source_reflection_target = source.send(proxy_reflection.source_reflection.name) + return true if source_reflection_target.respond_to?(:include?) ? source_reflection_target.include?(record) : source_reflection_target == record + end + false + else + @target.include?(record) + end + end end end end diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index c0be7dfdcc..7e070e1746 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -858,4 +858,10 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert_equal new_developer.name, "Marcelo" assert_equal new_developer.salary, 90_000 end + + def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build + project = Project.new + developer = project.developers.build + assert project.developers.include?(developer) + end end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 720b7fc386..c9f00fd737 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1267,4 +1267,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal new_comment.type, "SpecialComment" assert_equal new_comment.post_id, posts(:welcome).id end + + def test_include_method_in_has_many_association_should_return_true_for_instance_added_with_build + post = Post.new + comment = post.comments.build + assert post.comments.include?(comment) + end end diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 0dac633852..4b9f49f1ec 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -435,4 +435,18 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal new_subscriber.nick, "marklazz" assert_equal new_subscriber.name, "Marcelo Giorgi" end + + def test_include_method_in_association_through_should_return_true_for_instance_added_with_build + person = Person.new + reference = person.references.build + job = reference.build_job + assert person.jobs.include?(job) + end + + def test_include_method_in_association_through_should_return_true_for_instance_added_with_nested_builds + author = Author.new + post = author.posts.build + comment = post.comments.build + assert author.comments.include?(comment) + end end -- cgit v1.2.3 From fb4ee9c7e5da783d84d3a633297830ceac58ee48 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 14:22:09 -0700 Subject: type_name is never a blank string, so use faster .nil? call --- activerecord/lib/active_record/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 9204295d8c..aed4eff565 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -890,7 +890,7 @@ module ActiveRecord #:nodoc: end def find_sti_class(type_name) - if type_name.blank? || !columns_hash.include?(inheritance_column) + if type_name.nil? || !columns_hash.include?(inheritance_column) self else begin -- cgit v1.2.3 From 15419a5dc692be997d7637e40435a3d0d0fa4c1c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 14:35:36 -0700 Subject: build_where should be private --- activerecord/lib/active_record/relation/query_methods.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 2e0a2effc2..c8174b5f45 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -196,6 +196,8 @@ module ActiveRecord arel end + private + def build_where(opts, other = []) case opts when String, Array @@ -208,8 +210,6 @@ module ActiveRecord end end - private - def build_joins(relation, joins) association_joins = [] -- cgit v1.2.3 From 0238228e5d3ce1747a6f1d618693ffd44f947561 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 16:02:49 -0700 Subject: type_name should check for blank because people may have messed up databases --- activerecord/lib/active_record/base.rb | 2 +- activerecord/test/cases/inheritance_test.rb | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index aed4eff565..9204295d8c 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -890,7 +890,7 @@ module ActiveRecord #:nodoc: end def find_sti_class(type_name) - if type_name.nil? || !columns_hash.include?(inheritance_column) + if type_name.blank? || !columns_hash.include?(inheritance_column) self else begin diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index 8c09fc4d59..31679b2efe 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -14,6 +14,20 @@ class InheritanceTest < ActiveRecord::TestCase ActiveRecord::Base.store_full_sti_class = old end + def test_class_with_blank_sti_name + company = Company.find(:first) + company = company.clone + company.extend(Module.new { + def read_attribute(name) + return ' ' if name == 'type' + super + end + }) + company.save! + company = Company.find(:all).find { |x| x.id == company.id } + assert_equal ' ', company.type + end + def test_class_without_store_full_sti_class_returns_demodulized_name old = ActiveRecord::Base.store_full_sti_class ActiveRecord::Base.store_full_sti_class = false -- cgit v1.2.3 From 45edeed1ee5148e837ea9680fa0c40e4b151d6d7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 30 Sep 2010 16:28:12 -0700 Subject: Arel::Sql::Engine.new does not do anything anymore --- activerecord/lib/active_record.rb | 2 +- activerecord/lib/active_record/base.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index e2f2508ae8..f692e5ac89 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -118,7 +118,7 @@ module ActiveRecord end ActiveSupport.on_load(:active_record) do - Arel::Table.engine = Arel::Sql::Engine.new(self) + Arel::Table.engine = self end I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml' diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 9204295d8c..80ddd5e7ab 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -834,7 +834,7 @@ module ActiveRecord #:nodoc: if self == ActiveRecord::Base Arel::Table.engine else - connection_handler.connection_pools[name] ? Arel::Sql::Engine.new(self) : superclass.arel_engine + connection_handler.connection_pools[name] ? self : superclass.arel_engine end end end -- cgit v1.2.3 From 542ddd8c891e27278cdac26763b6ff8aadbfdf68 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 1 Oct 2010 23:16:05 +0200 Subject: brings csrf_meta_tags back to the generated layout After more discussion, it has be agreed that this kind of changes within reasonable margins are OK for 3.1. That is, it is fine to change a little bit the generators even if that means examples in existing books won't be exact. (Note that the singular csrf_meta_tag exists as an alias and thus those outdated examples will run, same for existing applications.) --- railties/guides/source/getting_started.textile | 2 +- .../rails/app/templates/app/views/layouts/application.html.erb.tt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 92b9131b59..9eae712a93 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -559,7 +559,7 @@ The view is only part of the story of how HTML is displayed in your web browser. Blog <%= stylesheet_link_tag :all %> <%= javascript_include_tag :defaults %> - <%= csrf_meta_tag %> + <%= csrf_meta_tags %> diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt index 1dd112b4a6..1de78eecae 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt @@ -4,7 +4,7 @@ <%= app_const_base %> <%%= stylesheet_link_tag :all %> <%%= javascript_include_tag :defaults %> - <%%= csrf_meta_tag %> + <%%= csrf_meta_tags %> -- cgit v1.2.3 From ff2fdcc52b391514cb62c2a1ef29827ac94914c6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 17:22:42 -0700 Subject: removing AS::Testing::Default in favor of just undefing default_test --- actionpack/lib/action_dispatch/testing/performance_test.rb | 3 +-- activesupport/lib/active_support/test_case.rb | 3 +-- activesupport/lib/active_support/testing/default.rb | 9 --------- activesupport/test/test_test.rb | 7 ------- 4 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 activesupport/lib/active_support/testing/default.rb diff --git a/actionpack/lib/action_dispatch/testing/performance_test.rb b/actionpack/lib/action_dispatch/testing/performance_test.rb index 33a5c68b9d..d6c98b4db7 100644 --- a/actionpack/lib/action_dispatch/testing/performance_test.rb +++ b/actionpack/lib/action_dispatch/testing/performance_test.rb @@ -11,9 +11,8 @@ begin # formats are written, so you'll have two output files per test method. class PerformanceTest < ActionDispatch::IntegrationTest include ActiveSupport::Testing::Performance - include ActiveSupport::Testing::Default end end rescue NameError $stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks." -end \ No newline at end of file +end diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index ed8c02ba3e..fb52fc7083 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -24,8 +24,7 @@ module ActiveSupport else Assertion = Test::Unit::AssertionFailedError - require 'active_support/testing/default' - include ActiveSupport::Testing::Default + undef :default_test end $tags = {} diff --git a/activesupport/lib/active_support/testing/default.rb b/activesupport/lib/active_support/testing/default.rb deleted file mode 100644 index a0bd6303c7..0000000000 --- a/activesupport/lib/active_support/testing/default.rb +++ /dev/null @@ -1,9 +0,0 @@ -module ActiveSupport - module Testing - module Default #:nodoc: - # Placeholder so test/unit ignores test cases without any tests. - def default_test - end - end - end -end diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb index cdaf63961a..ee5a20c789 100644 --- a/activesupport/test/test_test.rb +++ b/activesupport/test/test_test.rb @@ -126,13 +126,6 @@ class AssertPresentTest < ActiveSupport::TestCase end end -# These should always pass -if ActiveSupport::Testing.const_defined?(:Default) - class NotTestingThingsTest < Test::Unit::TestCase - include ActiveSupport::Testing::Default - end -end - class AlsoDoingNothingTest < ActiveSupport::TestCase end -- cgit v1.2.3 From 61e8b23fe599ac54382251b44d9690f08a759fe1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 17:37:34 -0700 Subject: speed up index_by by removing a lolinject --- activesupport/lib/active_support/core_ext/enumerable.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index f1103029c8..6ecedc26ef 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -90,10 +90,7 @@ module Enumerable # => { "Chade- Fowlersburg-e" => , "David Heinemeier Hansson" => , ...} # def index_by - inject({}) do |accum, elem| - accum[yield(elem)] = elem - accum - end + Hash[map { |elem| [yield(elem), elem] }] end # Returns true if the collection has more than 1 element. Functionally equivalent to collection.size > 1. -- cgit v1.2.3 From dfa331ae154c0475dfc631528071bdb06947acc2 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 17:54:50 -0700 Subject: use a method that actually exists --- actionpack/test/controller/integration_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 4ff39fb76c..f0d62b0b13 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -167,7 +167,7 @@ end class IntegrationTestTest < Test::Unit::TestCase def setup - @test = ::ActionDispatch::IntegrationTest.new(:default_test) + @test = ::ActionDispatch::IntegrationTest.new(:app) @test.class.stubs(:fixture_table_names).returns([]) @session = @test.open_session end -- cgit v1.2.3 From 6e1df2ca4631b8da6dae348af9d791f6e9aee1c5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 17:55:39 -0700 Subject: remove another lolinject --- activesupport/lib/active_support/cache/mem_cache_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index f32b562368..9eee3fc5e3 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -73,7 +73,7 @@ module ActiveSupport def read_multi(*names) options = names.extract_options! options = merged_options(options) - keys_to_names = names.inject({}){|map, name| map[escape_key(namespaced_key(name, options))] = name; map} + keys_to_names = Hash[names.map{|name| [escape_key(namespaced_key(name, options)), name]}] raw_values = @data.get_multi(keys_to_names.keys, :raw => true) values = {} raw_values.each do |key, value| -- cgit v1.2.3 From 44f85678e967f1eccfaf448f82ca81111c9584af Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 18:01:34 -0700 Subject: delete repeated code --- actionpack/test/abstract_unit.rb | 18 ++++++++++++++++++ actionpack/test/controller/redirect_test.rb | 18 ------------------ actionpack/test/template/url_helper_test.rb | 18 ------------------ 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 3540af13ac..bf6d43da08 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -308,3 +308,21 @@ module ActionView end end end + +class Workshop + extend ActiveModel::Naming + include ActiveModel::Conversion + attr_accessor :id + + def initialize(id) + @id = id + end + + def persisted? + id.present? + end + + def to_s + id.to_s + end +end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index b00142c92d..92d4a6d98b 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -3,24 +3,6 @@ require 'abstract_unit' class WorkshopsController < ActionController::Base end -class Workshop - extend ActiveModel::Naming - include ActiveModel::Conversion - attr_accessor :id - - def initialize(id) - @id = id - end - - def persisted? - id.present? - end - - def to_s - id.to_s - end -end - class RedirectController < ActionController::Base def simple_redirect redirect_to :action => "hello_world" diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index db8fd82aeb..98276da559 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -547,24 +547,6 @@ class LinkToUnlessCurrentWithControllerTest < ActionController::TestCase end end -class Workshop - extend ActiveModel::Naming - include ActiveModel::Conversion - attr_accessor :id - - def initialize(id) - @id = id - end - - def persisted? - id.present? - end - - def to_s - id.to_s - end -end - class Session extend ActiveModel::Naming include ActiveModel::Conversion -- cgit v1.2.3 From ffbcb84c215bb615a3db4bb8bf8dcb977e72e32b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 18:05:59 -0700 Subject: removing more duplicate code --- actionpack/test/abstract_unit.rb | 17 +++++++++++++++++ actionpack/test/controller/rescue_test.rb | 16 ---------------- actionpack/test/dispatch/show_exceptions_test.rb | 14 -------------- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index bf6d43da08..470b36dbe2 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -326,3 +326,20 @@ class Workshop id.to_s end end + +module ActionDispatch + class ShowExceptions + private + remove_method :public_path + def public_path + "#{FIXTURE_LOAD_PATH}/public" + end + + remove_method :logger + # Silence logger + def logger + nil + end + end +end + diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index a2418bb7c0..c445285538 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -1,21 +1,5 @@ require 'abstract_unit' -module ActionDispatch - class ShowExceptions - private - remove_method :public_path - def public_path - "#{FIXTURE_LOAD_PATH}/public" - end - - remove_method :logger - # Silence logger - def logger - nil - end - end -end - class RescueController < ActionController::Base class NotAuthorized < StandardError end diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index 4ede1ab47c..ce6c397e32 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -1,19 +1,5 @@ require 'abstract_unit' -module ActionDispatch - class ShowExceptions - private - def public_path - "#{FIXTURE_LOAD_PATH}/public" - end - - # Silence logger - def logger - nil - end - end -end - class ShowExceptionsTest < ActionDispatch::IntegrationTest Boomer = lambda do |env| req = ActionDispatch::Request.new(env) -- cgit v1.2.3 From 50cf5c11a1b33cd082bbdf4f253581109955797c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 18:07:19 -0700 Subject: fixing warnings with regexps on assert_match --- actionpack/test/controller/log_subscriber_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index 10873708fe..90c944d890 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -151,8 +151,8 @@ class ACLogSubscriberTest < ActionController::TestCase wait assert_equal 4, logs.size - assert_match /Exist fragment\? views\/foo%bar/, logs[1] - assert_match /Write fragment views\/foo%bar/, logs[2] + assert_match(/Exist fragment\? views\/foo%bar/, logs[1]) + assert_match(/Write fragment views\/foo%bar/, logs[2]) ensure @controller.config.perform_caching = true end -- cgit v1.2.3 From 3eb7f9adee4f606ac65e8e3d25098411b5a787b7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 1 Oct 2010 18:09:37 -0700 Subject: removing more duplicate code. :'( --- actionpack/test/controller/record_identifier_test.rb | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb index 835a0e970b..e46e317e31 100644 --- a/actionpack/test/controller/record_identifier_test.rb +++ b/actionpack/test/controller/record_identifier_test.rb @@ -1,17 +1,5 @@ require 'abstract_unit' - -class Comment - 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 comment' : "comment ##{@id}" - end -end +require 'controller/fake_models' class Sheep extend ActiveModel::Naming -- cgit v1.2.3 From b95152201871f076a0d5c95e9e6387f68feab94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 08:36:55 +0200 Subject: Revert "Perf: refactor _assign method to avoid inject and defining unneeded local var." _assigns must return a hash. This reverts commit e66c1cee86aba1c81152f3d0872313e65cec85a9. --- actionpack/lib/action_view/test_case.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 915c2f90d7..0eb4a663de 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -192,7 +192,11 @@ module ActionView end def _assigns - _instance_variables.map { |var| [var[1..-1].to_sym, instance_variable_get(var)] } + _instance_variables.inject({}) do |hash, var| + name = var[1..-1].to_sym + hash[name] = instance_variable_get(var) + hash + end end def _routes -- cgit v1.2.3 From 4e93179ed3f44825c157b54517e5a256f5725a55 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Thu, 30 Sep 2010 20:28:22 -0300 Subject: Refactor AssociationCollection#include? with objects in memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../lib/active_record/associations/association_collection.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index a617a0fb36..cb2d9e0a79 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -558,11 +558,10 @@ module ActiveRecord def include_in_memory?(record) if @reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) - @owner.send(proxy_reflection.through_reflection.name.to_sym).map do |source| - source_reflection_target = source.send(proxy_reflection.source_reflection.name) - return true if source_reflection_target.respond_to?(:include?) ? source_reflection_target.include?(record) : source_reflection_target == record + @owner.send(proxy_reflection.through_reflection.name.to_sym).any? do |source| + target = source.send(proxy_reflection.source_reflection.name) + target.respond_to?(:include?) ? target.include?(record) : target == record end - false else @target.include?(record) end -- cgit v1.2.3 From 609849a0f10ce37d96444f0359ce325b01d916ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 17:42:36 +0200 Subject: Fix a routing test. Reorganize middleware tests. --- .../application/middleware/best_practices_test.rb | 26 +++++++ railties/test/application/middleware/cache_test.rb | 12 --- .../test/application/middleware/remote_ip_test.rb | 63 +++++++++++++++ .../test/application/middleware/sendfile_test.rb | 56 +++++++++++++ railties/test/application/middleware_test.rb | 91 ---------------------- railties/test/application/routing_test.rb | 56 ++----------- railties/test/isolation/abstract_unit.rb | 27 +++++++ 7 files changed, 180 insertions(+), 151 deletions(-) create mode 100644 railties/test/application/middleware/best_practices_test.rb create mode 100644 railties/test/application/middleware/remote_ip_test.rb create mode 100644 railties/test/application/middleware/sendfile_test.rb diff --git a/railties/test/application/middleware/best_practices_test.rb b/railties/test/application/middleware/best_practices_test.rb new file mode 100644 index 0000000000..5b722e7510 --- /dev/null +++ b/railties/test/application/middleware/best_practices_test.rb @@ -0,0 +1,26 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class BestPracticesTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + require 'rack/test' + extend Rack::Test::Methods + simple_controller + end + + test "simple controller in production mode returns best standards" do + get '/foo' + assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"] + end + + test "simple controller in development mode leaves out Chrome" do + app("development") + get "/foo" + assert_equal "IE=Edge", last_response.headers["X-UA-Compatible"] + end + end +end diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb index 5675cebfd9..f582ed0e42 100644 --- a/railties/test/application/middleware/cache_test.rb +++ b/railties/test/application/middleware/cache_test.rb @@ -11,18 +11,6 @@ module ApplicationTests extend Rack::Test::Methods end - def app(env = "production") - old_env = ENV["RAILS_ENV"] - - @app ||= begin - ENV["RAILS_ENV"] = env - require "#{app_path}/config/environment" - Rails.application - end - ensure - ENV["RAILS_ENV"] = old_env - end - def simple_controller controller :expires, <<-RUBY class ExpiresController < ApplicationController diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb new file mode 100644 index 0000000000..f28302d70a --- /dev/null +++ b/railties/test/application/middleware/remote_ip_test.rb @@ -0,0 +1,63 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class RemoteIpTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + def app + @app ||= Rails.application + end + + def remote_ip(env = {}) + remote_ip = nil + env = Rack::MockRequest.env_for("/").merge(env).merge!( + 'action_dispatch.show_exceptions' => false, + 'action_dispatch.secret_token' => 'b3c631c314c0bbca50c1b2843150fe33' + ) + + endpoint = Proc.new do |e| + remote_ip = ActionDispatch::Request.new(e).remote_ip + [200, {}, ["Hello"]] + end + + Rails.application.middleware.build(endpoint).call(env) + remote_ip + end + + test "remote_ip works" do + make_basic_app + assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1") + end + + test "checks IP spoofing by default" do + make_basic_app + assert_raises(ActionDispatch::RemoteIp::IpSpoofAttackError) do + remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") + end + end + + test "can disable IP spoofing check" do + make_basic_app do |app| + app.config.action_dispatch.ip_spoofing_check = false + end + + assert_nothing_raised(ActionDispatch::RemoteIp::IpSpoofAttackError) do + assert_equal "1.1.1.2", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") + end + end + + test "the user can set trusted proxies" do + make_basic_app do |app| + app.config.action_dispatch.trusted_proxies = /^4\.2\.42\.42$/ + end + + assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "4.2.42.42,1.1.1.1") + end + end +end diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb new file mode 100644 index 0000000000..0128261cd4 --- /dev/null +++ b/railties/test/application/middleware/sendfile_test.rb @@ -0,0 +1,56 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class SendfileTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + def app + @app ||= Rails.application + end + + define_method :simple_controller do + class ::OmgController < ActionController::Base + def index + send_file __FILE__ + end + end + end + + # x_sendfile_header middleware + test "config.action_dispatch.x_sendfile_header defaults to ''" do + make_basic_app + simple_controller + + get "/" + assert_equal File.read(__FILE__), last_response.body + end + + test "config.action_dispatch.x_sendfile_header can be set" do + make_basic_app do |app| + app.config.action_dispatch.x_sendfile_header = "X-Sendfile" + end + + simple_controller + + get "/" + assert_equal File.expand_path(__FILE__), last_response.headers["X-Sendfile"] + end + + test "config.action_dispatch.x_sendfile_header is sent to Rack::Sendfile" do + make_basic_app do |app| + app.config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File' + end + + simple_controller + + get "/" + assert_equal File.expand_path(__FILE__), last_response.headers["X-Lighttpd-Send-File"] + end + end +end diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index f9b594eb33..2372ad85b8 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -129,81 +129,6 @@ module ApplicationTests assert_equal "Rack::Config", middleware.first end - # x_sendfile_header middleware - test "config.action_dispatch.x_sendfile_header defaults to ''" do - make_basic_app - - class ::OmgController < ActionController::Base - def index - send_file __FILE__ - end - end - - get "/" - assert_equal File.read(__FILE__), last_response.body - end - - test "config.action_dispatch.x_sendfile_header can be set" do - make_basic_app do |app| - app.config.action_dispatch.x_sendfile_header = "X-Sendfile" - end - - class ::OmgController < ActionController::Base - def index - send_file __FILE__ - end - end - - get "/" - assert_equal File.expand_path(__FILE__), last_response.headers["X-Sendfile"] - end - - test "config.action_dispatch.x_sendfile_header is sent to Rack::Sendfile" do - make_basic_app do |app| - app.config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File' - end - - class ::OmgController < ActionController::Base - def index - send_file __FILE__ - end - end - - get "/" - assert_equal File.expand_path(__FILE__), last_response.headers["X-Lighttpd-Send-File"] - end - - # remote_ip tests - test "remote_ip works" do - make_basic_app - assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1") - end - - test "checks IP spoofing by default" do - make_basic_app - assert_raises(ActionDispatch::RemoteIp::IpSpoofAttackError) do - remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") - end - end - - test "can disable IP spoofing check" do - make_basic_app do |app| - app.config.action_dispatch.ip_spoofing_check = false - end - - assert_nothing_raised(ActionDispatch::RemoteIp::IpSpoofAttackError) do - assert_equal "1.1.1.2", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") - end - end - - test "the user can set trusted proxies" do - make_basic_app do |app| - app.config.action_dispatch.trusted_proxies = /^4\.2\.42\.42$/ - end - - assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "4.2.42.42,1.1.1.1") - end - test "show exceptions middleware filter backtrace before logging" do my_middleware = Struct.new(:app) do def call(env) @@ -232,21 +157,5 @@ module ApplicationTests def middleware AppTemplate::Application.middleware.map(&:klass).map(&:name) end - - def remote_ip(env = {}) - remote_ip = nil - env = Rack::MockRequest.env_for("/").merge(env).merge!( - 'action_dispatch.show_exceptions' => false, - 'action_dispatch.secret_token' => 'b3c631c314c0bbca50c1b2843150fe33' - ) - - endpoint = Proc.new do |e| - remote_ip = ActionDispatch::Request.new(e).remote_ip - [200, {}, ["Hello"]] - end - - Rails.application.middleware.build(endpoint).call(env) - remote_ip - end end end diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index 416a5de5b0..e42f5720a9 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -11,34 +11,6 @@ module ApplicationTests extend Rack::Test::Methods end - def app(env = "production") - old_env = ENV["RAILS_ENV"] - - @app ||= begin - ENV["RAILS_ENV"] = env - require "#{app_path}/config/environment" - Rails.application - end - ensure - ENV["RAILS_ENV"] = old_env - end - - def simple_controller - controller :foo, <<-RUBY - class FooController < ApplicationController - def index - render :text => "foo" - end - end - RUBY - - app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do - match ':controller(/:action)' - end - RUBY - end - test "rails/info/properties in development" do app("development") get "/rails/info/properties" @@ -58,21 +30,6 @@ module ApplicationTests assert_equal 'foo', last_response.body end - test "simple controller in production mode returns best standards" do - simple_controller - - get '/foo' - assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"] - end - - test "simple controller in development mode leaves out Chrome" do - simple_controller - app("development") - - get "/foo" - assert_equal "IE=Edge", last_response.headers["X-UA-Compatible"] - end - test "simple controller with helper" do controller :foo, <<-RUBY class FooController < ApplicationController @@ -177,7 +134,7 @@ module ApplicationTests assert_equal 'admin::foo', last_response.body end - def test_reloads_appended_route_blocks + test "routes appending blocks" do app_file 'config/routes.rb', <<-RUBY AppTemplate::Application.routes.draw do match ':controller#:action' @@ -246,10 +203,13 @@ module ApplicationTests test 'routes are loaded just after initialization' do require "#{app_path}/config/application" - app_file 'config/routes.rb', <<-RUBY - InitializeRackApp = lambda { |env| [200, {}, ["InitializeRackApp"]] } + # Create the rack app just inside after initialize callback + ActiveSupport.on_load(:after_initialize) do + ::InitializeRackApp = lambda { |env| [200, {}, ["InitializeRackApp"]] } + end - AppTemplate::Application.routes.draw do + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do |map| match 'foo', :to => ::InitializeRackApp end RUBY @@ -258,7 +218,7 @@ module ApplicationTests assert_equal "InitializeRackApp", last_response.body end - test 'resource routing with irrigular inflection' do + test 'resource routing with irregular inflection' do app_file 'config/initializers/inflection.rb', <<-RUBY ActiveSupport::Inflector.inflections do |inflect| inflect.irregular 'yazi', 'yazilar' diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 79c7735019..3b03e4eb3d 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -45,6 +45,17 @@ module TestHelpers end module Rack + def app(env = "production") + old_env = ENV["RAILS_ENV"] + @app ||= begin + ENV["RAILS_ENV"] = env + require "#{app_path}/config/environment" + Rails.application + end + ensure + ENV["RAILS_ENV"] = old_env + end + def extract_body(response) "".tap do |body| response[2].each {|chunk| body << chunk } @@ -124,6 +135,22 @@ module TestHelpers extend ::Rack::Test::Methods end + def simple_controller + controller :foo, <<-RUBY + class FooController < ApplicationController + def index + render :text => "foo" + end + end + RUBY + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match ':controller(/:action)' + end + RUBY + end + class Bukkit attr_reader :path -- cgit v1.2.3 From 7b0c592e38e4b1d370e04d856d245f825dfa9cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 17:45:26 +0200 Subject: reload_routes! is part of the public API and should not be removed. --- railties/lib/rails/application.rb | 4 ++++ railties/lib/rails/application/routes_reloader.rb | 6 ++++-- railties/test/application/routing_test.rb | 9 ++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index aafbbc29ee..4d04184b20 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -81,6 +81,10 @@ module Rails super end + def reload_routes! + routes_reloader.reload! + end + def routes_reloader @routes_reloader ||= RoutesReloader.new end diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb index 23b72a0ec6..6da903c1ac 100644 --- a/railties/lib/rails/application/routes_reloader.rb +++ b/railties/lib/rails/application/routes_reloader.rb @@ -8,7 +8,7 @@ module Rails def blocks @blocks ||= {} end - private + def reload! clear! load_blocks @@ -18,6 +18,8 @@ module Rails revert end + protected + def clear! routers.each do |routes| routes.disable_clear_and_finalize = true @@ -32,7 +34,7 @@ module Rails end def load_paths - paths.each { |path| load(path) } + paths.each { |path| load(path) } end def finalize! diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index e42f5720a9..62589c998d 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -209,7 +209,7 @@ module ApplicationTests end app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match 'foo', :to => ::InitializeRackApp end RUBY @@ -218,6 +218,13 @@ module ApplicationTests assert_equal "InitializeRackApp", last_response.body end + test 'reload_routes! is part of Rails.application API' do + app("development") + assert_nothing_raised do + Rails.application.reload_routes! + end + end + test 'resource routing with irregular inflection' do app_file 'config/initializers/inflection.rb', <<-RUBY ActiveSupport::Inflector.inflections do |inflect| -- cgit v1.2.3 From 8d1df887d32643f0aee2d71f7216ec98fdfe4fdb Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Wed, 29 Sep 2010 18:15:36 +0530 Subject: Fixing search_field to remove object attribute from options hash [#5730 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/lib/action_view/helpers/form_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 1836baaf12..3cd8b02bc4 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -791,7 +791,7 @@ module ActionView options["incremental"] = true unless options.has_key?("incremental") end - InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("search", options) + InstanceTag.new(object_name, method, self, options.delete("object")).to_input_field_tag("search", options) end # Returns a text_field of type "tel". -- cgit v1.2.3 From 297cf0b26658ff9c7f19fc703de5bd8939e31d06 Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Sat, 2 Oct 2010 17:39:12 +0530 Subject: added test for form_for with search_field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionpack/test/template/form_helper_test.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index abc98ebe69..8809e510fb 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -761,6 +761,20 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + + def test_form_for_with_search_field + # Test case for bug which would emit an "object" attribute + # when used with form_for using a search_field form helper + form_for(Post.new, :url => "/search", :html => { :id => 'search-post' }) do |f| + concat f.search_field(:title) + end + + expected = whole_form("/search", "search-post", "new_post") do + "" + end + + assert_dom_equal expected, output_buffer + end def test_form_for_with_remote form_for(@post, :url => '/', :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| @@ -1737,4 +1751,5 @@ class FormHelperTest < ActionView::TestCase def protect_against_forgery? false end + end -- cgit v1.2.3 From 757bbd540cadc47b8f9d6b9d6bc7bb3cb638d022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 18:30:38 +0200 Subject: :'' is not valid ruby. --- railties/test/generators/generated_attribute_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/generators/generated_attribute_test.rb b/railties/test/generators/generated_attribute_test.rb index 272e179fe3..064546a3f3 100644 --- a/railties/test/generators/generated_attribute_test.rb +++ b/railties/test/generators/generated_attribute_test.rb @@ -117,7 +117,7 @@ class GeneratedAttributeTest < Rails::Generators::TestCase def test_missing_type_raises_exception assert_raise Thor::Error do - create_generated_attribute(:'', 'title') + create_generated_attribute('', 'title') end end end -- cgit v1.2.3 From 04cbabb0a0206553d7b474ee7a191d19957048fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 18:38:23 +0200 Subject: Deprecate generators in Railties. You should use app_generators instead. --- railties/lib/rails/engine/configuration.rb | 28 ++++++++++++++++++++++--- railties/lib/rails/railtie.rb | 2 +- railties/lib/rails/railtie/configuration.rb | 32 ++++++----------------------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index d4d87be527..b69c0e1c53 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -4,16 +4,38 @@ module Rails class Engine class Configuration < ::Rails::Railtie::Configuration attr_reader :root - attr_writer :eager_load_paths, :autoload_once_paths, :autoload_paths - attr_accessor :middleware, :plugins, :asset_path + attr_writer :middleware, :eager_load_paths, :autoload_once_paths, :autoload_paths + attr_accessor :plugins, :asset_path def initialize(root=nil) super() @root = root - @middleware = Rails::Configuration::MiddlewareStackProxy.new @helpers_paths = [] end + # Returns the middleware stack for the engine. + def middleware + @middleware ||= Rails::Configuration::MiddlewareStackProxy.new + end + + # Holds generators configuration: + # + # config.generators do |g| + # g.orm :datamapper, :migration => true + # g.template_engine :haml + # g.test_framework :rspec + # end + # + # If you want to disable color in console, do: + # + # config.generators.colorize_logging = false + # + def generators #:nodoc + @generators ||= Rails::Configuration::Generators.new + yield(@generators) if block_given? + @generators + end + def paths @paths ||= begin paths = Rails::Paths::Root.new(@root) diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index 09650789ac..2b68a3c453 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -83,7 +83,7 @@ module Rails # # class MyRailtie < Rails::Railtie # # Customize the ORM - # config.generators.orm :my_railtie_orm + # config.app_generators.orm :my_railtie_orm # # # Add a to_prepare block which is executed once in production # # and before each request in development diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index e0e4324a4a..3d0af185a2 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -5,7 +5,6 @@ module Rails class Configuration def initialize @@options ||= {} - @@static_asset_paths = ActiveSupport::OrderedHash.new end # This allows you to modify the application's middlewares from Engines. @@ -23,32 +22,13 @@ module Rails # application overwrites them. def app_generators @@app_generators ||= Rails::Configuration::Generators.new - if block_given? - yield @@app_generators - else - @@app_generators - end + yield(@@app_generators) if block_given? + @@app_generators end - # Holds generators configuration: - # - # config.generators do |g| - # g.orm :datamapper, :migration => true - # g.template_engine :haml - # g.test_framework :rspec - # end - # - # If you want to disable color in console, do: - # - # config.generators.colorize_logging = false - # - def generators - @generators ||= Rails::Configuration::Generators.new - if block_given? - yield @generators - else - @generators - end + def generators(&block) #:nodoc + ActiveSupport::Deprecation.warn "config.generators is deprecated. Please use config.app_generators instead." + app_generators(&block) end def before_configuration(&block) @@ -83,7 +63,7 @@ module Rails # with associated public folders, like: # { "/" => "/app/public", "/my_engine" => "app/engines/my_engine/public" } def static_asset_paths - @@static_asset_paths + @@static_asset_paths ||= ActiveSupport::OrderedHash.new end private -- cgit v1.2.3 From 49cc01002e82208596439bb94d04805b85b75d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 2 Oct 2010 09:40:54 -0700 Subject: Be more explicit about what is deprecated. --- railties/lib/rails/railtie/configuration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index 3d0af185a2..afeceafb67 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -27,7 +27,7 @@ module Rails end def generators(&block) #:nodoc - ActiveSupport::Deprecation.warn "config.generators is deprecated. Please use config.app_generators instead." + ActiveSupport::Deprecation.warn "config.generators in Rails::Railtie is deprecated. Please use config.app_generators instead." app_generators(&block) end -- cgit v1.2.3 From f656796d05715174568536cfe119a3959a020f23 Mon Sep 17 00:00:00 2001 From: David Chelimsky Date: Sat, 2 Oct 2010 12:35:17 -0500 Subject: Rename _assigns to view_assigns in AV::TC - also add tests - also deprecate _assigns [#5751 state:resolved] Signed-off-by: Santiago Pastorino --- actionpack/lib/action_view/test_case.rb | 30 ++++++++++++++++++++--------- actionpack/test/template/test_case_test.rb | 31 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 0eb4a663de..ac59c16d7c 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -103,7 +103,7 @@ module ActionView end def render(options = {}, local_assigns = {}, &block) - view.assign(_assigns) + view.assign(view_assigns) @rendered << output = view.render(options, local_assigns, &block) output end @@ -169,15 +169,19 @@ module ActionView alias_method :_view, :view - EXCLUDE_IVARS = %w{ + INTERNAL_IVARS = %w{ + @__name__ @_assertion_wrapped + @_assertions @_result + @_routes @controller @layouts @locals @method_name @output_buffer @partials + @passed @rendered @request @routes @@ -187,18 +191,26 @@ module ActionView @view_context_class } - def _instance_variables - instance_variables.map(&:to_s) - EXCLUDE_IVARS + def _user_defined_ivars + instance_variables.map(&:to_s) - INTERNAL_IVARS end - def _assigns - _instance_variables.inject({}) do |hash, var| - name = var[1..-1].to_sym - hash[name] = instance_variable_get(var) - hash + # Returns a Hash of instance variables and their values, as defined by + # the user in the test case, which are then assigned to the view being + # rendered. This is generally intended for internal use and extension + # frameworks. + def view_assigns + _user_defined_ivars.inject({}) do |hash, var| + hash.merge(var.sub('@','').to_sym => instance_variable_get(var)) end end + def _assigns + ActiveSupport::Deprecation.warn "ActionView::TestCase#_assigns is deprecated and will be removed in future versions. " << + "Please use view_assigns instead." + view_assigns + end + def _routes @controller._routes if @controller.respond_to?(:_routes) end diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index 8526db61cc..a745999622 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -116,6 +116,37 @@ module ActionView end end + class AssignsTest < ActionView::TestCase + setup do + ActiveSupport::Deprecation.stubs(:warn) + end + + test "_assigns delegates to user_defined_ivars" do + self.expects(:view_assigns) + _assigns + end + + test "_assigns is deprecated" do + ActiveSupport::Deprecation.expects(:warn) + _assigns + end + end + + class ViewAssignsTest < ActionView::TestCase + test "view_assigns returns a Hash of user defined ivars" do + @a = 'b' + @c = 'd' + assert_equal({:a => 'b', :c => 'd'}, view_assigns) + end + + test "view_assigns excludes internal ivars" do + INTERNAL_IVARS.each do |ivar| + assert defined?(ivar), "expected #{ivar} to be defined" + assert !view_assigns.keys.include?(ivar.sub('@','').to_sym), "expected #{ivar} to be excluded from view_assigns" + end + end + end + class HelperExposureTest < ActionView::TestCase helper(Module.new do def render_from_helper -- cgit v1.2.3 From c28bebef13b8a0e497fc7bbb83f542e9400e07e5 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 3 Oct 2010 13:34:34 -0200 Subject: PERF: Hash[] + map is faster than this silly inject, and var[1..-1] is faster than var.sub('@', '') --- actionpack/lib/action_view/test_case.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index ac59c16d7c..731f91df30 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -200,9 +200,9 @@ module ActionView # rendered. This is generally intended for internal use and extension # frameworks. def view_assigns - _user_defined_ivars.inject({}) do |hash, var| - hash.merge(var.sub('@','').to_sym => instance_variable_get(var)) - end + Hash[_user_defined_ivars.map do |var| + [var[1..-1].to_sym, instance_variable_get(var)] + end] end def _assigns -- cgit v1.2.3 From 10249d7b7728525fb7660409e3bbc9e0286dbf0f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 3 Oct 2010 14:52:46 -0200 Subject: PERF: change inject({}) with Hash + map --- actionmailer/lib/action_mailer/old_api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionmailer/lib/action_mailer/old_api.rb b/actionmailer/lib/action_mailer/old_api.rb index b8c15df263..a9cdf6c0ca 100644 --- a/actionmailer/lib/action_mailer/old_api.rb +++ b/actionmailer/lib/action_mailer/old_api.rb @@ -247,7 +247,7 @@ module ActionMailer [ nil, {} ] else ctype, *attrs = @content_type.split(/;\s*/) - attrs = attrs.inject({}) { |h,s| k,v = s.split(/\=/, 2); h[k] = v; h } + attrs = Hash[attrs.map { |attr| attr.split(/\=/, 2) }] [ctype, {"charset" => @charset}.merge(attrs)] end end -- cgit v1.2.3 From 49203126430c6dbaf9ce47c21c58c4081fb53e82 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 3 Oct 2010 14:58:18 -0200 Subject: PERF: Don't create unnecessary objects --- actionmailer/lib/action_mailer/old_api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionmailer/lib/action_mailer/old_api.rb b/actionmailer/lib/action_mailer/old_api.rb index a9cdf6c0ca..0396f0775e 100644 --- a/actionmailer/lib/action_mailer/old_api.rb +++ b/actionmailer/lib/action_mailer/old_api.rb @@ -248,7 +248,7 @@ module ActionMailer else ctype, *attrs = @content_type.split(/;\s*/) attrs = Hash[attrs.map { |attr| attr.split(/\=/, 2) }] - [ctype, {"charset" => @charset}.merge(attrs)] + [ctype, {"charset" => @charset}.merge!(attrs)] end end end -- cgit v1.2.3 From 42fad8c82b3ba6f86c84f06645cc1e39a8a776dd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 3 Oct 2010 15:03:59 -0200 Subject: PERF: more changes from inject({}) to Hash + map --- activeresource/lib/active_resource/validations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activeresource/lib/active_resource/validations.rb b/activeresource/lib/active_resource/validations.rb index d3b19ee560..a373e53f11 100644 --- a/activeresource/lib/active_resource/validations.rb +++ b/activeresource/lib/active_resource/validations.rb @@ -13,7 +13,7 @@ module ActiveResource # or not (by passing true) def from_array(messages, save_cache = false) clear unless save_cache - humanized_attributes = @base.attributes.keys.inject({}) { |h, attr_name| h.update(attr_name.humanize => attr_name) } + humanized_attributes = Hash[@base.attributes.keys.map { |attr_name| [attr_name.humanize, attr_name] }] messages.each do |message| attr_message = humanized_attributes.keys.detect do |attr_name| if message[0, attr_name.size + 1] == "#{attr_name} " -- cgit v1.2.3 From 5836af8f8b0eb3c569c66792abf50a0485bb6f22 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 3 Oct 2010 16:33:46 -0200 Subject: PERF: more Hash + map changes --- .../lib/active_support/core_ext/class/inheritable_attributes.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index 7a6a0be69d..af30bfc13a 100644 --- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -158,9 +158,9 @@ class Class # :nodoc: if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES) new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES else - new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)| - memo.update(key => value.duplicable? ? value.dup : value) - end + new_inheritable_attributes = Hash[inheritable_attributes.map do |(key, value)| + [key, value.duplicable? ? value.dup : value] + end] end child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes) -- cgit v1.2.3 From 50215f9525b6b5e3bfe703724b9f68177ed8565d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 20 Sep 2010 10:18:44 +0200 Subject: Rely on Rack::Session stores API for more compatibility across the Ruby world. --- Gemfile | 1 + actionpack/CHANGELOG | 6 +- actionpack/lib/action_controller/test_case.rb | 8 +- actionpack/lib/action_dispatch/http/url.rb | 5 - .../middleware/session/abstract_store.rb | 280 ++++----------------- .../middleware/session/cookie_store.rb | 64 ++--- .../middleware/session/mem_cache_store.rb | 53 +--- .../test/dispatch/session/cookie_store_test.rb | 12 - activerecord/lib/active_record/session_store.rb | 7 +- 9 files changed, 90 insertions(+), 346 deletions(-) diff --git a/Gemfile b/Gemfile index 9d29c42e1c..7fe1c3ad22 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ else gem "arel", :git => "git://github.com/rails/arel.git" end +gem "rack", :git => "git://github.com/rack/rack.git" gem "rails", :path => File.dirname(__FILE__) gem "rake", ">= 0.8.7" diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 6f8314109b..6352b97a6b 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,12 +1,12 @@ *Rails 3.1.0 (unreleased)* +* Rely on Rack::Session stores API for more compatibility across the Ruby world. This is backwards incompatible since Rack::Session expects #get_session to accept 4 arguments and requires #destroy_session instead of simply #destroy. [José Valim] + * file_field automatically adds :multipart => true to the enclosing form. [Santiago Pastorino] * Renames csrf_meta_tag -> csrf_meta_tags, and aliases csrf_meta_tag for backwards compatibility. [fxn] -* Add Rack::Cache to the default stack. Create a Rails store that delegates to the Rails cache, so by default, whatever caching layer you are using will be used - for HTTP caching. Note that Rack::Cache will be used if you use #expires_in, #fresh_when or #stale with :public => true. Otherwise, the caching rules will apply - to the browser only. +* Add Rack::Cache to the default stack. Create a Rails store that delegates to the Rails cache, so by default, whatever caching layer you are using will be used for HTTP caching. Note that Rack::Cache will be used if you use #expires_in, #fresh_when or #stale with :public => true. Otherwise, the caching rules will apply to the browser only. [Yehuda Katz, Carl Lerche] *Rails 3.0.0 (August 29, 2010)* diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 1af75fc2d7..d7b54c2abc 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -187,15 +187,17 @@ module ActionController end end - class TestSession < ActionDispatch::Session::AbstractStore::SessionHash #:nodoc: - DEFAULT_OPTIONS = ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS + class TestSession < Rack::Session::Abstract::SessionHash #:nodoc: + DEFAULT_OPTIONS = Rack::Session::Abstract::ID::DEFAULT_OPTIONS def initialize(session = {}) replace(session.stringify_keys) @loaded = true end - def exists?; true; end + def exists? + true + end end # Superclass for ActionController functional tests. Functional tests allow you to diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 3e5cd6a2f9..cfee95eb4b 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -18,11 +18,6 @@ module ActionDispatch @protocol ||= ssl? ? 'https://' : 'http://' end - # Is this an SSL request? - def ssl? - @ssl ||= @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https' - end - # Returns the \host for this request, such as "example.com". def raw_host_with_port if forwarded = env["HTTP_X_FORWARDED_HOST"] diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index db0187c015..679ba7fc8e 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -1,5 +1,6 @@ require 'rack/utils' require 'rack/request' +require 'rack/session/abstract/id' require 'action_dispatch/middleware/cookies' require 'active_support/core_ext/object/blank' @@ -8,252 +9,69 @@ module ActionDispatch class SessionRestoreError < StandardError #:nodoc: end - class AbstractStore - ENV_SESSION_KEY = 'rack.session'.freeze - ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze - - # thin wrapper around Hash that allows us to lazily - # load session id into session_options - class OptionsHash < Hash - def initialize(by, env, default_options) - @by = by - @env = env - @session_id_loaded = false - merge!(default_options) - end - - def [](key) - if key == :id - load_session_id! unless key?(:id) || has_session_id? - end - super - end - - private - - def has_session_id? - @session_id_loaded - end - - def load_session_id! - self[:id] = @by.send(:extract_session_id, @env) - @session_id_loaded = true - end - end - - class SessionHash < Hash - def initialize(by, env) - super() - @by = by - @env = env - @loaded = false - end - - def [](key) - load_for_read! - super(key.to_s) - end - - def has_key?(key) - load_for_read! - super(key.to_s) - end - - def []=(key, value) - load_for_write! - super(key.to_s, value) - end - - def clear - load_for_write! - super - end - - def to_hash - load_for_read! - h = {}.replace(self) - h.delete_if { |k,v| v.nil? } - h - end - - def update(hash) - load_for_write! - super(hash.stringify_keys) - end - - def delete(key) - load_for_write! - super(key.to_s) - end - - def inspect - load_for_read! - super - end - - def exists? - return @exists if instance_variable_defined?(:@exists) - @exists = @by.send(:exists?, @env) - end - - def loaded? - @loaded - end - - def destroy - clear - @by.send(:destroy, @env) if defined?(@by) && @by - @env[ENV_SESSION_OPTIONS_KEY][:id] = nil if defined?(@env) && @env && @env[ENV_SESSION_OPTIONS_KEY] - @loaded = false - end - - private - - def load_for_read! - load! if !loaded? && exists? - end - - def load_for_write! - load! unless loaded? - end - - def load! - id, session = @by.send(:load_session, @env) - @env[ENV_SESSION_OPTIONS_KEY][:id] = id - replace(session.stringify_keys) - @loaded = true - end - + module DestroyableSession + def destroy + clear + options = @env[Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY] if @env + options ||= {} + @by.send(:destroy_session, @env, options[:id], options) if @by + options[:id] = nil + @loaded = false end + end - DEFAULT_OPTIONS = { - :key => '_session_id', - :path => '/', - :domain => nil, - :expire_after => nil, - :secure => false, - :httponly => true, - :cookie_only => true - } + ::Rack::Session::Abstract::SessionHash.send :include, DestroyableSession + module Compatibility def initialize(app, options = {}) - @app = app - @default_options = DEFAULT_OPTIONS.merge(options) - @key = @default_options.delete(:key).freeze - @cookie_only = @default_options.delete(:cookie_only) - ensure_session_key! + options[:key] ||= '_session_id' + super end - def call(env) - prepare!(env) - response = @app.call(env) - - session_data = env[ENV_SESSION_KEY] - options = env[ENV_SESSION_OPTIONS_KEY] - - if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after] - request = ActionDispatch::Request.new(env) - - return response if (options[:secure] && !request.ssl?) - - session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded? - - sid = options[:id] || generate_sid - session_data = session_data.to_hash - - value = set_session(env, sid, session_data) - return response unless value - - cookie = { :value => value } - if options[:expire_after] - cookie[:expires] = Time.now + options.delete(:expire_after) - end - - set_cookie(request, cookie.merge!(options)) - end - - response + def generate_sid + ActiveSupport::SecureRandom.hex(16) end + end - private - - def prepare!(env) - env[ENV_SESSION_KEY] = SessionHash.new(self, env) - env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options) - end - - def generate_sid - ActiveSupport::SecureRandom.hex(16) - end - - def set_cookie(request, options) - if request.cookie_jar[@key] != options[:value] || !options[:expires].nil? - request.cookie_jar[@key] = options - end - end - - def load_session(env) - stale_session_check! do - sid = current_session_id(env) - sid, session = get_session(env, sid) - [sid, session] - end - end - - def extract_session_id(env) - stale_session_check! do - request = ActionDispatch::Request.new(env) - sid = request.cookies[@key] - sid ||= request.params[@key] unless @cookie_only - sid - end - end - - def current_session_id(env) - env[ENV_SESSION_OPTIONS_KEY][:id] - end + module StaleSessionCheck + def load_session(env) + stale_session_check! { super } + end - def ensure_session_key! - if @key.blank? - raise ArgumentError, 'A key is required to write a ' + - 'cookie containing the session data. Use ' + - 'config.session_store SESSION_STORE, { :key => ' + - '"_myapp_session" } in config/application.rb' - end - end + def extract_session_id(env) + stale_session_check! { super } + end - def stale_session_check! - yield - rescue ArgumentError => argument_error - if argument_error.message =~ %r{undefined class/module ([\w:]*\w)} - begin - # Note that the regexp does not allow $1 to end with a ':' - $1.constantize - rescue LoadError, NameError => const_error - raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n" - end - retry - else - raise + def stale_session_check! + yield + rescue ArgumentError => argument_error + if argument_error.message =~ %r{undefined class/module ([\w:]*\w)} + begin + # Note that the regexp does not allow $1 to end with a ':' + $1.constantize + rescue LoadError, NameError => const_error + raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n" end + retry + else + raise end + end + end - def exists?(env) - current_session_id(env).present? - end - - def get_session(env, sid) - raise '#get_session needs to be implemented.' - end + class AbstractStore < Rack::Session::Abstract::ID + include Compatibility + include StaleSessionCheck - def set_session(env, sid, session_data) - raise '#set_session needs to be implemented and should return ' << - 'the value to be stored in the cookie (usually the sid)' - end + def destroy_session(env, sid, options) + ActiveSupport::Deprecation.warn "Implementing #destroy in session stores is deprecated. " << + "Please implement destroy_session(env, session_id, options) instead." + destroy(env) + end - def destroy(env) - raise '#destroy needs to be implemented.' - end + def destroy(env) + raise '#destroy needs to be implemented.' + end end end end diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index ca1494425f..9c9ccc62f5 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -1,5 +1,7 @@ require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/object/blank' +require 'action_dispatch/middleware/session/abstract_store' +require 'rack/session/cookie' module ActionDispatch module Session @@ -38,58 +40,32 @@ module ActionDispatch # "rake secret" and set the key in config/initializers/secret_token.rb. # # Note that changing digest or secret invalidates all existing sessions! - class CookieStore < AbstractStore - - def initialize(app, options = {}) - super(app, options.merge!(:cookie_only => true)) - freeze - end + class CookieStore < Rack::Session::Cookie + include Compatibility + include StaleSessionCheck private - def load_session(env) - data = unpacked_cookie_data(env) - data = persistent_session_id!(data) - [data["session_id"], data] - end - - def extract_session_id(env) - if data = unpacked_cookie_data(env) - data["session_id"] - else - nil - end - end - - def unpacked_cookie_data(env) - env["action_dispatch.request.unsigned_session_cookie"] ||= begin - stale_session_check! do - request = ActionDispatch::Request.new(env) - if data = request.cookie_jar.signed[@key] - data.stringify_keys! - end - data || {} + def unpacked_cookie_data(env) + env["action_dispatch.request.unsigned_session_cookie"] ||= begin + stale_session_check! do + request = ActionDispatch::Request.new(env) + if data = request.cookie_jar.signed[@key] + data.stringify_keys! end + data || {} end end + end - def set_cookie(request, options) - request.cookie_jar.signed[@key] = options - end - - def set_session(env, sid, session_data) - persistent_session_id!(session_data, sid) - end - - def destroy(env) - # session data is stored on client; nothing to do here - end + def set_session(env, sid, session_data, options) + persistent_session_id!(session_data, sid) + end - def persistent_session_id!(data, sid=nil) - data ||= {} - data["session_id"] ||= sid || generate_sid - data - end + def set_cookie(env, session_id, cookie) + request = ActionDispatch::Request.new(env) + request.cookie_jar.signed[@key] = cookie + end end end end diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb index 28e3dbd732..4dd9a946c2 100644 --- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb @@ -1,56 +1,17 @@ +require 'action_dispatch/middleware/session/abstract_store' +require 'rack/session/memcache' + module ActionDispatch module Session - class MemCacheStore < AbstractStore + class MemCacheStore < Rack::Session::Memcache + include Compatibility + include StaleSessionCheck + def initialize(app, options = {}) require 'memcache' - - # Support old :expires option options[:expire_after] ||= options[:expires] - - super - - @default_options = { - :namespace => 'rack:session', - :memcache_server => 'localhost:11211' - }.merge(@default_options) - - @pool = options[:cache] || MemCache.new(@default_options[:memcache_server], @default_options) - unless @pool.servers.any? { |s| s.alive? } - raise "#{self} unable to find server during initialization." - end - @mutex = Mutex.new - super end - - private - def get_session(env, sid) - sid ||= generate_sid - begin - session = @pool.get(sid) || {} - rescue MemCache::MemCacheError, Errno::ECONNREFUSED - session = {} - end - [sid, session] - end - - def set_session(env, sid, session_data) - options = env['rack.session.options'] - expiry = options[:expire_after] || 0 - @pool.set(sid, session_data, expiry) - sid - rescue MemCache::MemCacheError, Errno::ECONNREFUSED - false - end - - def destroy(env) - if sid = current_session_id(env) - @pool.delete(sid) - end - rescue MemCache::MemCacheError, Errno::ECONNREFUSED - false - end - end end end diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 3489f628ed..256d0781c7 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -53,18 +53,6 @@ class CookieStoreTest < ActionDispatch::IntegrationTest def rescue_action(e) raise end end - def test_raises_argument_error_if_missing_session_key - assert_raise(ArgumentError, nil.inspect) { - ActionDispatch::Session::CookieStore.new(nil, - :key => nil, :secret => SessionSecret) - } - - assert_raise(ArgumentError, ''.inspect) { - ActionDispatch::Session::CookieStore.new(nil, - :key => '', :secret => SessionSecret) - } - end - def test_setting_session_value with_test_route_set do get '/set_session_value' diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb index 01cc14b8d6..3fc596e02a 100644 --- a/activerecord/lib/active_record/session_store.rb +++ b/activerecord/lib/active_record/session_store.rb @@ -288,6 +288,7 @@ module ActiveRecord self.session_class = Session SESSION_RECORD_KEY = 'rack.session.record' + ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY private def get_session(env, sid) @@ -299,7 +300,7 @@ module ActiveRecord end end - def set_session(env, sid, session_data) + def set_session(env, sid, session_data, options) Base.silence do record = get_session_model(env, sid) record.data = session_data @@ -316,12 +317,14 @@ module ActiveRecord sid end - def destroy(env) + def destroy_session(env, session_id, options) if sid = current_session_id(env) Base.silence do get_session_model(env, sid).destroy end end + + generate_sid unless options[:drop] end def get_session_model(env, sid) -- cgit v1.2.3 From 74dd8a3681c6984ea35c879f88c6a87521b58ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 22 Sep 2010 21:40:14 +0200 Subject: Move ETag and ConditionalGet logic from AD::Response to the middleware stack. --- actionpack/lib/action_dispatch/http/cache.rb | 22 +---- actionpack/lib/action_dispatch/http/response.rb | 2 +- actionpack/test/controller/new_base/etag_test.rb | 46 --------- actionpack/test/controller/render_test.rb | 118 ----------------------- actionpack/test/dispatch/response_test.rb | 11 +-- railties/lib/rails/application.rb | 4 +- railties/test/application/middleware_test.rb | 64 ++++++++---- 7 files changed, 51 insertions(+), 216 deletions(-) delete mode 100644 actionpack/test/controller/new_base/etag_test.rb diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index 047fab006e..4061222d11 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -50,8 +50,7 @@ module ActionDispatch if cache_control = self["Cache-Control"] cache_control.split(/,\s*/).each do |segment| first, last = segment.split("=") - last ||= true - @cache_control[first.to_sym] = last + @cache_control[first.to_sym] = last || true end end end @@ -88,28 +87,9 @@ module ActionDispatch def handle_conditional_get! if etag? || last_modified? || !@cache_control.empty? set_conditional_cache_control! - elsif nonempty_ok_response? - self.etag = body - - if request && request.etag_matches?(etag) - self.status = 304 - self.body = [] - end - - set_conditional_cache_control! - else - headers["Cache-Control"] = "no-cache" end end - def nonempty_ok_response? - @status == 200 && string_body? - end - - def string_body? - !@blank && @body.respond_to?(:all?) && @body.all? { |part| part.is_a?(String) } - end - DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate" def set_conditional_cache_control! diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 151c90167b..72871e328a 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -132,7 +132,7 @@ module ActionDispatch # :nodoc: # information. attr_accessor :charset, :content_type - CONTENT_TYPE = "Content-Type" + CONTENT_TYPE = "Content-Type" cattr_accessor(:default_charset) { "utf-8" } diff --git a/actionpack/test/controller/new_base/etag_test.rb b/actionpack/test/controller/new_base/etag_test.rb deleted file mode 100644 index 2bca5aec6a..0000000000 --- a/actionpack/test/controller/new_base/etag_test.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'abstract_unit' - -module Etags - class BasicController < ActionController::Base - self.view_paths = [ActionView::FixtureResolver.new( - "etags/basic/base.html.erb" => "Hello from without_layout.html.erb", - "layouts/etags.html.erb" => "teh <%= yield %> tagz" - )] - - def without_layout - render :action => "base" - end - - def with_layout - render :action => "base", :layout => "etags" - end - end - - class EtagTest < Rack::TestCase - describe "Rendering without any special etag options returns an etag that is an MD5 hash of its text" - - test "an action without a layout" do - get "/etags/basic/without_layout" - - body = "Hello from without_layout.html.erb" - assert_body body - assert_header "Etag", etag_for(body) - assert_status 200 - end - - test "an action with a layout" do - get "/etags/basic/with_layout" - - body = "teh Hello from without_layout.html.erb tagz" - assert_body body - assert_header "Etag", etag_for(body) - assert_status 200 - end - - private - - def etag_for(text) - %("#{Digest::MD5.hexdigest(text)}") - end - end -end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 7ca784c467..fca8de60bc 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -99,11 +99,6 @@ class TestController < ActionController::Base render :template => "test/hello_world" end - def render_hello_world_with_etag_set - response.etag = "hello_world" - render :template => "test/hello_world" - end - # :ported: compatibility def render_hello_world_with_forward_slash render :template => "/test/hello_world" @@ -1386,119 +1381,6 @@ class ExpiresInRenderTest < ActionController::TestCase end end - -class EtagRenderTest < ActionController::TestCase - tests TestController - - def setup - super - @request.host = "www.nextangle.com" - @expected_bang_etag = etag_for(expand_key([:foo, 123])) - end - - def test_render_blank_body_shouldnt_set_etag - get :blank_response - assert !@response.etag? - end - - def test_render_200_should_set_etag - get :render_hello_world_from_variable - assert_equal etag_for("hello david"), @response.headers['ETag'] - assert_equal "max-age=0, private, must-revalidate", @response.headers['Cache-Control'] - end - - def test_render_against_etag_request_should_304_when_match - @request.if_none_match = etag_for("hello david") - get :render_hello_world_from_variable - assert_equal 304, @response.status.to_i - assert @response.body.empty? - end - - def test_render_against_etag_request_should_have_no_content_length_when_match - @request.if_none_match = etag_for("hello david") - get :render_hello_world_from_variable - assert !@response.headers.has_key?("Content-Length") - end - - def test_render_against_etag_request_should_200_when_no_match - @request.if_none_match = etag_for("hello somewhere else") - get :render_hello_world_from_variable - assert_equal 200, @response.status.to_i - assert !@response.body.empty? - end - - def test_render_should_not_set_etag_when_last_modified_has_been_specified - get :render_hello_world_with_last_modified_set - assert_equal 200, @response.status.to_i - assert_not_nil @response.last_modified - assert_nil @response.etag - assert_present @response.body - end - - def test_render_with_etag - get :render_hello_world_from_variable - expected_etag = etag_for('hello david') - assert_equal expected_etag, @response.headers['ETag'] - @response = ActionController::TestResponse.new - - @request.if_none_match = expected_etag - get :render_hello_world_from_variable - assert_equal 304, @response.status.to_i - - @response = ActionController::TestResponse.new - @request.if_none_match = "\"diftag\"" - get :render_hello_world_from_variable - assert_equal 200, @response.status.to_i - end - - def render_with_404_shouldnt_have_etag - get :render_custom_code - assert_nil @response.headers['ETag'] - end - - def test_etag_should_not_be_changed_when_already_set - get :render_hello_world_with_etag_set - assert_equal etag_for("hello_world"), @response.headers['ETag'] - end - - def test_etag_should_govern_renders_with_layouts_too - get :builder_layout_test - assert_equal "\n\n

Hello

\n

This is grand!

\n\n
\n", @response.body - assert_equal etag_for("\n\n

Hello

\n

This is grand!

\n\n
\n"), @response.headers['ETag'] - end - - def test_etag_with_bang_should_set_etag - get :conditional_hello_with_bangs - assert_equal @expected_bang_etag, @response.headers["ETag"] - assert_response :success - end - - def test_etag_with_bang_should_obey_if_none_match - @request.if_none_match = @expected_bang_etag - get :conditional_hello_with_bangs - assert_response :not_modified - end - - def test_etag_with_public_true_should_set_header - get :conditional_hello_with_public_header - assert_equal "public", @response.headers['Cache-Control'] - end - - def test_etag_with_public_true_should_set_header_and_retain_other_headers - get :conditional_hello_with_public_header_and_expires_at - assert_equal "max-age=60, public", @response.headers['Cache-Control'] - end - - protected - def etag_for(text) - %("#{Digest::MD5.hexdigest(text)}") - end - - def expand_key(args) - ActiveSupport::Cache.expand_cache_key(args) - end -end - class LastModifiedRenderTest < ActionController::TestCase tests TestController diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index cd0418c338..be6398fead 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -11,9 +11,7 @@ class ResponseTest < ActiveSupport::TestCase status, headers, body = @response.to_a assert_equal 200, status assert_equal({ - "Content-Type" => "text/html; charset=utf-8", - "Cache-Control" => "max-age=0, private, must-revalidate", - "ETag" => '"65a8e27d8879283831b664bd8b7f0ad4"' + "Content-Type" => "text/html; charset=utf-8" }, headers) parts = [] @@ -27,9 +25,7 @@ class ResponseTest < ActiveSupport::TestCase status, headers, body = @response.to_a assert_equal 200, status assert_equal({ - "Content-Type" => "text/html; charset=utf-8", - "Cache-Control" => "max-age=0, private, must-revalidate", - "ETag" => '"ebb5e89e8a94e9dd22abf5d915d112b2"' + "Content-Type" => "text/html; charset=utf-8" }, headers) end @@ -41,8 +37,7 @@ class ResponseTest < ActiveSupport::TestCase status, headers, body = @response.to_a assert_equal 200, status assert_equal({ - "Content-Type" => "text/html; charset=utf-8", - "Cache-Control" => "no-cache" + "Content-Type" => "text/html; charset=utf-8" }, headers) parts = [] diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 4d04184b20..075e3c5692 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -145,8 +145,8 @@ module Rails rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache require "action_dispatch/http/rack_cache" if rack_cache + middleware.use ::Rack::Cache, rack_cache if rack_cache - middleware.use ::Rack::Cache, rack_cache if rack_cache middleware.use ::ActionDispatch::Static, config.static_asset_paths if config.serve_static_assets middleware.use ::Rack::Lock if !config.allow_concurrency middleware.use ::Rack::Runtime @@ -165,6 +165,8 @@ module Rails middleware.use ::ActionDispatch::ParamsParser middleware.use ::Rack::MethodOverride middleware.use ::ActionDispatch::Head + middleware.use ::Rack::ConditionalGet + middleware.use ::Rack::ETag, "no-cache" middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support if config.action_dispatch.best_standards_support end end diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 2372ad85b8..173ac40b12 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -36,6 +36,8 @@ module ApplicationTests "ActionDispatch::ParamsParser", "Rack::MethodOverride", "ActionDispatch::Head", + "Rack::ConditionalGet", + "Rack::ETag", "ActionDispatch::BestStandardsSupport" ], middleware end @@ -45,27 +47,7 @@ module ApplicationTests boot! - assert_equal [ - "Rack::Cache", - "ActionDispatch::Static", - "Rack::Lock", - "ActiveSupport::Cache::Strategy::LocalCache", - "Rack::Runtime", - "Rails::Rack::Logger", - "ActionDispatch::ShowExceptions", - "ActionDispatch::RemoteIp", - "Rack::Sendfile", - "ActionDispatch::Callbacks", - "ActiveRecord::ConnectionAdapters::ConnectionManagement", - "ActiveRecord::QueryCache", - "ActionDispatch::Cookies", - "ActionDispatch::Session::CookieStore", - "ActionDispatch::Flash", - "ActionDispatch::ParamsParser", - "Rack::MethodOverride", - "ActionDispatch::Head", - "ActionDispatch::BestStandardsSupport" - ], middleware + assert_equal "Rack::Cache", middleware.first end test "removing Active Record omits its middleware" do @@ -129,6 +111,46 @@ module ApplicationTests assert_equal "Rack::Config", middleware.first end + # ConditionalGet + Etag + test "conditional get + etag middlewares handle http caching based on body" do + make_basic_app + + class ::OmgController < ActionController::Base + def index + if params[:nothing] + render :text => "" + else + render :text => "OMG" + end + end + end + + etag = "5af83e3196bf99f440f31f2e1a6c9afe".inspect + + get "/" + assert_equal 200, last_response.status + assert_equal "OMG", last_response.body + assert_equal "text/html; charset=utf-8", last_response.headers["Content-Type"] + assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"] + assert_equal etag, last_response.headers["Etag"] + + get "/", {}, "HTTP_IF_NONE_MATCH" => etag + assert_equal 304, last_response.status + assert_equal "", last_response.body + assert_equal nil, last_response.headers["Content-Type"] + assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"] + assert_equal etag, last_response.headers["Etag"] + + get "/?nothing=true" + puts last_response.body + assert_equal 200, last_response.status + assert_equal "", last_response.body + assert_equal "text/html; charset=utf-8", last_response.headers["Content-Type"] + assert_equal "no-cache", last_response.headers["Cache-Control"] + assert_equal nil, last_response.headers["Etag"] + end + + # Show exceptions middleware test "show exceptions middleware filter backtrace before logging" do my_middleware = Struct.new(:app) do def call(env) -- cgit v1.2.3 From 653acac069e66f53b791caa4838a1e25de905f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 3 Oct 2010 21:45:27 +0200 Subject: Solve some warnings and a failing test. --- actionpack/lib/action_controller/test_case.rb | 1 + actionpack/lib/action_dispatch/http/request.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index d7b54c2abc..6061945622 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -191,6 +191,7 @@ module ActionController DEFAULT_OPTIONS = Rack::Session::Abstract::ID::DEFAULT_OPTIONS def initialize(session = {}) + @env, @by = nil, nil replace(session.stringify_keys) @loaded = true end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 09d6ba8223..bbcdefb190 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -199,7 +199,7 @@ module ActionDispatch # TODO This should be broken apart into AD::Request::Session and probably # be included by the session middleware. def reset_session - session.destroy if session + session.destroy if session && session.respond_to?(:destroy) self.session = {} @env['action_dispatch.request.flash_hash'] = nil end -- cgit v1.2.3 From adfd43a4daf08cc9a801a0b6a039dd109ce4e81f Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 30 Sep 2010 19:17:36 +0200 Subject: Add documentation on app_generators --- railties/lib/rails/engine.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 9ae235b818..ba89bce928 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -47,6 +47,26 @@ module Rails # end # end # + # == Generators + # + # You can set up generators for engine with config.generators method: + # + # class MyEngine < Rails::Engine + # config.generators do |g| + # g.orm :active_record + # g.template_engine :erb + # g.test_framework :test_unit + # end + # end + # + # You can also set generators for application by using config.app_generators: + # + # class MyEngine < Rails::Engine + # # note that you can also pass block to app_generators in the same way you + # # can pass it to generators method + # config.app_generators.orm :datamapper + # end + # # == Paths # # Since Rails 3.0, both your Application and Engines do not have hardcoded paths. -- cgit v1.2.3 From 18a7b767e8ad545702c1025fc9cc7a1cc3c64f28 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 14:11:34 -0700 Subject: moving fake model to the correct file --- actionpack/test/controller/record_identifier_test.rb | 13 ------------- actionpack/test/lib/controller/fake_models.rb | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb index e46e317e31..f3e5ff8a47 100644 --- a/actionpack/test/controller/record_identifier_test.rb +++ b/actionpack/test/controller/record_identifier_test.rb @@ -1,19 +1,6 @@ require 'abstract_unit' require 'controller/fake_models' -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 RecordIdentifierTest < Test::Unit::TestCase include ActionController::RecordIdentifier diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index 8cb3b4940a..cf3f2f7fa4 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -130,6 +130,20 @@ 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 -- cgit v1.2.3 From 83633b807a3b08aaf5554c0fc793583a064c2472 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 14:12:06 -0700 Subject: avoid creating objects when we can --- activerecord/lib/active_record/base.rb | 3 +-- .../lib/active_record/relation/predicate_builder.rb | 16 +++++----------- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 80ddd5e7ab..f6d9050828 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1270,8 +1270,7 @@ MSG attrs = expand_hash_conditions_for_aggregates(attrs) table = Arel::Table.new(self.table_name, :engine => arel_engine, :as => default_table_name) - builder = PredicateBuilder.new(arel_engine) - builder.build_from_hash(attrs, table).map{ |b| b.to_sql }.join(' AND ') + PredicateBuilder.build_from_hash(arel_engine, attrs, table).map{ |b| b.to_sql }.join(' AND ') end alias_method :sanitize_sql_hash, :sanitize_sql_hash_for_conditions diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 0d1307d87e..c5428dccd6 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -1,23 +1,18 @@ module ActiveRecord - class PredicateBuilder - - def initialize(engine) - @engine = engine - end - - def build_from_hash(attributes, default_table) + class PredicateBuilder # :nodoc: + def self.build_from_hash(engine, attributes, default_table) predicates = attributes.map do |column, value| table = default_table if value.is_a?(Hash) - table = Arel::Table.new(column, :engine => @engine) - build_from_hash(value, table) + table = Arel::Table.new(column, :engine => engine) + build_from_hash(engine, value, table) else column = column.to_s if column.include?('.') table_name, column = column.split('.', 2) - table = Arel::Table.new(table_name, :engine => @engine) + table = Arel::Table.new(table_name, :engine => engine) end attribute = table[column] || Arel::Attribute.new(table, column) @@ -38,6 +33,5 @@ module ActiveRecord predicates.flatten end - end end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index c8174b5f45..001207514d 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -204,7 +204,7 @@ module ActiveRecord [@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))] when Hash attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts) - PredicateBuilder.new(table.engine).build_from_hash(attributes, table) + PredicateBuilder.build_from_hash(table.engine, attributes, table) else [opts] end -- cgit v1.2.3 From bd78d24bd8168b43ceb167e8d8b3e542486a1bba Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 14:27:54 -0700 Subject: be kind to the garbage collector and reuse our visitor object --- activerecord/lib/active_record/base.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index f6d9050828..ff6be4ff19 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1270,7 +1270,10 @@ MSG attrs = expand_hash_conditions_for_aggregates(attrs) table = Arel::Table.new(self.table_name, :engine => arel_engine, :as => default_table_name) - PredicateBuilder.build_from_hash(arel_engine, attrs, table).map{ |b| b.to_sql }.join(' AND ') + viz = Arel::Visitors.for(arel_engine) + PredicateBuilder.build_from_hash(arel_engine, attrs, table).map { |b| + viz.accept b + }.join(' AND ') end alias_method :sanitize_sql_hash, :sanitize_sql_hash_for_conditions -- cgit v1.2.3 From 7836616a6473527f1f42672e54cf6971c05f6fdf Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 15:18:32 -0700 Subject: remove a few function calls --- activerecord/lib/active_record/schema_dumper.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 6faa88ab78..437f01b657 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -176,9 +176,11 @@ HEADER def indexes(table, stream) if (indexes = @connection.indexes(table)).any? add_index_statements = indexes.map do |index| - statement_parts = [ ('add_index ' + index.table.inspect) ] - statement_parts << index.columns.inspect - statement_parts << (':name => ' + index.name.inspect) + statement_parts = [ + ('add_index ' + index.table.inspect), + index.columns.inspect, + (':name => ' + index.name.inspect), + ] statement_parts << ':unique => true' if index.unique index_lengths = index.lengths.compact if index.lengths.is_a?(Array) -- cgit v1.2.3 From 5154a464cc405438336739ba0d563f87d9fc2d96 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 15:35:56 -0700 Subject: lengths will be nil or an array --- activerecord/lib/active_record/schema_dumper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 437f01b657..f5331bb8a9 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -183,8 +183,8 @@ HEADER ] statement_parts << ':unique => true' if index.unique - index_lengths = index.lengths.compact if index.lengths.is_a?(Array) - statement_parts << (':length => ' + Hash[*index.columns.zip(index.lengths).flatten].inspect) if index_lengths.present? + index_lengths = (index.lengths || []).compact + statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty? ' ' + statement_parts.join(', ') end -- cgit v1.2.3 From a6c42c82678f11271fe71923a200eb135f2f1c0e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 15:38:17 -0700 Subject: two argument String#slice is faster than single argument, also avoid creating a Range object --- actionpack/lib/action_view/test_case.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 731f91df30..4026f7a40e 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -201,7 +201,7 @@ module ActionView # frameworks. def view_assigns Hash[_user_defined_ivars.map do |var| - [var[1..-1].to_sym, instance_variable_get(var)] + [var[1, var.length].to_sym, instance_variable_get(var)] end] end -- cgit v1.2.3 From 8beda11fd3cbd2db21a7a7a7ae9823edbbc2dd5e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 16:13:45 -0700 Subject: no need to differentiate between nil and false in this case --- activerecord/lib/active_record/migration.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index e708b3fbcf..b075632de6 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -570,7 +570,7 @@ module ActiveRecord current = migrations.detect { |m| m.version == current_version } target = migrations.detect { |m| m.version == @target_version } - if target.nil? && !@target_version.nil? && @target_version > 0 + if target.nil? && @target_version && @target_version > 0 raise UnknownMigrationVersionError.new(@target_version) end @@ -579,7 +579,7 @@ module ActiveRecord runnable = migrations[start..finish] # skip the last migration if we're headed down, but not ALL the way down - runnable.pop if down? && !target.nil? + runnable.pop if down? && target runnable.each do |migration| Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger -- cgit v1.2.3 From 341e71a1b9a3d0ad367f79ff89b1c97fe6890905 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 16:23:07 -0700 Subject: dry up some migration logic --- activerecord/lib/active_record/migration.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index b075632de6..6744a0783a 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -584,11 +584,13 @@ module ActiveRecord runnable.each do |migration| Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger + seen = migrated.include?(migration.version.to_i) + # On our way up, we skip migrating the ones we've already migrated - next if up? && migrated.include?(migration.version.to_i) + next if up? && seen # On our way down, we skip reverting the ones we've never migrated - if down? && !migrated.include?(migration.version.to_i) + if down? && !seen migration.announce 'never migrated, skipping'; migration.write next end -- cgit v1.2.3 From e6583901e58afe58aeb07f1ba1bd9f103492b98b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 16:32:27 -0700 Subject: convertion MigrationProxy to a Struct, initialize instance variables --- activerecord/lib/active_record/migration.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 6744a0783a..5458bba51f 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -419,9 +419,12 @@ module ActiveRecord # MigrationProxy is used to defer loading of the actual migration classes # until they are needed - class MigrationProxy + class MigrationProxy < Struct.new(:name, :version, :filename, :scope) - attr_accessor :name, :version, :filename, :scope + def initialize(name, version, filename, scope) + super + @migration = nil + end delegate :migrate, :announce, :write, :to=>:migration @@ -518,11 +521,7 @@ module ActiveRecord raise DuplicateMigrationNameError.new(name.camelize) end - migration = MigrationProxy.new - migration.name = name.camelize - migration.version = version - migration.filename = file - migration.scope = scope + migration = MigrationProxy.new(name.camelize, version, file, scope) klasses << migration end -- cgit v1.2.3 From 40761c4bf39826254b7a5266210f91742591f58c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 16:36:43 -0700 Subject: reduce the number of calls to camelize --- activerecord/lib/active_record/migration.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 5458bba51f..3bfd1851b5 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -509,6 +509,7 @@ module ActiveRecord migrations = files.inject([]) do |klasses, file| version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?.rb/).first + name = name.camelize raise IllegalMigrationNameError.new(file) unless version version = version.to_i @@ -517,11 +518,11 @@ module ActiveRecord raise DuplicateMigrationVersionError.new(version) end - if klasses.detect { |m| m.name == name.camelize && m.scope == scope } - raise DuplicateMigrationNameError.new(name.camelize) + if klasses.detect { |m| m.name == name && m.scope == scope } + raise DuplicateMigrationNameError.new(name) end - migration = MigrationProxy.new(name.camelize, version, file, scope) + migration = MigrationProxy.new(name, version, file, scope) klasses << migration end -- cgit v1.2.3 From 365c93b7cdaa161c77c157c7cc385221ebbc33c7 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 16:39:48 -0700 Subject: speed up duplicate migration detection --- activerecord/lib/active_record/migration.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 3bfd1851b5..7a1504430b 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -507,6 +507,8 @@ module ActiveRecord def migrations(path) files = Dir["#{path}/[0-9]*_*.rb"] + seen = Hash.new false + migrations = files.inject([]) do |klasses, file| version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?.rb/).first name = name.camelize @@ -514,13 +516,10 @@ module ActiveRecord raise IllegalMigrationNameError.new(file) unless version version = version.to_i - if klasses.detect { |m| m.version == version } - raise DuplicateMigrationVersionError.new(version) - end + raise DuplicateMigrationVersionError.new(version) if seen[version] + raise DuplicateMigrationNameError.new(name) if seen[[name, scope]] - if klasses.detect { |m| m.name == name && m.scope == scope } - raise DuplicateMigrationNameError.new(name) - end + seen[version] = seen[[name, scope]] = true migration = MigrationProxy.new(name, version, file, scope) klasses << migration -- cgit v1.2.3 From 69a2c6b0419177448d9811745cf4035d46b68bbd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 3 Oct 2010 16:41:59 -0700 Subject: converting inject([]) to map --- activerecord/lib/active_record/migration.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 7a1504430b..9ac18f9939 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -509,20 +509,19 @@ module ActiveRecord seen = Hash.new false - migrations = files.inject([]) do |klasses, file| + migrations = files.map do |file| version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?.rb/).first - name = name.camelize raise IllegalMigrationNameError.new(file) unless version version = version.to_i + name = name.camelize raise DuplicateMigrationVersionError.new(version) if seen[version] raise DuplicateMigrationNameError.new(name) if seen[[name, scope]] seen[version] = seen[[name, scope]] = true - migration = MigrationProxy.new(name, version, file, scope) - klasses << migration + MigrationProxy.new(name, version, file, scope) end migrations.sort_by(&:version) -- cgit v1.2.3 From 3986fcb935c8d5b89ecb86b2f1cbb463460182de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 4 Oct 2010 08:47:36 +0200 Subject: Initialize sid should just skip instance variables. --- .../lib/action_dispatch/middleware/session/abstract_store.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 679ba7fc8e..64d3a87fd0 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -31,6 +31,13 @@ module ActionDispatch def generate_sid ActiveSupport::SecureRandom.hex(16) end + + protected + + def initialize_sid + @default_options.delete(:sidbits) + @default_options.delete(:secure_random) + end end module StaleSessionCheck -- cgit v1.2.3 From 10d014acb875c8201b33f5ffe7b08dbcd81b2875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 4 Oct 2010 13:46:37 +0200 Subject: Update to Thor 0.14.3. --- railties/railties.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/railties.gemspec b/railties/railties.gemspec index 73acb73dec..d26c1bcdbc 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |s| s.has_rdoc = false s.add_dependency('rake', '>= 0.8.7') - s.add_dependency('thor', '~> 0.14.2') + s.add_dependency('thor', '~> 0.14.3') s.add_dependency('activesupport', version) s.add_dependency('actionpack', version) end -- cgit v1.2.3 From 0b51f3cc73ac21ed56b45a15fcce1d31beb7170c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 4 Oct 2010 18:06:04 +0200 Subject: Ensure the proper content type is returned for static files. --- .../lib/action_dispatch/middleware/static.rb | 6 +-- actionpack/test/dispatch/static_test.rb | 47 +++++++++++++--------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index cf13938331..913b899e20 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -6,13 +6,13 @@ module ActionDispatch @at, @root = at.chomp('/'), root.chomp('/') @compiled_at = (Regexp.compile(/^#{Regexp.escape(at)}/) unless @at.blank?) @compiled_root = Regexp.compile(/^#{Regexp.escape(root)}/) - @file_server = ::Rack::File.new(root) + @file_server = ::Rack::File.new(@root) end def match?(path) path = path.dup - if @compiled_at.blank? || path.sub!(@compiled_at, '') - full_path = File.join(@root, ::Rack::Utils.unescape(path)) + if !@compiled_at || path.sub!(@compiled_at, '') + full_path = path.empty? ? @root : File.join(@root, ::Rack::Utils.unescape(path)) paths = "#{full_path}#{ext}" matches = Dir[paths] diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index 2eb82fc5d8..655745a848 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -2,30 +2,37 @@ require 'abstract_unit' module StaticTests def test_serves_dynamic_content - assert_equal "Hello, World!", get("/nofile") + assert_equal "Hello, World!", get("/nofile").body end def test_serves_static_index_at_root - assert_equal "/index.html", get("/index.html") - assert_equal "/index.html", get("/index") - assert_equal "/index.html", get("/") + assert_html "/index.html", get("/index.html") + assert_html "/index.html", get("/index") + assert_html "/index.html", get("/") + assert_html "/index.html", get("") end def test_serves_static_file_in_directory - assert_equal "/foo/bar.html", get("/foo/bar.html") - assert_equal "/foo/bar.html", get("/foo/bar/") - assert_equal "/foo/bar.html", get("/foo/bar") + assert_html "/foo/bar.html", get("/foo/bar.html") + assert_html "/foo/bar.html", get("/foo/bar/") + assert_html "/foo/bar.html", get("/foo/bar") end def test_serves_static_index_file_in_directory - assert_equal "/foo/index.html", get("/foo/index.html") - assert_equal "/foo/index.html", get("/foo/") - assert_equal "/foo/index.html", get("/foo") + assert_html "/foo/index.html", get("/foo/index.html") + assert_html "/foo/index.html", get("/foo/") + assert_html "/foo/index.html", get("/foo") end private + + def assert_html(body, response) + assert_equal body, response.body + assert_equal "text/html", response.headers["Content-Type"] + end + def get(path) - Rack::MockRequest.new(@app).request("GET", path).body + Rack::MockRequest.new(@app).request("GET", path) end end @@ -59,16 +66,16 @@ class MultipleDirectorisStaticTest < ActiveSupport::TestCase include StaticTests test "serves files from other mounted directories" do - assert_equal "/blog/index.html", get("/blog/index.html") - assert_equal "/blog/index.html", get("/blog/index") - assert_equal "/blog/index.html", get("/blog/") + assert_html "/blog/index.html", get("/blog/index.html") + assert_html "/blog/index.html", get("/blog/index") + assert_html "/blog/index.html", get("/blog/") - assert_equal "/blog/blog.html", get("/blog/blog/") - assert_equal "/blog/blog.html", get("/blog/blog.html") - assert_equal "/blog/blog.html", get("/blog/blog") + assert_html "/blog/blog.html", get("/blog/blog/") + assert_html "/blog/blog.html", get("/blog/blog.html") + assert_html "/blog/blog.html", get("/blog/blog") - assert_equal "/blog/subdir/index.html", get("/blog/subdir/index.html") - assert_equal "/blog/subdir/index.html", get("/blog/subdir/") - assert_equal "/blog/subdir/index.html", get("/blog/subdir") + assert_html "/blog/subdir/index.html", get("/blog/subdir/index.html") + assert_html "/blog/subdir/index.html", get("/blog/subdir/") + assert_html "/blog/subdir/index.html", get("/blog/subdir") end end -- cgit v1.2.3 From 848e48ec9c20b6de15768c7bc33a5c54b242afac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 4 Oct 2010 18:08:03 +0200 Subject: Link to rack from github for this while. --- railties/lib/rails/generators/rails/app/templates/Gemfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 1dbf27d978..40213b1261 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -3,15 +3,18 @@ source 'http://rubygems.org' <%- if options.dev? -%> gem 'rails', :path => '<%= Rails::Generators::RAILS_DEV_PATH %>' gem 'arel', :git => 'git://github.com/rails/arel.git' +gem "rack", :git => "git://github.com/rack/rack.git" <%- elsif options.edge? -%> gem 'rails', :git => 'git://github.com/rails/rails.git' gem 'arel', :git => 'git://github.com/rails/arel.git' +gem "rack", :git => "git://github.com/rack/rack.git" <%- else -%> gem 'rails', '<%= Rails::VERSION::STRING %>' # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' # gem 'arel', :git => 'git://github.com/rails/arel.git' +# gem "rack", :git => "git://github.com/rack/rack.git" <%- end -%> <% unless options[:skip_active_record] -%> -- cgit v1.2.3 From ccf228b0276afb8bb00d14f1b861015b1ef5ab76 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 09:28:21 -0700 Subject: [#5406 state:resolved] calling the correct method on minitest to obtain the test name --- activesupport/test/test_case_test.rb | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 activesupport/test/test_case_test.rb diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb new file mode 100644 index 0000000000..8a5006cdf2 --- /dev/null +++ b/activesupport/test/test_case_test.rb @@ -0,0 +1,38 @@ +require 'abstract_unit' + +module ActiveSupport + class TestCaseTest < ActiveSupport::TestCase + class FakeRunner + attr_reader :puked + + def initialize + @puked = [] + end + + def puke(klass, name, e) + @puked << [klass, name, e] + end + end + + if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions + def test_callback_with_exception + tc = Class.new(TestCase) do + setup :bad_callback + def bad_callback; raise 'oh noes' end + def test_true; assert true end + end + + test_name = 'test_true' + fr = FakeRunner.new + + test = tc.new test_name + test.run fr + klass, name, exception = *fr.puked.first + + assert_equal tc, klass + assert_equal test_name, name + assert_equal 'oh noes', exception.message + end + end + end +end -- cgit v1.2.3 From b7c49cedba4a9acd001df65a102d79611598f472 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 09:29:37 -0700 Subject: calling correct method on minitest for test name when teardown callback fails --- activesupport/test/test_case_test.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 8a5006cdf2..7e65c63062 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -33,6 +33,25 @@ module ActiveSupport assert_equal test_name, name assert_equal 'oh noes', exception.message end + + def test_teardown_callback_with_exception + tc = Class.new(TestCase) do + teardown :bad_callback + def bad_callback; raise 'oh noes' end + def test_true; assert true end + end + + test_name = 'test_true' + fr = FakeRunner.new + + test = tc.new test_name + test.run fr + klass, name, exception = *fr.puked.first + + assert_equal tc, klass + assert_equal test_name, name + assert_equal 'oh noes', exception.message + end end end end -- cgit v1.2.3 From 6644675831a5a87c77f66697124d95ab37202509 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 24 Sep 2010 14:06:47 -0700 Subject: Template::Error is also used if rendering fails. --- actionpack/lib/action_view/template/error.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb index 423e1e0bf5..ff256738a9 100644 --- a/actionpack/lib/action_view/template/error.rb +++ b/actionpack/lib/action_view/template/error.rb @@ -43,8 +43,9 @@ module ActionView end class Template - # The Template::Error exception is raised when the compilation of the template fails. This exception then gathers a - # bunch of intimate details and uses it to report a very precise exception message. + # The Template::Error exception is raised when the compilation or rendering of the template + # fails. This exception then gathers a bunch of intimate details and uses it to report a + # precise exception message. class Error < ActionViewError #:nodoc: SOURCE_CODE_RADIUS = 3 -- cgit v1.2.3 From b1047888fb4ddf9ba2cbdd4cd596ad4f1aca8645 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 4 Oct 2010 11:14:42 -0700 Subject: `render :text => proc { ... }` is no longer supported. --- actionpack/lib/action_controller/metal/streaming.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb index 2013da3adb..312dc8eb3e 100644 --- a/actionpack/lib/action_controller/metal/streaming.rb +++ b/actionpack/lib/action_controller/metal/streaming.rb @@ -101,10 +101,6 @@ module ActionController #:nodoc: # send_data image.data, :type => image.content_type, :disposition => 'inline' # # See +send_file+ for more information on HTTP Content-* headers and caching. - # - # Tip: if you want to stream large amounts of on-the-fly generated - # data to the browser, then use render :text => proc { ... } - # instead. See ActionController::Base#render for more information. def send_data(data, options = {}) #:doc: send_file_headers! options.dup render options.slice(:status, :content_type).merge(:text => data) -- cgit v1.2.3 From 33aaa15f6208d65ca043ffcc5dc161d410963e9d Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Mon, 4 Oct 2010 13:35:38 -0400 Subject: Convert to model before calling model_name on a record in ActiveModel::Naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activemodel/lib/active_model/naming.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index 2d580fd325..adb71f788f 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -129,7 +129,11 @@ module ActiveModel private def self.model_name_from_record_or_class(record_or_class) - (record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name + (record_or_class.is_a?(Class) ? record_or_class : convert_to_model(record_or_class).class).model_name + end + + def self.convert_to_model(object) + object.respond_to?(:to_model) ? object.to_model : object end end -- cgit v1.2.3 From 21cb1d40b9c57ab814c69d01a242b50e27e8283b Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Mon, 4 Oct 2010 15:04:39 -0400 Subject: Test to_model being called in ActiveModel::Naming helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activemodel/test/cases/naming_test.rb | 4 ++++ activemodel/test/models/track_back.rb | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb index 40ce4c0e2d..a7dde2c433 100644 --- a/activemodel/test/cases/naming_test.rb +++ b/activemodel/test/cases/naming_test.rb @@ -125,6 +125,10 @@ class NamingHelpersTest < Test::Unit::TestCase @param_key = 'contact' end + def test_to_model_called_on_record + assert_equal 'post_named_track_backs', plural(Post::TrackBack.new) + end + def test_singular assert_equal @singular, singular(@record) end diff --git a/activemodel/test/models/track_back.rb b/activemodel/test/models/track_back.rb index d137e4ff8f..545acd1655 100644 --- a/activemodel/test/models/track_back.rb +++ b/activemodel/test/models/track_back.rb @@ -1,4 +1,11 @@ class Post class TrackBack + def to_model + NamedTrackBack.new(self) + end + end + + class NamedTrackBack + extend ActiveModel::Naming end end \ No newline at end of file -- cgit v1.2.3 From 232e56ce872383ef1805d1a7ef0fbf5475e5cfb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 4 Oct 2010 22:32:29 +0200 Subject: No need to pass self as parameter here. --- activemodel/test/models/track_back.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemodel/test/models/track_back.rb b/activemodel/test/models/track_back.rb index 545acd1655..768c96ecf0 100644 --- a/activemodel/test/models/track_back.rb +++ b/activemodel/test/models/track_back.rb @@ -1,7 +1,7 @@ class Post class TrackBack def to_model - NamedTrackBack.new(self) + NamedTrackBack.new end end -- cgit v1.2.3 From d8135eb452bfb956e093c61cf12adb9b0da6e28b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 15:19:27 -0700 Subject: * + flatten is not required in >= Ruby 1.8.7 --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 194842a9a0..95b6a8137d 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -975,7 +975,7 @@ module ActiveRecord def select(sql, name = nil) fields, rows = select_raw(sql, name) rows.map do |row| - Hash[*fields.zip(row).flatten] + Hash[fields.zip(row)] end end -- cgit v1.2.3 From e7d860c6bed99b0d44680097fcc1cfd7c1fa07ef Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 15:25:20 -0700 Subject: create fewer objects, call fewer methods in extract_pg_identifier_from_name --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 95b6a8137d..5f14284615 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1017,11 +1017,11 @@ module ActiveRecord end def extract_pg_identifier_from_name(name) - match_data = name[0,1] == '"' ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/) + match_data = name.start_with?('"') ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/) if match_data - rest = name[match_data[0].length..-1] - rest = rest[1..-1] if rest[0,1] == "." + rest = name[match_data[0].length, name.length] + rest = rest[1, rest.length] if rest.start_with? "." [match_data[1], (rest.length > 0 ? rest : nil)] end end -- cgit v1.2.3 From 28bb1885f5a35d0adecd35d38b73751d737891c4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 16:08:01 -0700 Subject: avoid method call to compact --- actionpack/lib/action_dispatch/routing/mapper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 47aed0273c..bf10f81127 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -171,13 +171,13 @@ module ActionDispatch end def blocks + block = @scope[:blocks] || [] + if @options[:constraints].present? && !@options[:constraints].is_a?(Hash) - block = @options[:constraints] - else - block = nil + block << @options[:constraints] end - ((@scope[:blocks] || []) + [ block ]).compact + block end def constraints -- cgit v1.2.3 From f9734f2b0f5326c399d1c1cccba8b6d8e7d9bdd4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 16:30:16 -0700 Subject: adding tests for uploaded file --- actionpack/test/dispatch/uploaded_file_test.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 actionpack/test/dispatch/uploaded_file_test.rb diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb new file mode 100644 index 0000000000..def6289fb3 --- /dev/null +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -0,0 +1,25 @@ +require 'abstract_unit' + +module ActionDispatch + class UploadedFileTest < ActiveSupport::TestCase + def test_original_filename + uf = Http::UploadedFile.new(:filename => 'foo') + assert_equal 'foo', uf.original_filename + end + + def test_content_type + uf = Http::UploadedFile.new(:type => 'foo') + assert_equal 'foo', uf.content_type + end + + def test_headers + uf = Http::UploadedFile.new(:head => 'foo') + assert_equal 'foo', uf.headers + end + + def test_tempfile + uf = Http::UploadedFile.new(:tempfile => 'foo') + assert_equal 'foo', uf.tempfile + end + end +end -- cgit v1.2.3 From 2a3022db7f2ddc0fc0e678ea757f97902c5f5c01 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 16:56:45 -0700 Subject: delegate to the @tempfile instance variable --- actionpack/lib/action_dispatch/http/upload.rb | 18 +++++------------- actionpack/test/dispatch/uploaded_file_test.rb | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index 49465d820e..bfbe7c5305 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -2,27 +2,19 @@ require 'active_support/core_ext/object/blank' module ActionDispatch module Http - class UploadedFile < Tempfile + class UploadedFile attr_accessor :original_filename, :content_type, :tempfile, :headers def initialize(hash) @original_filename = hash[:filename] @content_type = hash[:type] @headers = hash[:head] - - # To the untrained eye, this may appear as insanity. Given the alternatives, - # such as busting the method cache on every request or breaking backwards - # compatibility with is_a?(Tempfile), this solution is the best available - # option. - # - # TODO: Deprecate is_a?(Tempfile) and define a real API for this parameter - tempfile = hash[:tempfile] - tempfile.instance_variables.each do |ivar| - instance_variable_set(ivar, tempfile.instance_variable_get(ivar)) - end + @tempfile = hash[:tempfile] end - alias local_path path + def method_missing(name, *args, &block) + @tempfile.send(name, *args, &block) + end end module Upload diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index def6289fb3..d04d5a8650 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -21,5 +21,23 @@ module ActionDispatch uf = Http::UploadedFile.new(:tempfile => 'foo') assert_equal 'foo', uf.tempfile end + + def test_delegates_to_tempfile + tf = Class.new { def tenderlove; 'thunderhorse' end } + uf = Http::UploadedFile.new(:tempfile => tf.new) + assert_equal 'thunderhorse', uf.tenderlove + end + + def test_delegates_to_tempfile_with_params + tf = Class.new { def tenderlove *args; args end } + uf = Http::UploadedFile.new(:tempfile => tf.new) + assert_equal %w{ thunder horse }, uf.tenderlove(*%w{ thunder horse }) + end + + def test_delegates_to_tempfile_with_block + tf = Class.new { def tenderlove; yield end } + uf = Http::UploadedFile.new(:tempfile => tf.new) + assert_equal('thunderhorse', uf.tenderlove { 'thunderhorse' }) + end end end -- cgit v1.2.3 From 876acf001a32887679e259f83a2fbad750ac2e67 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 16:57:11 -0700 Subject: if it walks like a duck and talks like a duck, it must be a duck --- actionpack/test/dispatch/request/multipart_params_parsing_test.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index 073dd3ddad..3ff558ec5a 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -36,7 +36,6 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest assert_equal 'bar', params['foo'] file = params['file'] - assert_kind_of Tempfile, file assert_equal 'file.txt', file.original_filename assert_equal "text/plain", file.content_type assert_equal 'contents', file.read @@ -49,8 +48,6 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest file = params['file'] foo = params['foo'] - assert_kind_of Tempfile, file - assert_equal 'file.txt', file.original_filename assert_equal "text/plain", file.content_type @@ -64,8 +61,6 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest file = params['file'] - assert_kind_of Tempfile, file - assert_equal 'file.txt', file.original_filename assert_equal "text/plain", file.content_type assert_equal(('a' * 20480), file.read) @@ -77,13 +72,11 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest assert_equal 'bar', params['foo'] file = params['file'] - assert_kind_of Tempfile, file assert_equal 'file.csv', file.original_filename assert_nil file.content_type assert_equal 'contents', file.read file = params['flowers'] - assert_kind_of Tempfile, file assert_equal 'flowers.jpg', file.original_filename assert_equal "image/jpeg", file.content_type assert_equal 19512, file.size -- cgit v1.2.3 From 8a9747021085c569f0118db1093bc12cfa2ba915 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 17:08:25 -0700 Subject: raising an argument error if tempfile is not provided --- actionpack/lib/action_dispatch/http/upload.rb | 1 + actionpack/test/dispatch/uploaded_file_test.rb | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index bfbe7c5305..d4fabe1eaf 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -10,6 +10,7 @@ module ActionDispatch @content_type = hash[:type] @headers = hash[:head] @tempfile = hash[:tempfile] + raise(ArgumentError, ':tempfile is required') unless @tempfile end def method_missing(name, *args, &block) diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index d04d5a8650..4173ce0a44 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -2,18 +2,24 @@ require 'abstract_unit' module ActionDispatch class UploadedFileTest < ActiveSupport::TestCase + def test_constructor_with_argument_error + assert_raises(ArgumentError) do + Http::UploadedFile.new({}) + end + end + def test_original_filename - uf = Http::UploadedFile.new(:filename => 'foo') + uf = Http::UploadedFile.new(:filename => 'foo', :tempfile => Object.new) assert_equal 'foo', uf.original_filename end def test_content_type - uf = Http::UploadedFile.new(:type => 'foo') + uf = Http::UploadedFile.new(:type => 'foo', :tempfile => Object.new) assert_equal 'foo', uf.content_type end def test_headers - uf = Http::UploadedFile.new(:head => 'foo') + uf = Http::UploadedFile.new(:head => 'foo', :tempfile => Object.new) assert_equal 'foo', uf.headers end -- cgit v1.2.3 From 3370ad0b1e883c9ec24c771f6c52b296a71eff40 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 17:11:50 -0700 Subject: making sure respond_to? works properly --- actionpack/lib/action_dispatch/http/upload.rb | 5 +++++ actionpack/test/dispatch/uploaded_file_test.rb | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index d4fabe1eaf..53f8039121 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -13,7 +13,12 @@ module ActionDispatch raise(ArgumentError, ':tempfile is required') unless @tempfile end + def respond_to?(name) + super || @tempfile.respond_to?(name) + end + def method_missing(name, *args, &block) + return super unless respond_to?(name) @tempfile.send(name, *args, &block) end end diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index 4173ce0a44..c81797a73f 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -45,5 +45,20 @@ module ActionDispatch uf = Http::UploadedFile.new(:tempfile => tf.new) assert_equal('thunderhorse', uf.tenderlove { 'thunderhorse' }) end + + def test_delegate_respects_respond_to? + tf = Class.new { def tenderlove; yield end; private :tenderlove } + uf = Http::UploadedFile.new(:tempfile => tf.new) + assert_raises(NoMethodError) do + uf.tenderlove + end + end + + def test_respond_to? + tf = Class.new { def tenderlove; yield end } + uf = Http::UploadedFile.new(:tempfile => tf.new) + assert uf.respond_to?(:headers), 'responds to headers' + assert uf.respond_to?(:tenderlove), 'responds to tenderlove' + end end end -- cgit v1.2.3 From 12173396163616e077f761e190c13beb43d536bd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 19:28:40 -0700 Subject: only forwarding enough methods to work. People should grab the delegate tempfile if they really need to do hard work --- actionpack/lib/action_dispatch/http/upload.rb | 13 ++++++++----- actionpack/test/dispatch/uploaded_file_test.rb | 22 ++++++++-------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index 53f8039121..84e58d7d6a 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -13,13 +13,16 @@ module ActionDispatch raise(ArgumentError, ':tempfile is required') unless @tempfile end - def respond_to?(name) - super || @tempfile.respond_to?(name) + def read(*args) + @tempfile.read(*args) end - def method_missing(name, *args, &block) - return super unless respond_to?(name) - @tempfile.send(name, *args, &block) + def rewind + @tempfile.rewind + end + + def size + @tempfile.size end end diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index c81797a73f..b51697b930 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -29,36 +29,30 @@ module ActionDispatch end def test_delegates_to_tempfile - tf = Class.new { def tenderlove; 'thunderhorse' end } + tf = Class.new { def read; 'thunderhorse' end } uf = Http::UploadedFile.new(:tempfile => tf.new) - assert_equal 'thunderhorse', uf.tenderlove + assert_equal 'thunderhorse', uf.read end def test_delegates_to_tempfile_with_params - tf = Class.new { def tenderlove *args; args end } + tf = Class.new { def read *args; args end } uf = Http::UploadedFile.new(:tempfile => tf.new) - assert_equal %w{ thunder horse }, uf.tenderlove(*%w{ thunder horse }) - end - - def test_delegates_to_tempfile_with_block - tf = Class.new { def tenderlove; yield end } - uf = Http::UploadedFile.new(:tempfile => tf.new) - assert_equal('thunderhorse', uf.tenderlove { 'thunderhorse' }) + assert_equal %w{ thunder horse }, uf.read(*%w{ thunder horse }) end def test_delegate_respects_respond_to? - tf = Class.new { def tenderlove; yield end; private :tenderlove } + tf = Class.new { def read; yield end; private :read } uf = Http::UploadedFile.new(:tempfile => tf.new) assert_raises(NoMethodError) do - uf.tenderlove + uf.read end end def test_respond_to? - tf = Class.new { def tenderlove; yield end } + tf = Class.new { def read; yield end } uf = Http::UploadedFile.new(:tempfile => tf.new) assert uf.respond_to?(:headers), 'responds to headers' - assert uf.respond_to?(:tenderlove), 'responds to tenderlove' + assert uf.respond_to?(:read), 'responds to read' end end end -- cgit v1.2.3 From 5769636663c2849fd132fd593c0f6d29702b7cf1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 19:32:49 -0700 Subject: fixing a few test warnings --- actionpack/test/controller/filters_test.rb | 4 ++-- actionpack/test/lib/controller/fake_models.rb | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index dfc90943e1..3a8a37d967 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -758,12 +758,12 @@ class ControllerWithSymbolAsFilter < PostsController def without_exception # Do stuff... - 1 + 1 + wtf = 1 + 1 yield # Do stuff... - 1 + 1 + wtf += 1 end end diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index cf3f2f7fa4..dba632e6df 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -55,6 +55,11 @@ class Post < Struct.new(:title, :author_name, :body, :secret, :written_on, :cost alias_method :secret?, :secret + def initialize(*args) + super + @persisted = false + end + def persisted=(boolean) @persisted = boolean end -- cgit v1.2.3 From 333a5659e8663049618386e3fa45248d388070fd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 19:46:38 -0700 Subject: dry up some crazy codes --- actionpack/lib/action_view/helpers/url_helper.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 1c3ca78d28..440e0162cd 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -476,18 +476,16 @@ module ActionView html_options = html_options.stringify_keys encode = html_options.delete("encode").to_s - cc, bcc, subject, body = html_options.delete("cc"), html_options.delete("bcc"), html_options.delete("subject"), html_options.delete("body") - extras = [] - extras << "cc=#{Rack::Utils.escape(cc).gsub("+", "%20")}" unless cc.nil? - extras << "bcc=#{Rack::Utils.escape(bcc).gsub("+", "%20")}" unless bcc.nil? - extras << "body=#{Rack::Utils.escape(body).gsub("+", "%20")}" unless body.nil? - extras << "subject=#{Rack::Utils.escape(subject).gsub("+", "%20")}" unless subject.nil? + extras = %w{ cc bcc body subject }.map { |item| + option = html_options.delete(item) || next + "#{item}=#{Rack::Utils.escape(option).gsub("+", "%20")}" + }.compact extras = extras.empty? ? '' : '?' + html_escape(extras.join('&')) email_address_obfuscated = email_address.dup - email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.has_key?("replace_at") - email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot") + email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.key?("replace_at") + email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.key?("replace_dot") string = '' -- cgit v1.2.3 From 714fea4540c96f70d044e2bd1be92b504d1f8fa3 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 19:52:17 -0700 Subject: deleting more crazy --- actionpack/lib/action_view/helpers/url_helper.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 440e0162cd..0eed3ea259 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -495,13 +495,11 @@ module ActionView end "".html_safe elsif encode == "hex" - email_address_encoded = '' - email_address_obfuscated.each_byte do |c| - email_address_encoded << sprintf("&#%d;", c) - end + email_address_encoded = email_address_obfuscated.unpack('C*').map {|c| + sprintf("&#%d;", c) + }.join - protocol = 'mailto:' - protocol.each_byte { |c| string << sprintf("&#%d;", c) } + string += 'mailto:'.unpack('C*').map { |c| sprintf("&#%d;", c) }.join email_address.each_byte do |c| char = c.chr -- cgit v1.2.3 From 839e2f96647d5b29cc2865555a6f615c31429109 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 20:00:55 -0700 Subject: cleaning up more crazy! --- actionpack/lib/action_view/helpers/url_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 0eed3ea259..651240a122 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -501,10 +501,10 @@ module ActionView string += 'mailto:'.unpack('C*').map { |c| sprintf("&#%d;", c) }.join - email_address.each_byte do |c| + string += email_address.unpack('C*').map do |c| char = c.chr - string << (char =~ /\w/ ? sprintf("%%%x", c) : char) - end + char =~ /\w/ ? sprintf("%%%x", c) : char + end.join content_tag "a", name || email_address_encoded.html_safe, html_options.merge("href" => "#{string}#{extras}".html_safe) else content_tag "a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe) -- cgit v1.2.3 From e3acdcfbf349e416c63f4c56170e9d82f7b1b1d0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 Oct 2010 20:05:56 -0700 Subject: refactoring to use fewer intermediate variables --- actionpack/lib/action_view/helpers/url_helper.rb | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 651240a122..da42d94318 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -487,24 +487,25 @@ module ActionView email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.key?("replace_at") email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.key?("replace_dot") - string = '' - - if encode == "javascript" - "document.write('#{content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe))}');".each_byte do |c| - string << sprintf("%%%x", c) - end + case encode + when "javascript" + string = + "document.write('#{content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe))}');".unpack('C*').map { |c| + sprintf("%%%x", c) + }.join "".html_safe - elsif encode == "hex" + when "hex" email_address_encoded = email_address_obfuscated.unpack('C*').map {|c| sprintf("&#%d;", c) }.join - string += 'mailto:'.unpack('C*').map { |c| sprintf("&#%d;", c) }.join - - string += email_address.unpack('C*').map do |c| + string = 'mailto:'.unpack('C*').map { |c| + sprintf("&#%d;", c) + }.join + email_address.unpack('C*').map { |c| char = c.chr char =~ /\w/ ? sprintf("%%%x", c) : char - end.join + }.join + content_tag "a", name || email_address_encoded.html_safe, html_options.merge("href" => "#{string}#{extras}".html_safe) else content_tag "a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe) -- cgit v1.2.3 From 4a4ff148ff85a148b5313dcc429e21b2d32057d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 5 Oct 2010 09:48:32 +0200 Subject: Use RbConfig instead of Config for 1.9.3 compatibility. --- railties/lib/rails/engine.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index ba89bce928..3981e8dfd5 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -535,7 +535,7 @@ module Rails root = File.exist?("#{root_path}/#{flag}") ? root_path : default raise "Could not find root path for #{self}" unless root - Config::CONFIG['host_os'] =~ /mswin|mingw/ ? + RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? Pathname.new(root).expand_path : Pathname.new(root).realpath end -- cgit v1.2.3 From 68d75c3365e1d0e1af21caab01e192223c371511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 5 Oct 2010 09:55:51 +0200 Subject: Don't expect an AD::Response object back from the app. --- railties/test/railties/engine_test.rb | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index c75639d740..89262aeaae 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -89,7 +89,7 @@ module RailtiesTest env = Rack::MockRequest.env_for("/bukkits") response = Rails.application.call(env) - assert_equal "HELLO WORLD", response[2] + assert_equal ["HELLO WORLD"], response[2] end test "it provides routes as default endpoint" do @@ -116,8 +116,7 @@ module RailtiesTest env = Rack::MockRequest.env_for("/bukkits/foo") response = Rails.application.call(env) - - assert_equal "foo", response[2] + assert_equal ["foo"], response[2] end test "engine can load its own plugins" do @@ -379,15 +378,15 @@ module RailtiesTest env = Rack::MockRequest.env_for("/foo") response = Rails.application.call(env) - assert_equal "Something... Something... Something...", response[2].body + assert_equal ["Something... Something... Something..."], response[2] env = Rack::MockRequest.env_for("/foo/show") response = Rails.application.call(env) - assert_equal "/foo", response[2].body + assert_equal ["/foo"], response[2] env = Rack::MockRequest.env_for("/foo/bar") response = Rails.application.call(env) - assert_equal "It's a bar.", response[2].body + assert_equal ["It's a bar."], response[2] end test "isolated engine should include only its own routes and helpers" do @@ -488,23 +487,23 @@ module RailtiesTest env = Rack::MockRequest.env_for("/bukkits/from_app") response = AppTemplate::Application.call(env) - assert_equal "false", response[2].body + assert_equal ["false"], response[2] env = Rack::MockRequest.env_for("/bukkits/foo/show") response = AppTemplate::Application.call(env) - assert_equal "/bukkits/foo", response[2].body + assert_equal ["/bukkits/foo"], response[2] env = Rack::MockRequest.env_for("/bukkits/foo") response = AppTemplate::Application.call(env) - assert_equal "Helped.", response[2].body + assert_equal ["Helped."], response[2] env = Rack::MockRequest.env_for("/bukkits/routes_helpers_in_view") response = AppTemplate::Application.call(env) - assert_equal "/bukkits/foo, /bar", response[2].body + assert_equal ["/bukkits/foo, /bar"], response[2] env = Rack::MockRequest.env_for("/bukkits/polymorphic_path_without_namespace") response = AppTemplate::Application.call(env) - assert_equal "/bukkits/posts/1", response[2].body + assert_equal ["/bukkits/posts/1"], response[2] end test "isolated engine should avoid namespace in names if that's possible" do -- cgit v1.2.3 From 360a8780706cc95144bef429d6fe42e9475a5400 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 5 Oct 2010 19:34:27 +0200 Subject: new guide: Ruby on Rails Guides Guidelines --- railties/guides/source/index.html.erb | 4 ++ railties/guides/source/layout.html.erb | 1 + .../source/ruby_on_rails_guides_guidelines.textile | 78 ++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 railties/guides/source/ruby_on_rails_guides_guidelines.textile diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb index e6d327168a..d28ea24a76 100644 --- a/railties/guides/source/index.html.erb +++ b/railties/guides/source/index.html.erb @@ -161,6 +161,10 @@ Ruby on Rails Guides <%= guide('API Documentation Guidelines', 'api_documentation_guidelines.html') do %>

This guide documents the Ruby on Rails API documentation guidelines.

<% end %> + + <%= guide('Ruby on Rails Guides Guidelines', 'ruby_on_rails_guides_guidelines.html') do %> +

This guide documentes the Ruby on Rails guides Guidelines.

+ <% end %>

Release Notes

diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index 2039c76213..f0aa227c7e 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -81,6 +81,7 @@
Contributing to Rails
Contributing to Rails
API Documentation Guidelines
+
Ruby on Rails Guides Guidelines
Release Notes
Ruby on Rails 3.0 Release Notes
diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile new file mode 100644 index 0000000000..818d96da79 --- /dev/null +++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile @@ -0,0 +1,78 @@ +h2. Ruby on Rails Guides Guidelines + +This guide documents guidelines for writing guides. This guide follows itself in a gracile loop. + +endprologue. + +h3. Textile + +Guides are written in "Textile":http://www.textism.com/tools/textile/. There's comprehensive documentation "here":http://redcloth.org/hobix.com/textile/ and a cheatsheet for markup "here":http://redcloth.org/hobix.com/textile/quick.html. + +h3. Prologue + +Each guide should start with motivational text at the top. That's the little introduction in the blue area. The prologue should tell the readers what's the guide about, and what will they learn. See for example the "Routing Guide":routing.html. + +h3. Titles + +The title of every guide uses +h2+, guide sections use +h3+, subsections +h4+, etc. + +Capitalize all words except for internal articles, prepositions, conjuctions, and forms of the verb to be: + + +h5. Middleware Stack is an Array +h5. When are Objects Saved? + + +Use same typography as in regular text: + + +h3. Brief Note About +Test::Unit+ +h6. The +:content_type+ Option + + +h3. API Documentation Guidelides + +The guides and the API should be coherent where appropriate. Please have a look at these particular sections of the "API Documentation Guidelines":api_documentation_guidelines.html: + +* "Wording":api_documentation_guidelines.html#wording +* "Example Code":api_documentation_guidelines.html#example-code +* "Filenames":api_documentation_guidelines.html#filenames +* "Fonts":api_documentation_guidelines.html#fonts + +Those guidelines apply also to guides. + +h3. HTML Generation + +To generate all the guides just cd into the +railties+ directory and execute + + +rake generate_guides + + +You'll need the gems erubis, i18n, and RedCloth. + +To process +my_guide.textile+ and nothing else use the +ONLY+ environment variable: + + +rake generate_guides ONLY=my_guide + + +Although by default guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice. + +To force process of al the guides pass +ALL=1+. + +It is also recommended that you work with +WARNINGS=1+, this detects duplicate IDs and warns about broken internal links. + +h3. HTML validation + +Please do validate the generated HTML with + + +rake validate_guides + + +Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set +WARNINGS=1+ when generating guides to detect them. The warning messages suggest a way to fix them. + +h3. Changelog + +* October 5, 2010: ported from the docrails wiki and revised by "Xavier Noria":credits.html#fxn -- cgit v1.2.3 From da34ee423f3d43c368e33d834bb70d59af16273b Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 5 Oct 2010 19:38:05 +0200 Subject: aaaaannnddd, your beloved typo only spotted in the github colored diff no matter how many passes you did before pushing --- railties/guides/source/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb index d28ea24a76..6b897e3a6a 100644 --- a/railties/guides/source/index.html.erb +++ b/railties/guides/source/index.html.erb @@ -163,7 +163,7 @@ Ruby on Rails Guides <% end %> <%= guide('Ruby on Rails Guides Guidelines', 'ruby_on_rails_guides_guidelines.html') do %> -

This guide documentes the Ruby on Rails guides Guidelines.

+

This guide documents the Ruby on Rails guides guidelines.

<% end %> -- cgit v1.2.3 From 3b7d48cc455a04a40328e8f29b4200fdfb4f73b7 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 5 Oct 2010 22:52:43 +0200 Subject: a couple of touches to the guides guidelines --- railties/guides/source/ruby_on_rails_guides_guidelines.textile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile index 818d96da79..0bc409cbda 100644 --- a/railties/guides/source/ruby_on_rails_guides_guidelines.textile +++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile @@ -26,11 +26,10 @@ h5. When are Objects Saved? Use same typography as in regular text: -h3. Brief Note About +Test::Unit+ h6. The +:content_type+ Option -h3. API Documentation Guidelides +h3. API Documentation Guidelines The guides and the API should be coherent where appropriate. Please have a look at these particular sections of the "API Documentation Guidelines":api_documentation_guidelines.html: -- cgit v1.2.3 From 19a5f99685ab9f0a60bb8c1ed2a3fdb40b2e762e Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Tue, 5 Oct 2010 19:21:07 -0700 Subject: Fix copy/paste bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activesupport/lib/active_support/xml_mini.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index 352172027b..b6a8cf3caf 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -25,7 +25,7 @@ module ActiveSupport DEFAULT_ENCODINGS = { "binary" => "base64" - } unless defined?(TYPE_NAMES) + } unless defined?(DEFAULT_ENCODINGS) TYPE_NAMES = { "Symbol" => "symbol", -- cgit v1.2.3 From 990719bb59b89c614ec81aa25f2fc83f3323c9ea Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Tue, 5 Oct 2010 21:01:01 +0530 Subject: mailer comment should use namespace in comment --- actionmailer/lib/rails/generators/mailer/templates/mailer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionmailer/lib/rails/generators/mailer/templates/mailer.rb b/actionmailer/lib/rails/generators/mailer/templates/mailer.rb index 4d21c65101..370a508cad 100644 --- a/actionmailer/lib/rails/generators/mailer/templates/mailer.rb +++ b/actionmailer/lib/rails/generators/mailer/templates/mailer.rb @@ -6,7 +6,7 @@ class <%= class_name %> < ActionMailer::Base # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # - # en.<%= file_name %>.<%= action %>.subject + # en.<%= file_path.gsub("/",".") %>.<%= action %>.subject # def <%= action %> @greeting = "Hi" -- cgit v1.2.3 From ae812e9fc9232a56daebd7e20f56a18981480d8c Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Wed, 6 Oct 2010 11:59:11 +0530 Subject: adding test for namedspaced mailers --- railties/test/generators/mailer_generator_test.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb index 450dec7716..f4fdc46328 100644 --- a/railties/test/generators/mailer_generator_test.rb +++ b/railties/test/generators/mailer_generator_test.rb @@ -59,6 +59,15 @@ class MailerGeneratorTest < Rails::Generators::TestCase assert_match /haml \[not found\]/, content end + def test_mailer_with_namedspaced_mailer + run_generator ["Farm::Animal", "moos"] + assert_file "app/mailers/farm/animal.rb" do |mailer| + assert_match /class Farm::Animal < ActionMailer::Base/, mailer + assert_match /en\.farm\.animal\.moos\.subject/, mailer + end + assert_file "app/views/farm/animal/moos.text.erb" + end + def test_actions_are_turned_into_methods run_generator -- cgit v1.2.3 From 6774e12afa0f29442aa612ddf6e51d5a1b7a4356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 6 Oct 2010 11:07:09 +0200 Subject: Clean up the builder abstraction in AppGenerator. This commit may be reverted once documentation and a proper way to handle actions are added. --- .../rails/generators/rails/app/app_generator.rb | 247 +++++---------------- railties/test/generators/app_generator_test.rb | 68 +----- 2 files changed, 55 insertions(+), 260 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 2715483914..be09698787 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -6,152 +6,12 @@ require 'open-uri' require 'uri' module Rails - module ActionMethods - attr_reader :options - - def initialize(generator) - @generator = generator - @options = generator.options - end - - private - %w(template copy_file directory empty_directory inside - empty_directory_with_gitkeep create_file chmod shebang).each do |method| - class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{method}(*args, &block) - @generator.send(:#{method}, *args, &block) - end - RUBY - end - - # TODO: Remove once this is fully in place - def method_missing(meth, *args, &block) - STDERR.puts "Calling #{meth} with #{args.inspect} with #{block}" - @generator.send(meth, *args, &block) - end - end - - class AppBuilder - def rakefile - template "Rakefile" - end - - def readme - copy_file "README" - end - - def gemfile - template "Gemfile" - end - - def configru - template "config.ru" - end - - def gitignore - copy_file "gitignore", ".gitignore" - end - - def app - directory 'app' - end - - def config - empty_directory "config" - - inside "config" do - template "routes.rb" - template "application.rb" - template "environment.rb" - - directory "environments" - directory "initializers" - directory "locales" - end - end - - def database_yml - template "config/databases/#{@options[:database]}.yml", "config/database.yml" - end - - def db - directory "db" - end - - def doc - directory "doc" - end - - def lib - empty_directory "lib" - empty_directory_with_gitkeep "lib/tasks" - end - - def log - empty_directory "log" - - inside "log" do - %w( server production development test ).each do |file| - create_file "#{file}.log" - chmod "#{file}.log", 0666, :verbose => false - end - end - end - - def public_directory - directory "public", "public", :recursive => false - end - - def images - directory "public/images" - end - - def stylesheets - empty_directory_with_gitkeep "public/stylesheets" - end - - def javascripts - unless options[:skip_prototype] - directory "public/javascripts" - else - empty_directory_with_gitkeep "public/javascripts" - create_file "public/javascripts/application.js" - end - end - - def script - directory "script" do |content| - "#{shebang}\n" + content - end - chmod "script", 0755, :verbose => false - end - - def test - directory "test" - end - - def tmp - empty_directory "tmp" - - inside "tmp" do - %w(sessions sockets cache pids).each do |dir| - empty_directory(dir) - end - end - end - - def vendor_plugins - empty_directory_with_gitkeep "vendor/plugins" - end - end - module Generators # We need to store the RAILS_DEV_PATH in a constant, otherwise the path # can change in Ruby 1.8.7 when we FileUtils.cd. RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__)) - RESERVED_NAMES = %w[application destroy benchmarker profiler - plugin runner test] + RESERVED_NAMES = %w(application destroy benchmarker profiler plugin runner test) class AppGenerator < Base DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) @@ -164,9 +24,6 @@ module Rails class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" - class_option :builder, :type => :string, :aliases => "-b", - :desc => "Path to an application builder (can be a filesystem path or URL)" - class_option :template, :type => :string, :aliases => "-m", :desc => "Path to an application template (can be a filesystem path or URL)" @@ -200,7 +57,6 @@ module Rails def initialize(*args) raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank? - @original_wd = Dir.pwd super @@ -220,19 +76,29 @@ module Rails end def create_root_files - build(:readme) - build(:rakefile) - build(:configru) - build(:gitignore) unless options[:skip_git] - build(:gemfile) unless options[:skip_gemfile] + copy_file "README" + template "Rakefile" + template "config.ru" + copy_file "gitignore", ".gitignore" unless options[:skip_git] + template "Gemfile" unless options[:skip_gemfile] end def create_app_files - build(:app) + directory 'app' end def create_config_files - build(:config) + empty_directory "config" + + inside "config" do + template "routes.rb" + template "application.rb" + template "environment.rb" + + directory "environments" + directory "initializers" + directory "locales" + end end def create_boot_file @@ -241,59 +107,77 @@ module Rails def create_active_record_files return if options[:skip_active_record] - build(:database_yml) + template "config/databases/#{@options[:database]}.yml", "config/database.yml" end def create_db_files - build(:db) + directory "db" end def create_doc_files - build(:doc) + directory "doc" end def create_lib_files - build(:lib) + empty_directory "lib" + empty_directory_with_gitkeep "lib/tasks" end def create_log_files - build(:log) + empty_directory "log" + + inside "log" do + %w( server production development test ).each do |file| + create_file "#{file}.log" + chmod "#{file}.log", 0666, :verbose => false + end + end end def create_public_files - build(:public_directory) + directory "public", "public", :recursive => false end def create_public_image_files - build(:images) + directory "public/images" end def create_public_stylesheets_files - build(:stylesheets) + empty_directory_with_gitkeep "public/stylesheets" end - def create_prototype_files - build(:javascripts) + def create_public_javascripts_files + unless options[:skip_prototype] + directory "public/javascripts" + else + empty_directory_with_gitkeep "public/javascripts" + create_file "public/javascripts/application.js" + end end def create_script_files - build(:script) + directory "script" do |content| + "#{shebang}\n" + content + end + chmod "script", 0755, :verbose => false end def create_test_files - build(:test) unless options[:skip_test_unit] + directory "test" unless options[:skip_test_unit] end def create_tmp_files - build(:tmp) - end + empty_directory "tmp" - def create_vendor_files - build(:vendor_plugins) + inside "tmp" do + %w(sessions sockets cache pids).each do |dir| + empty_directory(dir) + end + end end - def finish_template - build(:leftovers) + def create_vendor_files + empty_directory_with_gitkeep "vendor/plugins" end def apply_rails_template @@ -313,29 +197,6 @@ module Rails "rails new #{self.arguments.map(&:usage).join(' ')} [options]" end - def builder - @builder ||= begin - if path = options[:builder] - if URI(path).is_a?(URI::HTTP) - contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read } - else - contents = open(File.expand_path(path, @original_wd)) {|io| io.read } - end - - prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1) - instance_eval(&prok) - end - - builder_class = defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder - builder_class.send(:include, ActionMethods) - builder_class.new(self) - end - end - - def build(meth, *args) - builder.send(meth, *args) if builder.respond_to?(meth) - end - def set_default_accessors! self.rails_template = case options[:template] when /^http:\/\// diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 3653b067c8..3bd8770710 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -261,70 +261,4 @@ protected silence(:stdout){ generator.send(*args, &block) } end -end - -class CustomAppGeneratorTest < Rails::Generators::TestCase - include GeneratorsTestHelper - tests Rails::Generators::AppGenerator - - arguments [destination_root] - - def setup - Rails.application = TestApp::Application - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') - end - - def teardown - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - Object.class_eval { remove_const :AppBuilder if const_defined?(:AppBuilder) } - Rails.application = TestApp::Application.instance - end - - def test_builder_option_with_empty_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/empty_builder.rb"]) - DEFAULT_APP_FILES.each{ |path| assert_no_file path } - end - - def test_builder_option_with_simple_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/simple_builder.rb"]) - (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] - end - - def test_builder_option_with_relative_path - here = File.expand_path(File.dirname(__FILE__)) - FileUtils.cd(here) - run_generator([destination_root, "-b", "../fixtures/lib/simple_builder.rb"]) - (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] - end - - def test_builder_option_with_tweak_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/tweak_builder.rb"]) - DEFAULT_APP_FILES.each{ |path| assert_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] - end - - def test_builder_option_with_http - path = "http://gist.github.com/103208.txt" - template = "class AppBuilder; end" - template.instance_eval "def read; self; end" # Make the string respond to read - - generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) - capture(:stdout) { generator.invoke_all } - - DEFAULT_APP_FILES.each{ |path| assert_no_file path } - end - -protected - - def action(*args, &block) - silence(:stdout){ generator.send(*args, &block) } - end -end +end \ No newline at end of file -- cgit v1.2.3 From 848eb0d777d2f2907c399c2fe073fedffad14c63 Mon Sep 17 00:00:00 2001 From: wycats Date: Wed, 6 Oct 2010 02:53:00 -0700 Subject: Revert "Clean up the builder abstraction in AppGenerator." The phrase "clean up" misrepresents the fact that this removes a feature that ships with Rails 3.0. This reverts commit 6774e12afa0f29442aa612ddf6e51d5a1b7a4356. --- .../rails/generators/rails/app/app_generator.rb | 247 ++++++++++++++++----- railties/test/generators/app_generator_test.rb | 68 +++++- 2 files changed, 260 insertions(+), 55 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index be09698787..2715483914 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -6,12 +6,152 @@ require 'open-uri' require 'uri' module Rails + module ActionMethods + attr_reader :options + + def initialize(generator) + @generator = generator + @options = generator.options + end + + private + %w(template copy_file directory empty_directory inside + empty_directory_with_gitkeep create_file chmod shebang).each do |method| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args, &block) + @generator.send(:#{method}, *args, &block) + end + RUBY + end + + # TODO: Remove once this is fully in place + def method_missing(meth, *args, &block) + STDERR.puts "Calling #{meth} with #{args.inspect} with #{block}" + @generator.send(meth, *args, &block) + end + end + + class AppBuilder + def rakefile + template "Rakefile" + end + + def readme + copy_file "README" + end + + def gemfile + template "Gemfile" + end + + def configru + template "config.ru" + end + + def gitignore + copy_file "gitignore", ".gitignore" + end + + def app + directory 'app' + end + + def config + empty_directory "config" + + inside "config" do + template "routes.rb" + template "application.rb" + template "environment.rb" + + directory "environments" + directory "initializers" + directory "locales" + end + end + + def database_yml + template "config/databases/#{@options[:database]}.yml", "config/database.yml" + end + + def db + directory "db" + end + + def doc + directory "doc" + end + + def lib + empty_directory "lib" + empty_directory_with_gitkeep "lib/tasks" + end + + def log + empty_directory "log" + + inside "log" do + %w( server production development test ).each do |file| + create_file "#{file}.log" + chmod "#{file}.log", 0666, :verbose => false + end + end + end + + def public_directory + directory "public", "public", :recursive => false + end + + def images + directory "public/images" + end + + def stylesheets + empty_directory_with_gitkeep "public/stylesheets" + end + + def javascripts + unless options[:skip_prototype] + directory "public/javascripts" + else + empty_directory_with_gitkeep "public/javascripts" + create_file "public/javascripts/application.js" + end + end + + def script + directory "script" do |content| + "#{shebang}\n" + content + end + chmod "script", 0755, :verbose => false + end + + def test + directory "test" + end + + def tmp + empty_directory "tmp" + + inside "tmp" do + %w(sessions sockets cache pids).each do |dir| + empty_directory(dir) + end + end + end + + def vendor_plugins + empty_directory_with_gitkeep "vendor/plugins" + end + end + module Generators # We need to store the RAILS_DEV_PATH in a constant, otherwise the path # can change in Ruby 1.8.7 when we FileUtils.cd. RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__)) - RESERVED_NAMES = %w(application destroy benchmarker profiler plugin runner test) + RESERVED_NAMES = %w[application destroy benchmarker profiler + plugin runner test] class AppGenerator < Base DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) @@ -24,6 +164,9 @@ module Rails class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" + class_option :builder, :type => :string, :aliases => "-b", + :desc => "Path to an application builder (can be a filesystem path or URL)" + class_option :template, :type => :string, :aliases => "-m", :desc => "Path to an application template (can be a filesystem path or URL)" @@ -57,6 +200,7 @@ module Rails def initialize(*args) raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank? + @original_wd = Dir.pwd super @@ -76,29 +220,19 @@ module Rails end def create_root_files - copy_file "README" - template "Rakefile" - template "config.ru" - copy_file "gitignore", ".gitignore" unless options[:skip_git] - template "Gemfile" unless options[:skip_gemfile] + build(:readme) + build(:rakefile) + build(:configru) + build(:gitignore) unless options[:skip_git] + build(:gemfile) unless options[:skip_gemfile] end def create_app_files - directory 'app' + build(:app) end def create_config_files - empty_directory "config" - - inside "config" do - template "routes.rb" - template "application.rb" - template "environment.rb" - - directory "environments" - directory "initializers" - directory "locales" - end + build(:config) end def create_boot_file @@ -107,77 +241,59 @@ module Rails def create_active_record_files return if options[:skip_active_record] - template "config/databases/#{@options[:database]}.yml", "config/database.yml" + build(:database_yml) end def create_db_files - directory "db" + build(:db) end def create_doc_files - directory "doc" + build(:doc) end def create_lib_files - empty_directory "lib" - empty_directory_with_gitkeep "lib/tasks" + build(:lib) end def create_log_files - empty_directory "log" - - inside "log" do - %w( server production development test ).each do |file| - create_file "#{file}.log" - chmod "#{file}.log", 0666, :verbose => false - end - end + build(:log) end def create_public_files - directory "public", "public", :recursive => false + build(:public_directory) end def create_public_image_files - directory "public/images" + build(:images) end def create_public_stylesheets_files - empty_directory_with_gitkeep "public/stylesheets" + build(:stylesheets) end - def create_public_javascripts_files - unless options[:skip_prototype] - directory "public/javascripts" - else - empty_directory_with_gitkeep "public/javascripts" - create_file "public/javascripts/application.js" - end + def create_prototype_files + build(:javascripts) end def create_script_files - directory "script" do |content| - "#{shebang}\n" + content - end - chmod "script", 0755, :verbose => false + build(:script) end def create_test_files - directory "test" unless options[:skip_test_unit] + build(:test) unless options[:skip_test_unit] end def create_tmp_files - empty_directory "tmp" - - inside "tmp" do - %w(sessions sockets cache pids).each do |dir| - empty_directory(dir) - end - end + build(:tmp) end def create_vendor_files - empty_directory_with_gitkeep "vendor/plugins" + build(:vendor_plugins) + end + + def finish_template + build(:leftovers) end def apply_rails_template @@ -197,6 +313,29 @@ module Rails "rails new #{self.arguments.map(&:usage).join(' ')} [options]" end + def builder + @builder ||= begin + if path = options[:builder] + if URI(path).is_a?(URI::HTTP) + contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read } + else + contents = open(File.expand_path(path, @original_wd)) {|io| io.read } + end + + prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1) + instance_eval(&prok) + end + + builder_class = defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder + builder_class.send(:include, ActionMethods) + builder_class.new(self) + end + end + + def build(meth, *args) + builder.send(meth, *args) if builder.respond_to?(meth) + end + def set_default_accessors! self.rails_template = case options[:template] when /^http:\/\// diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 3bd8770710..3653b067c8 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -261,4 +261,70 @@ protected silence(:stdout){ generator.send(*args, &block) } end -end \ No newline at end of file +end + +class CustomAppGeneratorTest < Rails::Generators::TestCase + include GeneratorsTestHelper + tests Rails::Generators::AppGenerator + + arguments [destination_root] + + def setup + Rails.application = TestApp::Application + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + end + + def teardown + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + Object.class_eval { remove_const :AppBuilder if const_defined?(:AppBuilder) } + Rails.application = TestApp::Application.instance + end + + def test_builder_option_with_empty_app_builder + FileUtils.cd(Rails.root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/empty_builder.rb"]) + DEFAULT_APP_FILES.each{ |path| assert_no_file path } + end + + def test_builder_option_with_simple_app_builder + FileUtils.cd(Rails.root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/simple_builder.rb"]) + (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } + assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] + end + + def test_builder_option_with_relative_path + here = File.expand_path(File.dirname(__FILE__)) + FileUtils.cd(here) + run_generator([destination_root, "-b", "../fixtures/lib/simple_builder.rb"]) + (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } + assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] + end + + def test_builder_option_with_tweak_app_builder + FileUtils.cd(Rails.root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/tweak_builder.rb"]) + DEFAULT_APP_FILES.each{ |path| assert_file path } + assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] + end + + def test_builder_option_with_http + path = "http://gist.github.com/103208.txt" + template = "class AppBuilder; end" + template.instance_eval "def read; self; end" # Make the string respond to read + + generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) + capture(:stdout) { generator.invoke_all } + + DEFAULT_APP_FILES.each{ |path| assert_no_file path } + end + +protected + + def action(*args, &block) + silence(:stdout){ generator.send(*args, &block) } + end +end -- cgit v1.2.3 From 0904e8256864239f673bf91fce1cfffb9345ee61 Mon Sep 17 00:00:00 2001 From: wycats Date: Wed, 6 Oct 2010 02:58:49 -0700 Subject: Delegate everything to the generator --- .../lib/rails/generators/rails/app/app_generator.rb | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 2715483914..d2ab098885 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -14,21 +14,11 @@ module Rails @options = generator.options end - private - %w(template copy_file directory empty_directory inside - empty_directory_with_gitkeep create_file chmod shebang).each do |method| - class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{method}(*args, &block) - @generator.send(:#{method}, *args, &block) - end - RUBY - end + private - # TODO: Remove once this is fully in place - def method_missing(meth, *args, &block) - STDERR.puts "Calling #{meth} with #{args.inspect} with #{block}" - @generator.send(meth, *args, &block) - end + def method_missing(meth, *args, &block) + @generator.send(meth, *args, &block) + end end class AppBuilder -- cgit v1.2.3 From d40ca9cce241a8083756c993d6c99a79e62e050e Mon Sep 17 00:00:00 2001 From: wycats Date: Wed, 6 Oct 2010 03:06:12 -0700 Subject: Some initial docs --- railties/lib/rails/generators/rails/app/app_generator.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d2ab098885..7907191c74 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -21,6 +21,13 @@ module Rails end end + # The application builder allows you to override elements of the application + # generator without being forced to reverse the operations of the default + # generator. + # + # This allows you to override entire operations, like the creation of the + # Gemfile, README, or javascript files, without needing to know exactly + # what those operations do so you can create another template action. class AppBuilder def rakefile template "Rakefile" -- cgit v1.2.3 From d649bf158be130515566aed987f83d36ac9b0ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 6 Oct 2010 17:18:59 +0200 Subject: Provide a cleaner syntax for paths configuration that does not rely on method_missing. --- actionmailer/lib/action_mailer/railtie.rb | 6 +- actionpack/lib/action_controller/railtie.rb | 8 +- actionpack/lib/action_controller/railties/paths.rb | 6 +- .../lib/active_record/railties/databases.rake | 6 +- railties/lib/rails.rb | 2 +- railties/lib/rails/application.rb | 2 +- railties/lib/rails/application/bootstrap.rb | 2 +- railties/lib/rails/application/configuration.rb | 18 +- railties/lib/rails/application/finisher.rb | 2 +- railties/lib/rails/engine.rb | 59 ++--- railties/lib/rails/engine/configuration.rb | 43 ++-- railties/lib/rails/engine/railties.rb | 2 +- railties/lib/rails/paths.rb | 152 ++++++++---- railties/lib/rails/plugin.rb | 4 +- railties/lib/rails/tasks/railties.rake | 2 +- railties/test/application/configuration_test.rb | 4 +- railties/test/application/console_test.rb | 5 +- railties/test/application/generators_test.rb | 2 +- railties/test/application/paths_test.rb | 28 +-- railties/test/paths_test.rb | 268 ++++++++++++--------- railties/test/railties/engine_test.rb | 8 +- 21 files changed, 359 insertions(+), 270 deletions(-) diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 86136bdafd..d67a5b6521 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -14,9 +14,9 @@ module ActionMailer paths = app.config.paths options = app.config.action_mailer - options.assets_dir ||= paths.public.to_a.first - options.javascripts_dir ||= paths.public.javascripts.to_a.first - options.stylesheets_dir ||= paths.public.stylesheets.to_a.first + options.assets_dir ||= paths["public"].first + options.javascripts_dir ||= paths["public/javascripts"].first + options.stylesheets_dir ||= paths["public/stylesheets"].first # make sure readers methods get compiled options.asset_path ||= nil diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 0ade42ba2d..c5a661f2b0 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -21,10 +21,10 @@ module ActionController paths = app.config.paths options = app.config.action_controller - options.assets_dir ||= paths.public.to_a.first - options.javascripts_dir ||= paths.public.javascripts.to_a.first - options.stylesheets_dir ||= paths.public.stylesheets.to_a.first - options.page_cache_directory ||= paths.public.to_a.first + options.assets_dir ||= paths["public"].first + options.javascripts_dir ||= paths["public/javascripts"].first + options.stylesheets_dir ||= paths["public/stylesheets"].first + options.page_cache_directory ||= paths["public"].first # make sure readers methods get compiled options.asset_path ||= nil diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb index fa71d55946..7a59d4f2f3 100644 --- a/actionpack/lib/action_controller/railties/paths.rb +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -5,12 +5,14 @@ module ActionController Module.new do define_method(:inherited) do |klass| super(klass) + if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } - klass.helpers_path = namespace._railtie.config.paths.app.helpers.to_a + paths = namespace._railtie.paths["app/helpers"].existent else - klass.helpers_path = app.config.helpers_paths + paths = app.config.helpers_paths end + klass.helpers_path = paths klass.helper :all if klass.superclass == ActionController::Base end end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 58c705c8b2..4ef6c6f751 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -2,7 +2,7 @@ namespace :db do task :load_config => :rails_env do require 'active_record' ActiveRecord::Base.configurations = Rails.application.config.database_configuration - ActiveRecord::Migrator.migrations_path = Rails.application.config.paths.db.migrate.to_a.first + ActiveRecord::Migrator.migrations_path = Rails.application.paths["db/migrate"].first end task :copy_migrations => :load_config do @@ -11,8 +11,8 @@ namespace :db do Rails.application.railties.all do |railtie| next unless to_load == :all || to_load.include?(railtie.railtie_name) - if railtie.config.respond_to?(:paths) && railtie.config.paths.db - railties[railtie.railtie_name] = railtie.config.paths.db.migrate.to_a.first + if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first) + railties[railtie.railtie_name] = path end end diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index 3663910281..cca0891835 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -92,7 +92,7 @@ module Rails end def public_path - application && application.paths.public.to_a.first + application && application.paths["public"].first end end end diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 075e3c5692..5559f49fbd 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -72,7 +72,7 @@ module Rails end def require_environment! #:nodoc: - environment = paths.config.environment.to_a.first + environment = paths["config/environment"].existent.first require environment if environment end diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index e39b3bc705..213aa0768a 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -23,7 +23,7 @@ module Rails # Initialize the logger early in the stack in case we need to log some deprecation. initializer :initialize_logger do Rails.logger ||= config.logger || begin - path = config.paths.log.to_a.first + path = config.paths["log"].first logger = ActiveSupport::BufferedLogger.new(path) logger.level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase) logger.auto_flushing = false if Rails.env.production? diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index f902c3ded2..3505388479 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -9,7 +9,7 @@ module Rails :filter_parameters, :log_level, :logger, :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, - :time_zone, :whiny_nils + :time_zone, :whiny_nils, :helpers_paths def initialize(*) super @@ -17,6 +17,7 @@ module Rails @allow_concurrency = false @consider_all_requests_local = false @filter_parameters = [] + @helpers_paths = [] @dependency_loading = true @serve_static_assets = true @session_store = :cookie_store @@ -60,13 +61,12 @@ module Rails def paths @paths ||= begin paths = super - paths.config.database "config/database.yml" - paths.config.environment "config/environment.rb" - paths.lib.templates "lib/templates" - paths.log "log/#{Rails.env}.log" - paths.tmp "tmp" - paths.tmp.cache "tmp/cache" - + paths.add "config/database", :with => "config/database.yml" + paths.add "config/environment", :with => "config/environment.rb" + paths.add "lib/templates" + paths.add "log", :with => "log/#{Rails.env}.log" + paths.add "tmp" + paths.add "tmp/cache" paths end end @@ -88,7 +88,7 @@ module Rails # YAML::load. def database_configuration require 'erb' - YAML::load(ERB.new(IO.read(paths.config.database.to_a.first)).result) + YAML::load(ERB.new(IO.read(paths["config/database"].first)).result) end def cache_store diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index b95df467c7..e3342be7ee 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -4,7 +4,7 @@ module Rails include Initializable initializer :add_generator_templates do - config.generators.templates.unshift(*paths.lib.templates.to_a) + config.generators.templates.unshift(*paths["lib/templates"].existent) end initializer :ensure_autoload_once_paths_as_subset do diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 3981e8dfd5..bd3e612153 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -90,17 +90,17 @@ module Rails # The available paths in an Engine are: # # class MyEngine < Rails::Engine - # paths.app = "app" - # paths.app.controllers = "app/controllers" - # paths.app.helpers = "app/helpers" - # paths.app.models = "app/models" - # paths.app.views = "app/views" - # paths.lib = "lib" - # paths.lib.tasks = "lib/tasks" - # paths.config = "config" - # paths.config.initializers = "config/initializers" - # paths.config.locales = "config/locales" - # paths.config.routes = "config/routes.rb" + # paths["app"] #=> ["app"] + # paths["app/controllers"] #=> ["app/controllers"] + # paths["app/helpers"] #=> ["app/helpers"] + # paths["app/models"] #=> ["app/models"] + # paths["app/views"] #=> ["app/views"] + # paths["lib"] #=> ["lib"] + # paths["lib/tasks"] #=> ["lib/tasks"] + # paths["config"] #=> ["config"] + # paths["config/initializers"] #=> ["config/initializers"] + # paths["config/locales"] #=> ["config/locales"] + # paths["config/routes"] #=> ["config/routes.rb"] # end # # Your Application class adds a couple more paths to this set. And as in your Application, @@ -276,11 +276,11 @@ module Rails # end # end # - # There is also 'app' helper that gives you access to application's routes inside Engine: + # There is also 'main_app' helper that gives you access to application's routes inside Engine: # # module MyEngine # class BarController - # app.foo_path #=> /foo + # main_app.foo_path #=> /foo # end # end # @@ -381,7 +381,7 @@ module Rails def load_tasks super - config.paths.lib.tasks.to_a.sort.each { |ext| load(ext) } + paths["lib/tasks"].existent.sort.each { |ext| load(ext) } end def eager_load! @@ -441,7 +441,7 @@ module Rails # # Blog::Engine.load_seed def load_seed - seed_file = config.paths.db.seeds.to_a.first + seed_file = paths["db/seeds"].existent.first load(seed_file) if File.exist?(seed_file) end @@ -469,20 +469,22 @@ module Rails end initializer :add_routing_paths do |app| - app.routes_reloader.blocks[routes] = routes_draw_block - paths.config.routes.to_a.each do |route| - app.routes_reloader.paths.unshift(route) if File.exists?(route) + paths = self.paths["config/routes"].existent + + if routes? || paths.any? + app.routes_reloader.blocks[routes] = routes_draw_block + app.routes_reloader.paths.unshift(*paths) end end # I18n load paths are a special case since the ones added # later have higher priority. initializer :add_locales do - config.i18n.railties_load_path.concat(paths.config.locales.to_a) + config.i18n.railties_load_path.concat(paths["config/locales"].existent) end initializer :add_view_paths do - views = paths.app.views.to_a + views = paths["app/views"].existent unless views.empty? ActiveSupport.on_load(:action_controller){ prepend_view_path(views) } ActiveSupport.on_load(:action_mailer){ prepend_view_path(views) } @@ -490,28 +492,27 @@ module Rails end initializer :load_environment_config, :before => :load_environment_hook do - environment = config.paths.config.environments.to_a.first + environment = paths["config/environments"].existent.first require environment if environment end initializer :append_asset_paths do config.asset_path ||= "/#{engine_name}%s" - public_path = config.paths.public.to_a.first + public_path = paths["public"].first if config.compiled_asset_path && File.exist?(public_path) config.static_asset_paths[config.compiled_asset_path] = public_path end end - initializer :prepend_helpers_path do - unless namespaced? - config.helpers_paths = [] unless config.respond_to?(:helpers_paths) - config.helpers_paths = config.paths.app.helpers.to_a + config.helpers_paths + initializer :prepend_helpers_path do |app| + if !namespaced? || (app == self) + app.config.helpers_paths.unshift(*paths["app/helpers"].existent) end end initializer :load_config_initializers do - paths.config.initializers.to_a.sort.each do |initializer| + config.paths["config/initializers"].existent.sort.each do |initializer| load(initializer) end end @@ -524,6 +525,10 @@ module Rails protected attr_accessor :routes_draw_block + def routes? + defined?(@routes) + end + def find_root_with_flag(flag, default=nil) root_path = self.class.called_from diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index b69c0e1c53..7a07dcad7d 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -10,7 +10,6 @@ module Rails def initialize(root=nil) super() @root = root - @helpers_paths = [] end # Returns the middleware stack for the engine. @@ -39,27 +38,27 @@ module Rails def paths @paths ||= begin paths = Rails::Paths::Root.new(@root) - paths.app "app", :eager_load => true, :glob => "*" - paths.app.controllers "app/controllers", :eager_load => true - paths.app.helpers "app/helpers", :eager_load => true - paths.app.models "app/models", :eager_load => true - paths.app.mailers "app/mailers", :eager_load => true - paths.app.views "app/views" - paths.lib "lib", :load_path => true - paths.lib.tasks "lib/tasks", :glob => "**/*.rake" - paths.config "config" - paths.config.initializers "config/initializers", :glob => "**/*.rb" - paths.config.locales "config/locales", :glob => "*.{rb,yml}" - paths.config.routes "config/routes.rb" - paths.config.environments "config/environments", :glob => "#{Rails.env}.rb" - paths.public "public" - paths.public.javascripts "public/javascripts" - paths.public.stylesheets "public/stylesheets" - paths.vendor "vendor", :load_path => true - paths.vendor.plugins "vendor/plugins" - paths.db "db" - paths.db.migrate "db/migrate" - paths.db.seeds "db/seeds.rb" + paths.add "app", :eager_load => true, :glob => "*" + paths.add "app/controllers", :eager_load => true + paths.add "app/helpers", :eager_load => true + paths.add "app/models", :eager_load => true + paths.add "app/mailers", :eager_load => true + paths.add "app/views" + paths.add "lib", :load_path => true + paths.add "lib/tasks", :glob => "**/*.rake" + paths.add "config" + paths.add "config/environments", :glob => "#{Rails.env}.rb" + paths.add "config/initializers", :glob => "**/*.rb" + paths.add "config/locales", :glob => "*.{rb,yml}" + paths.add "config/routes", :with => "config/routes.rb" + paths.add "db" + paths.add "db/migrate" + paths.add "db/seeds", :with => "db/seeds.rb" + paths.add "public" + paths.add "public/javascripts" + paths.add "public/stylesheets" + paths.add "vendor", :load_path => true + paths.add "vendor/plugins" paths end end diff --git a/railties/lib/rails/engine/railties.rb b/railties/lib/rails/engine/railties.rb index 389a7602c6..e91bdbf1e5 100644 --- a/railties/lib/rails/engine/railties.rb +++ b/railties/lib/rails/engine/railties.rb @@ -15,7 +15,7 @@ module Rails def plugins @plugins ||= begin plugin_names = (@config.plugins || [:all]).map { |p| p.to_sym } - Plugin.all(plugin_names, @config.paths.vendor.plugins) + Plugin.all(plugin_names, @config.paths["vendor/plugins"].existent) end end end diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index d303212f52..1729e8707e 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -2,15 +2,17 @@ require 'set' module Rails module Paths - module PathParent - attr_reader :children - + module PathParent #:nodoc: def method_missing(id, *args) - name = id.to_s + match = id.to_s.match(/^(.*)=$/) + full = [@current, $1 || id].compact.join("/") + + ActiveSupport::Deprecation.warn 'config.paths.app.controller API is deprecated in ' << + 'favor of config.paths["app/controller"] API.' - if name =~ /^(.*)=$/ || args.any? - @children[$1 || name] = Path.new(@root, *args) - elsif path = @children[name] + if match || args.any? + @root[full] = Path.new(@root, full, *args) + elsif path = @root[full] path else super @@ -18,22 +20,72 @@ module Rails end end - class Root + # This object is an extended hash that behaves as root of the Rails::Paths system. + # It allows you to collect information about how you want to structure your application + # paths by a Hash like API. It requires you to give a physical path on initialization. + # + # root = Root.new + # root.add "app/controllers", :eager_load => true + # + # The command above creates a new root object and add "app/controllers" as a path. + # This means we can get a Path object back like below: + # + # path = root["app/controllers"] + # 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: + # + # path.is_a?(Array) #=> true + # path.inspect #=> ["app/controllers"] + # + # path << "lib/controllers" + # path.inspect #=> ["app/controllers", "lib/controllers"] + # + # Notice that when you add a path using #add, the path object created already + # contains te path with the same path value given to #add. In some situations, + # you may not want this behavior, so you can give :with as option. + # + # root.add "config/routes", :with => "config/routes.rb" + # root["config/routes"].inspect #=> ["config/routes.rb"] + # + # #add also accepts the following options as argument: eager_load, autoload, + # autoload_once and glob. + # + # Finally, the Path object also provides a few helpers: + # + # root = Root.new + # root.path = "/rails" + # root.add "app/controllers" + # + # root["app/controllers"].expanded #=> ["/rails/app/controllers"] + # root["app/controllers"].existent #=> ["/rails/app/controllers"] + # + # Check the Path documentation for more information. + class Root < ::Hash include PathParent - attr_accessor :path def initialize(path) raise if path.is_a?(Array) - @children = {} + @current = nil @path = path @root = self - @all_paths = [] + super() + end + + def []=(path, value) + value = Path.new(self, path, value) unless value.is_a?(Path) + super(path, value) + end + + def add(path, options={}) + with = options[:with] || path + self[path] = Path.new(self, path, with, options) end def all_paths - @all_paths.uniq! - @all_paths + values.tap { |v| v.uniq! } end def autoload_once @@ -52,68 +104,54 @@ module Rails filter_by(:load_path?) end - def push(*) - raise "Application root can only have one physical path" - end - - alias unshift push - alias << push - alias concat push - protected def filter_by(constraint) all = [] all_paths.each do |path| if path.send(constraint) - paths = path.paths - paths -= path.children.values.map { |p| p.send(constraint) ? [] : p.paths }.flatten + paths = path.existent + paths -= path.children.map { |p| p.send(constraint) ? [] : p.existent }.flatten all.concat(paths) end end all.uniq! - all.reject! { |p| !File.exists?(p) } all end end - class Path - include PathParent, Enumerable + class Path < Array + include PathParent attr_reader :path attr_accessor :glob - def initialize(root, *paths) - options = paths.last.is_a?(::Hash) ? paths.pop : {} - @children = {} + def initialize(root, current, *paths) + options = paths.last.is_a?(::Hash) ? paths.pop : {} + super(paths.flatten) + + @current = current @root = root - @paths = paths.flatten @glob = options[:glob] autoload_once! if options[:autoload_once] eager_load! if options[:eager_load] autoload! if options[:autoload] load_path! if options[:load_path] - - @root.all_paths << self - end - - def each - to_a.each { |p| yield p } end - def push(path) - @paths.push path + def children + keys = @root.keys.select { |k| k.include?(@current) } + keys.delete(@current) + @root.values_at(*keys.sort) end - alias << push - - def unshift(path) - @paths.unshift path + def first + expanded.first end - def concat(paths) - @paths.concat paths + def last + expanded.last end %w(autoload_once eager_load autoload load_path).each do |m| @@ -132,20 +170,36 @@ module Rails RUBY end - def paths + # Expands all paths against the root and return all unique values. + def expanded raise "You need to set a path root" unless @root.path + result = [] - result = @paths.map do |p| + each do |p| path = File.expand_path(p, @root.path) - @glob ? Dir[File.join(path, @glob)] : path + + if @glob + result.concat Dir[File.join(path, @glob)] + else + result << path + end end - result.flatten! result.uniq! result end - alias to_a paths + # Returns all expanded paths but only if they exist in the filesystem. + def existent + expanded.select { |f| File.exists?(f) } + end + + def paths + ActiveSupport::Deprecation.warn "paths is deprecated. Please call expand instead." + expanded + end + + alias to_a expanded end end end \ No newline at end of file diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 5614624673..76fa76598c 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -62,13 +62,13 @@ module Rails end initializer :handle_lib_autoload, :before => :set_load_path do |app| - paths = if app.config.reload_plugins + autoload = if app.config.reload_plugins config.autoload_paths else config.autoload_once_paths end - paths.concat config.paths.lib.to_a + autoload.concat paths["lib"].existent end initializer :load_init_rb, :before => :load_config_initializers do |app| diff --git a/railties/lib/rails/tasks/railties.rake b/railties/lib/rails/tasks/railties.rake index 7cf31f84a0..0c1ee0f17a 100644 --- a/railties/lib/rails/tasks/railties.rake +++ b/railties/lib/rails/tasks/railties.rake @@ -2,7 +2,7 @@ namespace :railties do desc "Create symlinks to railties public directories in application's public directory." task :create_symlinks => :environment do paths = Rails.application.config.static_asset_paths.dup - app_public_path = Rails.application.config.paths.public.to_a.first + app_public_path = Rails.application.paths["public"].first paths.each do |mount_path, path| symlink_path = File.join(app_public_path, mount_path) diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 7403d16cf4..b8d0854286 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -42,7 +42,7 @@ module ApplicationTests test "Rails::Application responds to paths" do require "#{app_path}/config/environment" assert_respond_to AppTemplate::Application, :paths - assert_equal AppTemplate::Application.paths.app.views.to_a, ["#{app_path}/app/views"] + assert_equal AppTemplate::Application.paths["app/views"].expanded, ["#{app_path}/app/views"] end test "the application root is set correctly" do @@ -180,7 +180,7 @@ module ApplicationTests test "config.paths.public sets Rails.public_path" do add_to_config <<-RUBY - config.paths.public = "somewhere" + config.paths["public"] = "somewhere" RUBY require "#{app_path}/config/application" diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index 25b4a21902..d4159dd0fd 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' class ConsoleTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation def setup build_app @@ -14,16 +14,15 @@ class ConsoleTest < Test::Unit::TestCase end def test_app_method_should_return_integration_session + TestHelpers::Rack.send :remove_method, :app load_environment console_session = app - assert_not_nil console_session assert_instance_of ActionDispatch::Integration::Session, console_session end def test_new_session_should_return_integration_session load_environment session = new_session - assert_not_nil session assert_instance_of ActionDispatch::Integration::Session, session end diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index d258625f42..551e966c85 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -69,7 +69,7 @@ module ApplicationTests assert_equal :rspec, Rails::Generators.options[:rails][:test_framework] assert_equal "-w", Rails::Generators.aliases[:rails][:test_framework] assert_equal Hash[:shoulda => :test_unit], Rails::Generators.fallbacks - assert_equal ["#{app_path}/lib/templates", "some/where"], Rails::Generators.templates_path + assert_equal ["some/where"], Rails::Generators.templates_path end test "generators no color on initialization" do diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb index c98b11556b..b1ff6e9cb1 100644 --- a/railties/test/application/paths_test.rb +++ b/railties/test/application/paths_test.rb @@ -25,7 +25,7 @@ module ApplicationTests end def assert_path(paths, *dir) - assert_equal [root(*dir)], paths.paths + assert_equal [root(*dir)], paths.expanded end def assert_in_load_path(*path) @@ -37,20 +37,20 @@ module ApplicationTests end test "booting up Rails yields a valid paths object" do - assert_path @paths.app.models, "app", "models" - assert_path @paths.app.helpers, "app", "helpers" - assert_path @paths.app.views, "app", "views" - assert_path @paths.lib, "lib" - assert_path @paths.vendor, "vendor" - assert_path @paths.vendor.plugins, "vendor", "plugins" - assert_path @paths.tmp, "tmp" - assert_path @paths.tmp.cache, "tmp", "cache" - assert_path @paths.config, "config" - assert_path @paths.config.locales, "config", "locales", "en.yml" - assert_path @paths.config.environment, "config", "environment.rb" - assert_path @paths.config.environments, "config", "environments", "development.rb" + assert_path @paths["app/models"], "app/models" + assert_path @paths["app/helpers"], "app/helpers" + assert_path @paths["app/views"], "app/views" + assert_path @paths["lib"], "lib" + assert_path @paths["vendor"], "vendor" + assert_path @paths["vendor/plugins"], "vendor/plugins" + assert_path @paths["tmp"], "tmp" + assert_path @paths["tmp/cache"], "tmp/cache" + assert_path @paths["config"], "config" + assert_path @paths["config/locales"], "config/locales/en.yml" + assert_path @paths["config/environment"], "config/environment.rb" + assert_path @paths["config/environments"], "config/environments/development.rb" - assert_equal root("app", "controllers"), @paths.app.controllers.to_a.first + assert_equal root("app", "controllers"), @paths["app/controllers"].expanded.first end test "booting up Rails yields a list of paths that are eager" do diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb index 80fae8c543..6e4e3446b3 100644 --- a/railties/test/paths_test.rb +++ b/railties/test/paths_test.rb @@ -20,234 +20,264 @@ class PathsTest < ActiveSupport::TestCase test "a paths object initialized with nil can be updated" do root = Rails::Paths::Root.new(nil) - root.app = "app" + root.add "app" root.path = "/root" - assert_equal ["/root/app"], root.app.to_a + assert_equal ["app"], root["app"] + assert_equal ["/root/app"], root["app"].to_a end test "creating a root level path" do - @root.app = "/foo/bar" - assert_equal ["/foo/bar"], @root.app.to_a + @root.add "app" + assert_equal ["/foo/bar/app"], @root["app"].to_a + end + + test "creating a root level path with options" do + @root.add "app", :with => "/foo/bar" + assert_equal ["/foo/bar"], @root["app"].to_a end test "raises exception if root path never set" do root = Rails::Paths::Root.new(nil) - root.app = "app" + root.add "app" assert_raises RuntimeError do - root.app.to_a + root["app"].to_a end end - test "creating a root level path without assignment" do - @root.app "/foo/bar" - assert_equal ["/foo/bar"], @root.app.to_a - end - - test "trying to access a path that does not exist raises NoMethodError" do - assert_raises(NoMethodError) { @root.app } - end - - test "relative paths are relative to the paths root" do - @root.app = "app" - assert_equal ["/foo/bar/app"], @root.app.to_a - end - - test "relative paths are relative to the paths root without assignment" do - @root.app "app" - assert_equal ["/foo/bar/app"], @root.app.to_a - end - test "creating a child level path" do - @root.app = "/foo/bar" - @root.app.models = "/foo/bar/baz" - assert_equal ["/foo/bar/baz"], @root.app.models.to_a + @root.add "app" + @root.add "app/models" + assert_equal ["/foo/bar/app/models"], @root["app/models"].to_a end - test "creating a child level path without assignment" do - @root.app = "/foo/bar" - @root.app.models "/foo/bar/baz" - assert_equal ["/foo/bar/baz"], @root.app.models.to_a + test "creating a child level path with option" do + @root.add "app" + @root.add "app/models", :with => "/foo/bar/baz" + assert_equal ["/foo/bar/baz"], @root["app/models"].to_a end test "child level paths are relative from the root" do - @root.app = "/app" - @root.app.models = "baz" - - assert_equal ["/foo/bar/baz"], @root.app.models.to_a + @root.add "app" + @root.add "app/models", :with => "baz" + assert_equal ["/foo/bar/baz"], @root["app/models"].to_a end test "adding multiple physical paths as an array" do - @root.app = ["/app", "/app2"] - assert_equal ["/app", "/app2"], @root.app.to_a - end - - test "adding multiple physical paths as an array without assignment" do - @root.app "/app", "/app2" - assert_equal ["/app", "/app2"], @root.app.to_a + @root.add "app", :with => ["/app", "/app2"] + assert_equal ["/app", "/app2"], @root["app"].to_a end test "adding multiple physical paths using #push" do - @root.app = "/app" - @root.app.push "/app2" - assert_equal ["/app", "/app2"], @root.app.to_a + @root.add "app" + @root["app"].push "app2" + assert_equal ["/foo/bar/app", "/foo/bar/app2"], @root["app"].to_a end test "adding multiple physical paths using <<" do - @root.app = "/app" - @root.app << "/app2" - assert_equal ["/app", "/app2"], @root.app.to_a + @root.add "app" + @root["app"] << "app2" + assert_equal ["/foo/bar/app", "/foo/bar/app2"], @root["app"].to_a end test "adding multiple physical paths using concat" do - @root.app = "/app" - @root.app.concat ["/app2", "/app3"] - assert_equal ["/app", "/app2", "/app3"], @root.app.to_a + @root.add "app" + @root["app"].concat ["app2", "/app3"] + assert_equal ["/foo/bar/app", "/foo/bar/app2", "/app3"], @root["app"].to_a end test "adding multiple physical paths using #unshift" do - @root.app = "/app" - @root.app.unshift "/app2" - assert_equal ["/app2", "/app"], @root.app.to_a + @root.add "app" + @root["app"].unshift "app2" + assert_equal ["/foo/bar/app2", "/foo/bar/app"], @root["app"].to_a end test "the root can only have one physical path" do assert_raise(RuntimeError) { Rails::Paths::Root.new(["/fiz", "/biz"]) } - assert_raise(RuntimeError) { @root.push "/biz" } - assert_raise(RuntimeError) { @root.unshift "/biz" } - assert_raise(RuntimeError) { @root.concat ["/biz"]} - assert_raise(RuntimeError) { @root << "/biz" } end test "it is possible to add a path that should be autoloaded only once" do - @root.app = "/app" - @root.app.autoload_once! - assert @root.app.autoload_once? - assert @root.autoload_once.include?(@root.app.paths.first) + @root.add "app", :with => "/app" + @root["app"].autoload_once! + assert @root["app"].autoload_once? + assert @root.autoload_once.include?(@root["app"].expanded.first) end test "it is possible to remove a path that should be autoloaded only once" do - @root.app = "/app" - @root.app.autoload_once! - assert @root.app.autoload_once? + @root["app"] = "/app" + @root["app"].autoload_once! + assert @root["app"].autoload_once? - @root.app.skip_autoload_once! - assert !@root.app.autoload_once? - assert !@root.autoload_once.include?(@root.app.paths.first) + @root["app"].skip_autoload_once! + assert !@root["app"].autoload_once? + assert !@root.autoload_once.include?(@root["app"].expanded.first) end test "it is possible to add a path without assignment and specify it should be loaded only once" do - @root.app "/app", :autoload_once => true - assert @root.app.autoload_once? + @root.add "app", :with => "/app", :autoload_once => true + assert @root["app"].autoload_once? assert @root.autoload_once.include?("/app") end test "it is possible to add multiple paths without assignment and specify it should be loaded only once" do - @root.app "/app", "/app2", :autoload_once => true - assert @root.app.autoload_once? + @root.add "app", :with => ["/app", "/app2"], :autoload_once => true + assert @root["app"].autoload_once? assert @root.autoload_once.include?("/app") assert @root.autoload_once.include?("/app2") end test "making a path autoload_once more than once only includes it once in @root.load_once" do - @root.app = "/app" - @root.app.autoload_once! - @root.app.autoload_once! - assert_equal 1, @root.autoload_once.select {|p| p == @root.app.paths.first }.size + @root["app"] = "/app" + @root["app"].autoload_once! + @root["app"].autoload_once! + assert_equal 1, @root.autoload_once.select {|p| p == @root["app"].expanded.first }.size end test "paths added to a load_once path should be added to the autoload_once collection" do - @root.app = "/app" - @root.app.autoload_once! - @root.app << "/app2" + @root["app"] = "/app" + @root["app"].autoload_once! + @root["app"] << "/app2" assert_equal 2, @root.autoload_once.size end test "it is possible to mark a path as eager loaded" do - @root.app = "/app" - @root.app.eager_load! - assert @root.app.eager_load? - assert @root.eager_load.include?(@root.app.paths.first) + @root["app"] = "/app" + @root["app"].eager_load! + assert @root["app"].eager_load? + assert @root.eager_load.include?(@root["app"].to_a.first) end test "it is possible to skip a path from eager loading" do - @root.app = "/app" - @root.app.eager_load! - assert @root.app.eager_load? + @root["app"] = "/app" + @root["app"].eager_load! + assert @root["app"].eager_load? - @root.app.skip_eager_load! - assert !@root.app.eager_load? - assert !@root.eager_load.include?(@root.app.paths.first) + @root["app"].skip_eager_load! + assert !@root["app"].eager_load? + assert !@root.eager_load.include?(@root["app"].to_a.first) end test "it is possible to add a path without assignment and mark it as eager" do - @root.app "/app", :eager_load => true - assert @root.app.eager_load? + @root.add "app", :with => "/app", :eager_load => true + assert @root["app"].eager_load? assert @root.eager_load.include?("/app") end test "it is possible to add multiple paths without assignment and mark them as eager" do - @root.app "/app", "/app2", :eager_load => true - assert @root.app.eager_load? + @root.add "app", :with => ["/app", "/app2"], :eager_load => true + assert @root["app"].eager_load? assert @root.eager_load.include?("/app") assert @root.eager_load.include?("/app2") end test "it is possible to create a path without assignment and mark it both as eager and load once" do - @root.app "/app", :eager_load => true, :autoload_once => true - assert @root.app.eager_load? - assert @root.app.autoload_once? + @root.add "app", :with => "/app", :eager_load => true, :autoload_once => true + assert @root["app"].eager_load? + assert @root["app"].autoload_once? assert @root.eager_load.include?("/app") assert @root.autoload_once.include?("/app") end test "making a path eager more than once only includes it once in @root.eager_paths" do - @root.app = "/app" - @root.app.eager_load! - @root.app.eager_load! - assert_equal 1, @root.eager_load.select {|p| p == @root.app.paths.first }.size + @root["app"] = "/app" + @root["app"].eager_load! + @root["app"].eager_load! + assert_equal 1, @root.eager_load.select {|p| p == @root["app"].expanded.first }.size end test "paths added to a eager_load path should be added to the eager_load collection" do - @root.app = "/app" - @root.app.eager_load! - @root.app << "/app2" + @root["app"] = "/app" + @root["app"].eager_load! + @root["app"] << "/app2" assert_equal 2, @root.eager_load.size end test "it should be possible to add a path's default glob" do - @root.app = "/app" - @root.app.glob = "*.rb" - assert_equal "*.rb", @root.app.glob + @root["app"] = "/app" + @root["app"].glob = "*.rb" + assert_equal "*.rb", @root["app"].glob end test "it should be possible to override a path's default glob without assignment" do - @root.app "/app", :glob => "*.rb" - assert_equal "*.rb", @root.app.glob + @root.add "app", :with => "/app", :glob => "*.rb" + assert_equal "*.rb", @root["app"].glob end test "a path can be added to the load path" do - @root.app = "app" - @root.app.load_path! - @root.app.models = "app/models" + @root["app"] = "app" + @root["app"].load_path! + @root["app/models"] = "app/models" assert_equal ["/foo/bar/app"], @root.load_paths end test "a path can be added to the load path on creation" do - @root.app "/app", :load_path => true - assert @root.app.load_path? + @root.add "app", :with => "/app", :load_path => true + assert @root["app"].load_path? assert_equal ["/app"], @root.load_paths end test "a path can be marked as autoload path" do - @root.app = "app" - @root.app.autoload! - @root.app.models = "app/models" + @root["app"] = "app" + @root["app"].autoload! + @root["app/models"] = "app/models" assert_equal ["/foo/bar/app"], @root.autoload_paths end test "a path can be marked as autoload on creation" do - @root.app "/app", :autoload => true - assert @root.app.autoload? + @root.add "app", :with => "/app", :autoload => true + assert @root["app"].autoload? assert_equal ["/app"], @root.autoload_paths end + + # Deprecated API tests + + test "reading a root level path with assignment" do + @root.add "app" + assert_deprecated do + assert_equal ["/foo/bar/app"], @root.app.to_a + end + end + + test "creating a root level path with assignment" do + assert_deprecated do + @root.app = "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app"].to_a + end + + test "creating a root level path without assignment" do + assert_deprecated do + @root.app "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app"].to_a + end + + test "reading a nested level path with assignment" do + @root.add "app" + @root.add "app/model" + assert_deprecated do + assert_equal ["/foo/bar/app/model"], @root.app.model.to_a + end + end + + test "creating a nested level path with assignment" do + @root.add "app" + assert_deprecated do + @root.app.model = "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app/model"].to_a + end + + test "creating a nested level path without assignment" do + @root.add "app" + assert_deprecated do + @root.app.model "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app/model"].to_a + end + + test "trying to access a path that does not exist raises NoMethodError" do + assert_deprecated do + assert_raises(NoMethodError) { @root.app } + end + end end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 89262aeaae..5eed4def14 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -552,11 +552,11 @@ module RailtiesTest end RUBY - @plugin.write "app/views/bukkits/posts/new.html.erb", <<-RUBY + @plugin.write "app/views/bukkits/posts/new.html.erb", <<-ERB <%= form_for(Bukkits::Post.new) do |f| %> <%= f.text_field :title %> <% end %> - RUBY + ERB add_to_config("config.action_dispatch.show_exceptions = false") @@ -593,7 +593,7 @@ module RailtiesTest module Bukkits class Engine < ::Rails::Engine namespace(Bukkits) - config.paths.public = "#{File.join(@plugin.path, "alternate_public")}" + paths["public"] = "#{File.join(@plugin.path, "alternate_public")}" end end RUBY @@ -611,7 +611,7 @@ module RailtiesTest module Bukkits class Engine < ::Rails::Engine namespace(Bukkits) - config.paths.public = "#{File.join(@plugin.path, "not_existing")}" + paths["public"] = "#{File.join(@plugin.path, "not_existing")}" end end RUBY -- cgit v1.2.3 From a0552d653b00e2e5b77e086b155e89fa22e4d6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 6 Oct 2010 12:50:31 -0300 Subject: Fixes typo --- railties/lib/rails/paths.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb index 1729e8707e..8570fc7b3f 100644 --- a/railties/lib/rails/paths.rb +++ b/railties/lib/rails/paths.rb @@ -43,7 +43,7 @@ module Rails # path.inspect #=> ["app/controllers", "lib/controllers"] # # Notice that when you add a path using #add, the path object created already - # contains te path with the same path value given to #add. In some situations, + # contains the path with the same path value given to #add. In some situations, # you may not want this behavior, so you can give :with as option. # # root.add "config/routes", :with => "config/routes.rb" @@ -202,4 +202,4 @@ module Rails alias to_a expanded end end -end \ No newline at end of file +end -- cgit v1.2.3 From 2a04110f266b6ccaf94aeeae224af578a9620fbd Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 30 Sep 2010 12:12:23 +0530 Subject: fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests --- .../abstract/connection_pool.rb | 14 +++++------ activerecord/test/cases/connection_pool_test.rb | 29 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 37e584a629..0c264de869 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -75,10 +75,7 @@ module ActiveRecord @queue = @connection_mutex.new_cond # default 5 second timeout unless on ruby 1.9 - @timeout = - if RUBY_VERSION < '1.9' - spec.config[:wait_timeout] || 5 - end + @timeout = spec.config[:wait_timeout] || 5 # default max pool size to 5 @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5 @@ -161,7 +158,6 @@ module ActiveRecord keys = @reserved_connections.keys - Thread.list.find_all { |t| t.alive? }.map { |thread| thread.object_id } - keys.each do |key| checkin @reserved_connections[key] @reserved_connections.delete(key) @@ -194,16 +190,18 @@ module ActiveRecord checkout_new_connection end return conn if conn - # No connections available; wait for one - if @queue.wait(@timeout) + + @queue.wait(@timeout) + + if(@checked_out.size < @connections.size) next else - # try looting dead threads clear_stale_cached_connections! if @size == @checked_out.size raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it." end end + end end end diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index 82b3c36ed2..f0ec5c751c 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -26,6 +26,35 @@ module ActiveRecord "threads should have been removed") assert_equal pool.checkins.length, threads.length end + + def test_checkout_behaviour + pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec + connection = pool.connection + assert_not_nil connection + threads = [] + 4.times do |i| + threads << Thread.new(i) do |pool_count| + connection = pool.connection + assert_not_nil connection + end + end + + threads.each {|t| t.join} + + Thread.new do + threads.each do |t| + thread_ids = pool.instance_variable_get(:@reserved_connections).keys + assert thread_ids.include?(t.object_id) + end + + pool.connection + threads.each do |t| + thread_ids = pool.instance_variable_get(:@reserved_connections).keys + assert !thread_ids.include?(t.object_id) + end + end.join() + + end end end end -- cgit v1.2.3 From 3ca6988b782f7ae9da736b090fbf1edd8bc02fcb Mon Sep 17 00:00:00 2001 From: Thomas McDonald Date: Wed, 6 Oct 2010 22:11:03 +0100 Subject: Fixed typo in engine documentation --- railties/lib/rails/engine.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 0620b8608e..5e2bdb7340 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -17,7 +17,7 @@ module Rails # In Rails versions before to 3.0, your gems automatically behaved as Engine, however # this coupled Rails to Rubygems. Since Rails 3.0, if you want a gem to automatically # behave as Engine, you have to specify an Engine for it somewhere inside your plugin - # lib folder (similar with how we spceify a Railtie): + # lib folder (similar to how we specify a Railtie): # # # lib/my_engine.rb # module MyEngine -- cgit v1.2.3 From 1e63a05d28fd7ebee2f962fc190d3e2af429dcb9 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Thu, 28 Jan 2010 00:12:02 +1000 Subject: Add "a" to make it better English [#3796 state:committed] Signed-off-by: Santiago Pastorino --- railties/lib/rails/plugin.rb | 2 +- railties/test/railties/plugin_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 76fa76598c..ceddd25eaa 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -83,7 +83,7 @@ module Rails initializer :sanity_check_railties_collision do if Engine.subclasses.map { |k| k.root.to_s }.include?(root.to_s) - raise "\"#{name}\" is a Railtie/Engine and cannot be installed as plugin" + raise "\"#{name}\" is a Railtie/Engine and cannot be installed as a plugin" end end end diff --git a/railties/test/railties/plugin_test.rb b/railties/test/railties/plugin_test.rb index bae05d6978..c15ac05103 100644 --- a/railties/test/railties/plugin_test.rb +++ b/railties/test/railties/plugin_test.rb @@ -110,7 +110,7 @@ module RailtiesTest boot_rails rescue Exception => e rescued = true - assert_equal '"bukkits" is a Railtie/Engine and cannot be installed as plugin', e.message + assert_equal '"bukkits" is a Railtie/Engine and cannot be installed as a plugin', e.message end assert rescued, "Expected boot rails to fail" -- cgit v1.2.3 From ea30da30699f588bee4dc4713859fe035d6243db Mon Sep 17 00:00:00 2001 From: Anil Wadghule Date: Wed, 6 Oct 2010 23:15:48 +0530 Subject: Add jruby-openssl gem in Gemfile necessary for JRuby [#5762 state:committed] Signed-off-by: Santiago Pastorino --- Gemfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gemfile b/Gemfile index 7fe1c3ad22..be91531770 100644 --- a/Gemfile +++ b/Gemfile @@ -55,6 +55,8 @@ platforms :jruby do gem "activerecord-jdbcsqlite3-adapter" + gem "jruby-openssl" + group :db do gem "activerecord-jdbcmysql-adapter" gem "activerecord-jdbcpostgresql-adapter" -- cgit v1.2.3 From 243513f4d17e62186ef0499edece1588c79220b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 7 Oct 2010 13:26:58 +0200 Subject: Get rid of ruby warnings in Resolvers. Move a few methods up to the abstract class. --- actionpack/lib/action_view/template/resolver.rb | 45 +++++++++++++------------ actionpack/lib/action_view/testing/resolvers.rb | 4 +-- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index a261e08dbc..a031d0dc33 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -6,7 +6,6 @@ module ActionView # = Action View Resolver class Resolver def initialize - @path = nil @cached = Hash.new { |h1,k1| h1[k1] = Hash.new { |h2,k2| h2[k2] = Hash.new { |h3, k3| h3[k3] = {} } } } end @@ -35,6 +34,23 @@ module ActionView raise NotImplementedError end + # Helpers that builds a path. Useful for building virtual paths. + def build_path(name, prefix, partial, details) + path = "" + path << "#{prefix}/" unless prefix.empty? + path << (partial ? "_#{name}" : name) + path + end + + # Get the handler and format from the given parameters. + def retrieve_handler_and_format(handler, format, default_formats=nil) + handler = Template.handler_class_for_extension(handler) + format = format && Mime[format] + format ||= handler.default_format if handler.respond_to?(:default_format) + format ||= default_formats + [handler, format] + end + def cached(key, prefix, name, partial) return yield unless key && caching? @cached[key][prefix][name][partial] ||= yield @@ -44,25 +60,13 @@ module ActionView class PathResolver < Resolver EXTENSION_ORDER = [:locale, :formats, :handlers] - def to_s - @path.to_s - end - alias :to_path :to_s - - private + private def find_templates(name, prefix, partial, details) path = build_path(name, prefix, partial, details) query(path, EXTENSION_ORDER.map { |ext| details[ext] }, details[:formats]) end - def build_path(name, prefix, partial, details) - path = "" - path << "#{prefix}/" unless prefix.empty? - path << (partial ? "_#{name}" : name) - path - end - def query(path, exts, formats) query = File.join(@path, path) @@ -86,13 +90,7 @@ module ActionView def extract_handler_and_format(path, default_formats) pieces = File.basename(path).split(".") pieces.shift - - handler = Template.handler_class_for_extension(pieces.pop) - format = pieces.last && Mime[pieces.last] && pieces.pop.to_sym - format ||= handler.default_format if handler.respond_to?(:default_format) - format ||= default_formats - - [handler, format] + retrieve_handler_and_format(pieces.pop, pieces.pop, default_formats) end end @@ -103,6 +101,11 @@ module ActionView @path = File.expand_path(path) end + def to_s + @path.to_s + end + alias :to_path :to_s + def eql?(resolver) self.class.equal?(resolver.class) && to_path == resolver.to_path end diff --git a/actionpack/lib/action_view/testing/resolvers.rb b/actionpack/lib/action_view/testing/resolvers.rb index b2b62528a9..6d82fa0971 100644 --- a/actionpack/lib/action_view/testing/resolvers.rb +++ b/actionpack/lib/action_view/testing/resolvers.rb @@ -13,7 +13,7 @@ module ActionView #:nodoc: @hash = hash end - private + private def query(path, exts, formats) query = Regexp.escape(path) @@ -32,7 +32,7 @@ module ActionView #:nodoc: end end - class NullResolver < ActionView::PathResolver + class NullResolver < PathResolver def query(path, exts, formats) handler, format = extract_handler_and_format(path, formats) [ActionView::Template.new("Template generated by Null Resolver", path, handler, :virtual_path => path, :format => format)] -- cgit v1.2.3 From b9f8501f8249cdc2dc780a7a1255269c63584ef2 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Wed, 6 Oct 2010 19:14:12 -0300 Subject: - Fix ActiveResource::HttpMock.respond_to replace the response if it has the same request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activeresource/lib/active_resource/http_mock.rb | 47 +++++++++++++++---------- activeresource/test/cases/http_mock_test.rb | 23 +++++++++--- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/activeresource/lib/active_resource/http_mock.rb b/activeresource/lib/active_resource/http_mock.rb index ddd3fb1f5d..2250ed9c04 100644 --- a/activeresource/lib/active_resource/http_mock.rb +++ b/activeresource/lib/active_resource/http_mock.rb @@ -100,11 +100,11 @@ module ActiveResource # Accepts a block which declares a set of requests and responses for the HttpMock to respond to in # the following format: - # + # # mock.http_method(path, request_headers = {}, body = nil, status = 200, response_headers = {}) - # + # # === Example - # + # # @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person") # ActiveResource::HttpMock.respond_to do |mock| # mock.post "/people.xml", {}, @matz, 201, "Location" => "/people/1.xml" @@ -112,58 +112,58 @@ module ActiveResource # mock.put "/people/1.xml", {}, nil, 204 # mock.delete "/people/1.xml", {}, nil, 200 # end - # + # # Alternatively, accepts a hash of {Request => Response} pairs allowing you to generate # these the following format: - # + # # ActiveResource::Request.new(method, path, body, request_headers) # ActiveResource::Response.new(body, status, response_headers) - # + # # === Example - # + # # Request.new(:#{method}, path, nil, request_headers) - # + # # @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person") # # create_matz = ActiveResource::Request.new(:post, '/people.xml', @matz, {}) # created_response = ActiveResource::Response.new("", 201, {"Location" => "/people/1.xml"}) # get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil) # ok_response = ActiveResource::Response.new("", 200, {}) - # + # # pairs = {create_matz => created_response, get_matz => ok_response} - # + # # ActiveResource::HttpMock.respond_to(pairs) # # Note, by default, every time you call +respond_to+, any previous request and response pairs stored # in HttpMock will be deleted giving you a clean slate to work on. - # + # # If you want to override this behaviour, pass in +false+ as the last argument to +respond_to+ - # + # # === Example - # + # # ActiveResource::HttpMock.respond_to do |mock| # mock.send(:get, "/people/1", {}, "XML1") # end # ActiveResource::HttpMock.responses.length #=> 1 - # + # # ActiveResource::HttpMock.respond_to(false) do |mock| # mock.send(:get, "/people/2", {}, "XML2") # end # ActiveResource::HttpMock.responses.length #=> 2 - # + # # This also works with passing in generated pairs of requests and responses, again, just pass in false # as the last argument: - # + # # === Example - # + # # ActiveResource::HttpMock.respond_to do |mock| # mock.send(:get, "/people/1", {}, "XML1") # end # ActiveResource::HttpMock.responses.length #=> 1 - # + # # get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil) # ok_response = ActiveResource::Response.new("", 200, {}) - # + # # pairs = {get_matz => ok_response} # # ActiveResource::HttpMock.respond_to(pairs, false) @@ -171,6 +171,8 @@ module ActiveResource def respond_to(*args) #:yields: mock pairs = args.first || {} reset! if args.last.class != FalseClass + + delete_responses_to_replace pairs.to_a responses.concat pairs.to_a if block_given? yield Responder.new(responses) @@ -179,6 +181,13 @@ module ActiveResource end end + def delete_responses_to_replace(new_responses) + new_responses.each{|nr| + request_to_remove = nr[0] + @@responses = responses.delete_if{|r| r[0] == request_to_remove} + } + end + # Deletes all logged requests and responses. def reset! requests.clear diff --git a/activeresource/test/cases/http_mock_test.rb b/activeresource/test/cases/http_mock_test.rb index d90d1e01b8..f15ad04b9a 100644 --- a/activeresource/test/cases/http_mock_test.rb +++ b/activeresource/test/cases/http_mock_test.rb @@ -69,19 +69,19 @@ class HttpMockTest < ActiveSupport::TestCase request(method, "/people/1", FORMAT_HEADER[method] => "application/json") end end - + end test "allows you to send in pairs directly to the respond_to method" do matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person") - + create_matz = ActiveResource::Request.new(:post, '/people.xml', matz, {}) created_response = ActiveResource::Response.new("", 201, {"Location" => "/people/1.xml"}) get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil) ok_response = ActiveResource::Response.new(matz, 200, {}) - + pairs = {create_matz => created_response, get_matz => ok_response} - + ActiveResource::HttpMock.respond_to(pairs) assert_equal 2, ActiveResource::HttpMock.responses.length assert_equal "", ActiveResource::HttpMock.responses.assoc(create_matz)[1].body @@ -140,6 +140,21 @@ class HttpMockTest < ActiveSupport::TestCase assert_equal 2, ActiveResource::HttpMock.responses.length end + test "allows you to add replace the existing reponese with the same path" do + ActiveResource::HttpMock.respond_to do |mock| + mock.send(:get, "/people/1", {}, "XML1") + end + assert_equal 1, ActiveResource::HttpMock.responses.length + + matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person") + get_matz = ActiveResource::Request.new(:get, '/people/1', nil) + ok_response = ActiveResource::Response.new(matz, 200, {}) + + ActiveResource::HttpMock.respond_to({get_matz => ok_response}, false) + + assert_equal 1, ActiveResource::HttpMock.responses.length + end + def request(method, path, headers = {}, body = nil) if [:put, :post].include? method @http.send(method, path, body, headers) -- cgit v1.2.3 From aee043de5a7f1189bd82ce6da20fffbefe36983b Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Wed, 6 Oct 2010 19:21:01 -0300 Subject: - ActiveResource::HttpMock.respond_to do not replace the response with the same path but different method - Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activeresource/test/cases/http_mock_test.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/activeresource/test/cases/http_mock_test.rb b/activeresource/test/cases/http_mock_test.rb index f15ad04b9a..82b5e60c77 100644 --- a/activeresource/test/cases/http_mock_test.rb +++ b/activeresource/test/cases/http_mock_test.rb @@ -140,7 +140,7 @@ class HttpMockTest < ActiveSupport::TestCase assert_equal 2, ActiveResource::HttpMock.responses.length end - test "allows you to add replace the existing reponese with the same path" do + test "allows you to replace the existing reponse with the same request" do ActiveResource::HttpMock.respond_to do |mock| mock.send(:get, "/people/1", {}, "XML1") end @@ -155,6 +155,19 @@ class HttpMockTest < ActiveSupport::TestCase assert_equal 1, ActiveResource::HttpMock.responses.length end + test "do not replace the response with the same path but different method" do + ActiveResource::HttpMock.respond_to do |mock| + mock.send(:get, "/people/1", {}, "XML1") + end + assert_equal 1, ActiveResource::HttpMock.responses.length + + put_matz = ActiveResource::Request.new(:put, '/people/1', nil) + ok_response = ActiveResource::Response.new("", 200, {}) + + ActiveResource::HttpMock.respond_to({put_matz => ok_response}, false) + assert_equal 2, ActiveResource::HttpMock.responses.length + end + def request(method, path, headers = {}, body = nil) if [:put, :post].include? method @http.send(method, path, body, headers) -- cgit v1.2.3 From cec6f3fe209f0c2312da1e1d091bffd30d6733b0 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Wed, 6 Oct 2010 19:27:25 -0300 Subject: - update documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activeresource/lib/active_resource/http_mock.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/activeresource/lib/active_resource/http_mock.rb b/activeresource/lib/active_resource/http_mock.rb index 2250ed9c04..9aefde7c30 100644 --- a/activeresource/lib/active_resource/http_mock.rb +++ b/activeresource/lib/active_resource/http_mock.rb @@ -168,6 +168,15 @@ module ActiveResource # # ActiveResource::HttpMock.respond_to(pairs, false) # ActiveResource::HttpMock.responses.length #=> 2 + # + # # If you add a response with an existing request, it will be replaced + # + # fail_response = ActiveResource::Response.new("", 404, {}) + # pairs = {get_matz => fail_response} + # + # ActiveResource::HttpMock.respond_to(pairs, false) + # ActiveResource::HttpMock.responses.length #=> 2 + # def respond_to(*args) #:yields: mock pairs = args.first || {} reset! if args.last.class != FalseClass -- cgit v1.2.3 From ad13eb72959f685927b5212ed387d51142d51805 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 7 Oct 2010 13:49:40 -0200 Subject: Add a TODO to remove gem "jruby-openssl" when jruby-openssl is merge in jruby [#5762] --- Gemfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index be91531770..13bf277d7a 100644 --- a/Gemfile +++ b/Gemfile @@ -55,6 +55,9 @@ platforms :jruby do gem "activerecord-jdbcsqlite3-adapter" + # This is needed by now to let tests work on JRuby + # TODO: When the JRuby guys merge jruby-openssl in + # jruby this will be removed gem "jruby-openssl" group :db do -- cgit v1.2.3 From b2600bfc181664fcfe448d100ca054017b0576dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 7 Oct 2010 15:50:20 +0200 Subject: Remove locals dependency from template. This means that templates does not need to store its source anymore, allowing us to reduce the ammount of memory taken by our Rails processes. Naively speaking, if your app/views contains 2MB of files, each of your processes (after being hit by a bunch of requests) will take 2MB less of memory after this commit. This is extremely important for the upcoming features. Since Rails will also render CSS and JS files, their source won't be stored as well allowing us to decrease the ammount of memory taken. --- actionpack/lib/action_view/lookup_context.rb | 16 ++--- actionpack/lib/action_view/paths.rb | 4 +- actionpack/lib/action_view/render/layouts.rb | 4 +- actionpack/lib/action_view/render/partials.rb | 80 ++++++++++++++----------- actionpack/lib/action_view/render/rendering.rb | 10 ++-- actionpack/lib/action_view/template.rb | 66 +++++++++++++------- actionpack/lib/action_view/template/resolver.rb | 30 +++++++--- actionpack/lib/action_view/template/text.rb | 4 -- actionpack/test/template/template_test.rb | 1 + 9 files changed, 130 insertions(+), 85 deletions(-) diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 3ea8b86af1..794fdeae64 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -77,17 +77,17 @@ module ActionView @view_paths = ActionView::Base.process_view_paths(paths) end - def find(name, prefix = nil, partial = false) - @view_paths.find(*args_for_lookup(name, prefix, partial)) + def find(name, prefix = nil, partial = false, keys = []) + @view_paths.find(*args_for_lookup(name, prefix, partial, keys)) end alias :find_template :find - def find_all(name, prefix = nil, partial = false) - @view_paths.find_all(*args_for_lookup(name, prefix, partial)) + def find_all(name, prefix = nil, partial = false, keys = []) + @view_paths.find_all(*args_for_lookup(name, prefix, partial, keys)) end - def exists?(name, prefix = nil, partial = false) - @view_paths.exists?(*args_for_lookup(name, prefix, partial)) + def exists?(name, prefix = nil, partial = false, keys = []) + @view_paths.exists?(*args_for_lookup(name, prefix, partial, keys)) end alias :template_exists? :exists? @@ -106,9 +106,9 @@ module ActionView protected - def args_for_lookup(name, prefix, partial) #:nodoc: + def args_for_lookup(name, prefix, partial, keys) #:nodoc: name, prefix = normalize_name(name, prefix) - [name, prefix, partial || false, @details, details_key] + [name, prefix, partial || false, @details, keys, details_key] end # Support legacy foo.erb names even though we now ignore .erb diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 9857d688d2..dc26d75ff3 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -10,8 +10,8 @@ module ActionView #:nodoc: METHOD end - def find(path, prefix = nil, partial = false, details = {}, key = nil) - template = find_all(path, prefix, partial, details, key).first + def find(path, prefix = nil, partial = false, details = {}, keys = [], key = nil) + template = find_all(path, prefix, partial, details, keys, key).first raise MissingTemplate.new(self, "#{prefix}/#{path}", details, partial) unless template template end diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb index 8882acca31..08162f7fd5 100644 --- a/actionpack/lib/action_view/render/layouts.rb +++ b/actionpack/lib/action_view/render/layouts.rb @@ -62,11 +62,11 @@ module ActionView # This is the method which actually finds the layout using details in the lookup # context object. If no layout is found, it checks if at least a layout with # the given name exists across all details before raising the error. - def find_layout(layout) + def find_layout(layout, keys) begin with_layout_format do layout =~ /^\// ? - with_fallbacks { find_template(layout) } : find_template(layout) + with_fallbacks { find_template(layout, nil, false, keys) } : find_template(layout, nil, false, keys) end rescue ActionView::MissingTemplate => e update_details(:formats => nil) do diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index cc9b444837..07e844afc2 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -218,7 +218,6 @@ module ActionView def initialize(view_context, options, block) @view = view_context @partial_names = PARTIAL_NAMES[@view.controller.class.name] - setup(options, block) end @@ -237,16 +236,28 @@ module ActionView @object = partial if @collection = collection - paths = @collection_paths = @collection.map { |o| partial_path(o) } + paths = @collection_data = @collection.map { |o| partial_path(o) } @path = paths.uniq.size == 1 ? paths.first : nil else @path = partial_path end end + + if @path + @variable, @variable_counter = retrieve_variable(@path) + else + paths.map! { |path| retrieve_variable(path).unshift(path) } + end + end + + def retrieve_variable(path) + variable = @options[:as] || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym + variable_counter = :"#{variable}_counter" if @collection + [variable, variable_counter] end def render - identifier = ((@template = find_template) ? @template.identifier : @path) + identifier = ((@template = find_partial) ? @template.identifier : @path) if @collection ActiveSupport::Notifications.instrument("render_collection.action_view", @@ -254,15 +265,16 @@ module ActionView render_collection end else + if !@block && (layout = @options[:layout]) + layout = find_template(layout) + end + content = ActiveSupport::Notifications.instrument("render_partial.action_view", :identifier => identifier) do render_partial end - if !@block && (layout = @options[:layout]) - content = @view._render_layout(find_template(layout), @locals){ content } - end - + content = @view._render_layout(layout, @locals){ content } if layout content end end @@ -278,16 +290,9 @@ module ActionView result.join(spacer).html_safe end - def collection_with_template(template = @template) + def collection_with_template segments, locals, template = [], @locals, @template - - if @options[:as] - as = @options[:as] - counter = "#{as}_counter".to_sym - else - as = template.variable_name - counter = template.counter_name - end + as, counter = @variable, @variable_counter locals[counter] = -1 @@ -300,20 +305,16 @@ module ActionView segments end - def collection_without_template(collection_paths = @collection_paths) - segments, locals = [], @locals + def collection_without_template + segments, locals, collection_data = [], @locals, @collection_data index, template = -1, nil - - if @options[:as] - as = @options[:as] - counter = "#{as}_counter" - end + keys = @locals.keys @collection.each_with_index do |object, i| - template = find_template(collection_paths[i]) - locals[as || template.variable_name] = object - locals[counter || template.counter_name] = (index += 1) - + path, *data = collection_data[i] + template = find_template(path, keys + data) + locals[data[0]] = object + locals[data[1]] = (index += 1) segments << template.render(@view, locals) end @@ -321,13 +322,14 @@ module ActionView segments end - def render_partial(object = @object) - locals, view, template = @locals, @view, @template + def render_partial + locals, view = @locals, @view + object, as = @object, @variable - object ||= locals[template.variable_name] - locals[@options[:as] || template.variable_name] = object + object ||= locals[as] + locals[as] = object - template.render(view, locals) do |*name| + @template.render(view, locals) do |*name| view._layout_for(*name, &@block) end end @@ -342,10 +344,18 @@ module ActionView end end - def find_template(path=@path) - return path unless path.is_a?(String) + def find_partial + if path = @path + locals = @locals.keys + locals << @variable + locals << @variable_counter if @collection + find_template(path, locals) + end + end + + def find_template(path=@path, locals=@locals.keys) prefix = @view.controller_path unless path.include?(?/) - @view.find_template(path, prefix, true) + @view.find_template(path, prefix, true, locals) end def partial_path(object = @object) diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 5320245173..0771b40c37 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -34,16 +34,18 @@ module ActionView # Determine the template to be rendered using the given options. def _determine_template(options) #:nodoc: + keys = (options[:locals] ||= {}).keys + if options.key?(:inline) handler = Template.handler_class_for_extension(options[:type] || "erb") - Template.new(options[:inline], "inline template", handler, {}) + Template.new(options[:inline], "inline template", handler, { :locals => keys }) elsif options.key?(:text) Template::Text.new(options[:text], formats.try(:first)) elsif options.key?(:file) - with_fallbacks { find_template(options[:file], options[:prefix]) } + with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } elsif options.key?(:template) options[:template].respond_to?(:render) ? - options[:template] : find_template(options[:template], options[:prefix]) + options[:template] : find_template(options[:template], options[:prefix], false, keys) end end @@ -51,7 +53,7 @@ module ActionView # supplied as well. def _render_template(template, layout = nil, options = {}) #:nodoc: locals = options[:locals] || {} - layout = find_layout(layout) if layout + layout = find_layout(layout, locals.keys) if layout ActiveSupport::Notifications.instrument("render_template.action_view", :identifier => template.identifier, :layout => layout.try(:virtual_path)) do diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 164d177dcc..7e65654d0b 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -98,6 +98,8 @@ module ActionView extend Template::Handlers + attr_accessor :locals + attr_reader :source, :identifier, :handler, :virtual_path, :formats, :original_encoding @@ -117,23 +119,17 @@ module ActionView @handler = handler @original_encoding = nil @method_names = {} - - format = details[:format] || :html - @formats = Array.wrap(format).map(&:to_sym) - @virtual_path = details[:virtual_path].try(:sub, ".#{format}", "") + @locals = details[:locals] || [] + @formats = Array.wrap(details[:format] || :html).map(&:to_sym) + @virtual_path = details[:virtual_path].try(:sub, ".#{@formats.first}", "") + @compiled = false end def render(view, locals, &block) # Notice that we use a bang in this instrumentation because you don't want to # consume this in production. This is only slow if it's being listened to. ActiveSupport::Notifications.instrument("!render_template.action_view", :virtual_path => @virtual_path) do - if view.is_a?(ActionView::CompiledTemplates) - mod = ActionView::CompiledTemplates - else - mod = view.singleton_class - end - - method_name = compile(locals, view, mod) + compile!(view) view.send(method_name, locals, &block) end rescue Exception => e @@ -141,7 +137,7 @@ module ActionView e.sub_template_of(self) raise e else - raise Template::Error.new(self, view.respond_to?(:assigns) ? view.assigns : {}, e) + raise Template::Error.new(refresh(view) || self, view.respond_to?(:assigns) ? view.assigns : {}, e) end end @@ -149,10 +145,12 @@ module ActionView @mime_type ||= Mime::Type.lookup_by_extension(@formats.first.to_s) if @formats.first end + # TODO Remove me def variable_name @variable_name ||= @virtual_path[%r'_?(\w+)(\.\w+)*$', 1].to_sym end + # TODO Remove me def counter_name @counter_name ||= "#{variable_name}_counter".to_sym end @@ -166,7 +164,25 @@ module ActionView end end - private + def compile!(view) + return if @compiled + + if view.is_a?(ActionView::CompiledTemplates) + mod = ActionView::CompiledTemplates + else + mod = view.singleton_class + end + + compile(view, mod) + + # Just discard the source if we have a virtual path. This + # means we can get the template back. + @source = nil if @virtual_path + @compiled = true + end + + protected + # Among other things, this method is responsible for properly setting # the encoding of the source. Until this point, we assume that the # source is BINARY data. If no additional information is supplied, @@ -187,11 +203,9 @@ module ActionView # encode the source into Encoding.default_internal. In general, # this means that templates will be UTF-8 inside of Rails, # regardless of the original source encoding. - def compile(locals, view, mod) - method_name = build_method_name(locals) - return method_name if view.respond_to?(method_name) - - locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join + def compile(view, mod) + method_name = self.method_name + locals_code = @locals.map { |key| "#{key} = local_assigns[:#{key}];" }.join if source.encoding_aware? # Look for # encoding: *. If we find one, we'll encode the @@ -256,8 +270,6 @@ module ActionView begin mod.module_eval(source, identifier, 0) ObjectSpace.define_finalizer(self, Finalizer[method_name, mod]) - - method_name rescue Exception => e # errors from template code if logger = (view && view.logger) logger.debug "ERROR: compiling #{method_name} RAISED #{e}" @@ -269,12 +281,20 @@ module ActionView end end - def build_method_name(locals) - @method_names[locals.keys.hash] ||= "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_") + def refresh(view) + return unless @virtual_path + pieces = @virtual_path.split("/") + name = pieces.pop + partial = name.sub!(/^_/, "") + view.find_template(name, pieces.join, partial || false, @locals) + end + + def method_name + @method_name ||= "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}".gsub('-', "_") end def identifier_method_name - @identifier_method_name ||= inspect.gsub(/[^a-z_]/, '_') + inspect.gsub(/[^a-z_]/, '_') end end end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index a031d0dc33..9ec39b16f0 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -6,8 +6,8 @@ module ActionView # = Action View Resolver class Resolver def initialize - @cached = Hash.new { |h1,k1| h1[k1] = - Hash.new { |h2,k2| h2[k2] = Hash.new { |h3, k3| h3[k3] = {} } } } + @cached = Hash.new { |h1,k1| h1[k1] = Hash.new { |h2,k2| + h2[k2] = Hash.new { |h3,k3| h3[k3] = Hash.new { |h4,k4| h4[k4] = {} } } } } end def clear_cache @@ -15,8 +15,8 @@ module ActionView end # Normalizes the arguments and passes it on to find_template. - def find_all(name, prefix=nil, partial=false, details={}, key=nil) - cached(key, prefix, name, partial) do + def find_all(name, prefix=nil, partial=false, details={}, locals=[], key=nil) + cached(key, prefix, name, partial, locals) do find_templates(name, prefix, partial, details) end end @@ -51,9 +51,25 @@ module ActionView [handler, format] end - def cached(key, prefix, name, partial) - return yield unless key && caching? - @cached[key][prefix][name][partial] ||= yield + def cached(key, prefix, name, partial, locals) + locals = sort_locals(locals) + unless key && caching? + yield.each { |t| t.locals = locals } + else + @cached[key][prefix][name][partial][locals] ||= yield.each { |t| t.locals = locals } + end + end + + if :locale.respond_to?("<=>") + def sort_locals(locals) + locals.sort.freeze + end + else + def sort_locals(locals) + locals = locals.map{ |l| l.to_s } + locals.sort! + locals.freeze + end end end diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb index 51be831dfb..4261c3b5e2 100644 --- a/actionpack/lib/action_view/template/text.rb +++ b/actionpack/lib/action_view/template/text.rb @@ -25,10 +25,6 @@ module ActionView #:nodoc: def formats [@mime_type.to_sym] end - - def partial? - false - end end end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index c7c33af670..210ba673f0 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -51,6 +51,7 @@ class TestERBTemplate < ActiveSupport::TestCase def test_locals @template = new_template("<%= my_local %>") + @template.locals = [:my_local] assert_equal "I'm a local", render(:my_local => "I'm a local") end -- cgit v1.2.3 From 8f9e9118e402ea2fe1eec6fcb9a2d3f0c84b3b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 7 Oct 2010 16:25:13 +0200 Subject: Make collection rendering faster. --- actionpack/lib/abstract_controller/rendering.rb | 2 +- actionpack/lib/action_view/render/partials.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 5d9b35d297..b4ab3481d5 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -50,7 +50,7 @@ module AbstractController if controller.respond_to?(:_helpers) include controller._helpers - if controller.respond_to?(:_routes) + if controller.respond_to?(:_routes) && controller._routes include controller._routes.url_helpers include controller._routes.mounted_helpers end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 07e844afc2..f7bdbd6917 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -307,12 +307,12 @@ module ActionView def collection_without_template segments, locals, collection_data = [], @locals, @collection_data - index, template = -1, nil + index, template, cache = -1, nil, {} keys = @locals.keys @collection.each_with_index do |object, i| path, *data = collection_data[i] - template = find_template(path, keys + data) + template = (cache[path] ||= find_template(path, keys + data)) locals[data[0]] = object locals[data[1]] = (index += 1) segments << template.render(@view, locals) -- cgit v1.2.3 From c563f10f3e8083bebe32200fa065748c8bcb65c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 7 Oct 2010 20:48:21 +0200 Subject: render :template => 'foo/bar.json' now works as it should. --- actionpack/lib/abstract_controller/rendering.rb | 1 - actionpack/lib/action_view/render/partials.rb | 14 ++++++++------ actionpack/lib/action_view/render/rendering.rb | 21 ++++++++++++++++++--- actionpack/lib/action_view/template.rb | 4 ++-- .../test/controller/new_base/render_partial_test.rb | 17 +++++++++++++++-- .../controller/new_base/render_template_test.rb | 15 ++++++++++++++- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index b4ab3481d5..e88e5aefc0 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -12,7 +12,6 @@ module AbstractController # This is a class to fix I18n global state. Whenever you provide I18n.locale during a request, # it will trigger the lookup_context and consequently expire the cache. - # TODO Add some deprecation warnings to remove I18n.locale from controllers class I18nProxy < ::I18n::Config #:nodoc: attr_reader :i18n_config, :lookup_context diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index f7bdbd6917..24d9e9ffb5 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -371,13 +371,15 @@ module ActionView end def _render_partial(options, &block) #:nodoc: - if defined?(@renderer) - @renderer.setup(options, block) - else - @renderer = PartialRenderer.new(self, options, block) - end + _wrap_formats(options[:partial]) do + if defined?(@renderer) + @renderer.setup(options, block) + else + @renderer = PartialRenderer.new(self, options, block) + end - @renderer.render + @renderer.render + end end end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 0771b40c37..8e599c71df 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -21,9 +21,11 @@ module ActionView elsif options.key?(:partial) _render_partial(options) else - template = _determine_template(options) - lookup_context.freeze_formats(template.formats, true) - _render_template(template, options[:layout], options) + _wrap_formats(options[:template] || options[:file]) do + template = _determine_template(options) + lookup_context.freeze_formats(template.formats, true) + _render_template(template, options[:layout], options) + end end when :update update_page(&block) @@ -32,6 +34,19 @@ module ActionView end end + # Checks if the given path contains a format and if so, change + # the lookup context to take this new format into account. + def _wrap_formats(value) + return yield unless value.is_a?(String) + @@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/ + + if value.sub!(@@formats_regexp, "") + update_details(:formats => [$1.to_sym]){ yield } + else + yield + end + end + # Determine the template to be rendered using the given options. def _determine_template(options) #:nodoc: keys = (options[:locals] ||= {}).keys diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 7e65654d0b..c15a0eb568 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -121,7 +121,7 @@ module ActionView @method_names = {} @locals = details[:locals] || [] @formats = Array.wrap(details[:format] || :html).map(&:to_sym) - @virtual_path = details[:virtual_path].try(:sub, ".#{@formats.first}", "") + @virtual_path = details[:virtual_path] @compiled = false end @@ -286,7 +286,7 @@ module ActionView pieces = @virtual_path.split("/") name = pieces.pop partial = name.sub!(/^_/, "") - view.find_template(name, pieces.join, partial || false, @locals) + view.find_template(name, pieces.join, partial || false, ["unlikely_local_key"]) end def method_name diff --git a/actionpack/test/controller/new_base/render_partial_test.rb b/actionpack/test/controller/new_base/render_partial_test.rb index 5c7e66dba2..d800ea264d 100644 --- a/actionpack/test/controller/new_base/render_partial_test.rb +++ b/actionpack/test/controller/new_base/render_partial_test.rb @@ -5,10 +5,17 @@ module RenderPartial class BasicController < ActionController::Base self.view_paths = [ActionView::FixtureResolver.new( - "render_partial/basic/_basic.html.erb" => "BasicPartial!", - "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>" + "render_partial/basic/_basic.html.erb" => "BasicPartial!", + "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>", + "render_partial/basic/with_json.html.erb" => "<%= render 'with_json.json' %>", + "render_partial/basic/_with_json.json.erb" => "<%= render 'final' %>", + "render_partial/basic/_final.json.erb" => "{ final: json }" )] + def html_with_json_inside_json + render :action => "with_json" + end + def changing @test_unchanged = 'hello' render :action => "basic" @@ -22,6 +29,12 @@ module RenderPartial get :changing assert_response("goodbyeBasicPartial!goodbye") end + + test "rendering a template with renders another partial with other format that renders other partial in the same format" do + get :html_with_json_inside_json + assert_content_type "text/html; charset=utf-8" + assert_response "{ final: json }" + end end end diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index fea98d6bbd..8f5f51d70b 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -8,13 +8,20 @@ module RenderTemplate "shared.html.erb" => "Elastica", "locals.html.erb" => "The secret is <%= secret %>", "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend", - "with_raw.html.erb" => "Hello <%=raw 'this is raw' %>" + "with_raw.html.erb" => "Hello <%=raw 'this is raw' %>", + "test/with_json.html.erb" => "<%= render :template => 'test/with_json.json' %>", + "test/with_json.json.erb" => "<%= render :template => 'test/final' %>", + "test/final.json.erb" => "{ final: json }" )] def index render :template => "test/basic" end + def html_with_json_inside_json + render :template => "test/with_json" + end + def index_without_key render "test/basic" end @@ -88,6 +95,12 @@ module RenderTemplate assert_body "Hello this is raw" assert_status 200 end + + test "rendering a template with renders another template with other format that renders other template in the same format" do + get :html_with_json_inside_json + assert_content_type "text/html; charset=utf-8" + assert_response "{ final: json }" + end end class WithLayoutController < ::ApplicationController -- cgit v1.2.3 From c7760809bfc8e19362272b71b23a294d48195d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 7 Oct 2010 21:30:19 +0200 Subject: Allow cache to be temporarily disabled through lookup_context. --- actionpack/lib/action_view/lookup_context.rb | 13 ++++++++++++- actionpack/lib/action_view/template.rb | 4 +++- actionpack/lib/action_view/testing/resolvers.rb | 8 +++++--- .../controller/new_base/render_template_test.rb | 13 ++++++++++++- actionpack/test/template/lookup_context_test.rb | 21 +++++++++++++++++++++ 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 794fdeae64..0cff888ac1 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -61,6 +61,7 @@ module ActionView def initialize(view_paths, details = {}) @details, @details_key = { :handlers => default_handlers }, nil @frozen_formats, @skip_default_locale = false, false + @cache = details.key?(:cache) ? details.delete(:cache) : true self.view_paths = view_paths self.registered_detail_setters.each do |key, setter| @@ -130,10 +131,20 @@ module ActionView end module Details + attr_accessor :cache + # Calculate the details key. Remove the handlers from calculation to improve performance # since the user cannot modify it explicitly. def details_key #:nodoc: - @details_key ||= DetailsKey.get(@details) + @details_key ||= DetailsKey.get(@details) if @cache + end + + # Temporary skip passing the details_key forward. + def disable_cache + old_value, @cache = @cache, false + yield + ensure + @cache = old_value end # Freeze the current formats in the lookup context. By freezing them, you are guaranteeing diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index c15a0eb568..1268b2f426 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -286,7 +286,9 @@ module ActionView pieces = @virtual_path.split("/") name = pieces.pop partial = name.sub!(/^_/, "") - view.find_template(name, pieces.join, partial || false, ["unlikely_local_key"]) + view.lookup_context.disable_cache do + view.find_template(name, pieces.join, partial || false, @locals) + end end def method_name diff --git a/actionpack/lib/action_view/testing/resolvers.rb b/actionpack/lib/action_view/testing/resolvers.rb index 6d82fa0971..ec0db48379 100644 --- a/actionpack/lib/action_view/testing/resolvers.rb +++ b/actionpack/lib/action_view/testing/resolvers.rb @@ -16,16 +16,18 @@ module ActionView #:nodoc: private def query(path, exts, formats) - query = Regexp.escape(path) + query = "" exts.each do |ext| query << '(' << ext.map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)' end + query = /^(#{Regexp.escape(path)})#{query}$/ templates = [] - @hash.select { |k,v| k =~ /^#{query}$/ }.each do |_path, source| + @hash.each do |_path, source| + next unless _path =~ query handler, format = extract_handler_and_format(_path, formats) templates << Template.new(source, _path, handler, - :virtual_path => _path, :format => format) + :virtual_path => $1, :format => format) end templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size } diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index 8f5f51d70b..d31193a063 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -11,7 +11,8 @@ module RenderTemplate "with_raw.html.erb" => "Hello <%=raw 'this is raw' %>", "test/with_json.html.erb" => "<%= render :template => 'test/with_json.json' %>", "test/with_json.json.erb" => "<%= render :template => 'test/final' %>", - "test/final.json.erb" => "{ final: json }" + "test/final.json.erb" => "{ final: json }", + "test/with_error.html.erb" => "<%= idontexist %>" )] def index @@ -49,6 +50,10 @@ module RenderTemplate def with_raw render :template => "with_raw" end + + def with_error + render :template => "test/with_error" + end end class TestWithoutLayout < Rack::TestCase @@ -101,6 +106,12 @@ module RenderTemplate assert_content_type "text/html; charset=utf-8" assert_response "{ final: json }" end + + test "rendering a template with error properly exceprts the code" do + get :with_error + assert_status 500 + assert_match "undefined local variable or method `idontexist'", response.body + end end class WithLayoutController < ::ApplicationController diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index cc71cb42d0..55d581e512 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -163,4 +163,25 @@ class LookupContextTest < ActiveSupport::TestCase template = @lookup_context.find("foo", "test", true) assert_equal "Bar", template.source end + + test "can disable the cache on demand" do + @lookup_context.view_paths = ActionView::FixtureResolver.new("test/_foo.erb" => "Foo") + old_template = @lookup_context.find("foo", "test", true) + + template = @lookup_context.find("foo", "test", true) + assert_equal template, old_template + + assert @lookup_context.cache + template = @lookup_context.disable_cache do + assert !@lookup_context.cache + @lookup_context.find("foo", "test", true) + end + assert @lookup_context.cache + + assert_not_equal template, old_template + end + + test "can have cache disabled on initialization" do + assert !ActionView::LookupContext.new(FIXTURE_LOAD_PATH, :cache => false).cache + end end \ No newline at end of file -- cgit v1.2.3 From 581b2b68368e3330cc725a305d0e2465c2e71e1c Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Fri, 8 Oct 2010 11:12:11 +1300 Subject: fix rendering a partial with an array as its :object [#5746 state:resolved] Signed-off-by: Michael Koziarski Conflicts: actionpack/lib/action_view/render/partials.rb --- actionpack/lib/action_view/render/partials.rb | 10 +++++++--- actionpack/test/fixtures/test/_object_inspector.erb | 1 + actionpack/test/template/render_test.rb | 4 ++++ 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 actionpack/test/fixtures/test/_object_inspector.erb diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 24d9e9ffb5..4e03d43358 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -235,7 +235,7 @@ module ActionView else @object = partial - if @collection = collection + if @collection = collection_from_object || collection paths = @collection_data = @collection.map { |o| partial_path(o) } @path = paths.uniq.size == 1 ? paths.first : nil else @@ -337,10 +337,14 @@ module ActionView private def collection + if @options.key?(:collection) + @options[:collection] || [] + end + end + + def collection_from_object if @object.respond_to?(:to_ary) @object - elsif @options.key?(:collection) - @options[:collection] || [] end end diff --git a/actionpack/test/fixtures/test/_object_inspector.erb b/actionpack/test/fixtures/test/_object_inspector.erb new file mode 100644 index 0000000000..53af593821 --- /dev/null +++ b/actionpack/test/fixtures/test/_object_inspector.erb @@ -0,0 +1 @@ +<%= object_inspector.inspect -%> \ No newline at end of file diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 205fdcf345..756d8d05d2 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -127,6 +127,10 @@ module RenderTestCases assert_equal "Hello: david", @view.render(:partial => "test/customer", :object => Customer.new("david")) end + def test_render_object_with_array + assert_equal "[1, 2, 3]", @view.render(:partial => "test/object_inspector", :object => [1, 2, 3]) + end + def test_render_partial_collection assert_equal "Hello: davidHello: mary", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), Customer.new("mary") ]) end -- cgit v1.2.3 From 740d7e5aa2e778cd3cf87090745b37ee97dac618 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 7 Oct 2010 16:40:15 -0600 Subject: removing false comment --- .../lib/active_record/connection_adapters/abstract/connection_pool.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 0c264de869..ca9314ec99 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -73,8 +73,6 @@ module ActiveRecord # The mutex used to synchronize pool access @connection_mutex = Monitor.new @queue = @connection_mutex.new_cond - - # default 5 second timeout unless on ruby 1.9 @timeout = spec.config[:wait_timeout] || 5 # default max pool size to 5 -- cgit v1.2.3 From c3c6f58ffb4a27f843378d4cce45c52831fb2e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vesa=20V=C3=A4nsk=C3=A4?= Date: Fri, 8 Oct 2010 15:01:33 +0800 Subject: Fixed rake task description typo --- railties/lib/rails/tasks/documentation.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake index 7aefbb49b0..edd716d7d0 100644 --- a/railties/lib/rails/tasks/documentation.rake +++ b/railties/lib/rails/tasks/documentation.rake @@ -47,7 +47,7 @@ namespace :doc do rdoc.rdoc_files.include('app/**/*.rb') rdoc.rdoc_files.include('lib/**/*.rb') } - Rake::Task['doc:app'].comment = "Generate docs for the app -- also availble doc:rails, doc:guides, doc:plugins (options: TEMPLATE=/rdoc-template.rb, TITLE=\"Custom Title\")" + Rake::Task['doc:app'].comment = "Generate docs for the app -- also available doc:rails, doc:guides, doc:plugins (options: TEMPLATE=/rdoc-template.rb, TITLE=\"Custom Title\")" # desc 'Generate documentation for the Rails framework.' RDocTaskWithoutDescriptions.new("rails") { |rdoc| -- cgit v1.2.3 From 54b09e17d4527bb4e5508d7dcb286040c3e3ea3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 8 Oct 2010 09:24:06 +0200 Subject: Fix 1.9.2 failures. --- actionpack/test/template/template_test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 210ba673f0..27b42006e3 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -32,8 +32,8 @@ class TestERBTemplate < ActiveSupport::TestCase end end - def new_template(body = "<%= hello %>", handler = ERBHandler, details = {}) - ActionView::Template.new(body, "hello template", ERBHandler, {:virtual_path => "hello"}) + def new_template(body = "<%= hello %>", details = {}) + ActionView::Template.new(body, "hello template", ERBHandler, {:virtual_path => "hello"}.merge!(details)) end def render(locals = {}) @@ -102,7 +102,7 @@ class TestERBTemplate < ActiveSupport::TestCase # inside Rails. def test_lying_with_magic_comment assert_raises(ActionView::Template::Error) do - @template = new_template("# encoding: UTF-8\nhello \xFCmlat") + @template = new_template("# encoding: UTF-8\nhello \xFCmlat", :virtual_path => nil) render end end @@ -118,7 +118,7 @@ class TestERBTemplate < ActiveSupport::TestCase def test_error_when_template_isnt_valid_utf8 assert_raises(ActionView::Template::Error, /\xFC/) do - @template = new_template("hello \xFCmlat") + @template = new_template("hello \xFCmlat", :virtual_path => nil) render end end -- cgit v1.2.3 From a0e482e807af5a1cd1470a1dd4efd97920e8c89e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 8 Oct 2010 09:29:07 +0200 Subject: Ensure rack body responds to each. --- railties/test/railties/engine_test.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 5eed4def14..ee01a4d6de 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -71,8 +71,7 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY class Bukkits class Engine < ::Rails::Engine - endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, 'Hello World'] } - + endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, ['Hello World']] } config.middleware.use ::RailtiesTest::EngineTest::Upcaser end end @@ -102,7 +101,7 @@ module RailtiesTest @plugin.write "config/routes.rb", <<-RUBY Bukkits::Engine.routes.draw do - match "/foo" => lambda { |env| [200, {'Content-Type' => 'text/html'}, 'foo'] } + match "/foo" => lambda { |env| [200, {'Content-Type' => 'text/html'}, ['foo']] } end RUBY -- cgit v1.2.3 From f1f2fb8ae733c4602ba2ec2d7ea830a85c64b4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 8 Oct 2010 16:14:39 +0200 Subject: Cleanup logger a bit. --- .../lib/active_support/core_ext/logger.rb | 49 +++++----------------- 1 file changed, 11 insertions(+), 38 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb index a1c351bfd9..e63a0a9ed9 100644 --- a/activesupport/lib/active_support/core_ext/logger.rb +++ b/activesupport/lib/active_support/core_ext/logger.rb @@ -4,18 +4,17 @@ require 'active_support/core_ext/class/attribute_accessors' class Logger #:nodoc: def self.define_around_helper(level) module_eval <<-end_eval, __FILE__, __LINE__ + 1 - def around_#{level}(before_message, after_message, &block) # def around_debug(before_message, after_message, &block) - self.#{level}(before_message) # self.debug(before_message) - return_value = block.call(self) # return_value = block.call(self) - self.#{level}(after_message) # self.debug(after_message) - return return_value # return return_value - end # end + def around_#{level}(before_message, after_message) # def around_debug(before_message, after_message, &block) + self.#{level}(before_message) # self.debug(before_message) + return_value = yield(self) # return_value = yield(self) + self.#{level}(after_message) # self.debug(after_message) + return_value # return_value + end # end end_eval end [:debug, :info, :error, :fatal].each {|level| define_around_helper(level) } end - require 'logger' # Extensions to the built-in Ruby logger. @@ -65,11 +64,11 @@ class Logger formatter.datetime_format if formatter.respond_to?(:datetime_format) end - alias :old_formatter :formatter if method_defined?(:formatter) - # Get the current formatter. The default formatter is a SimpleFormatter which only - # displays the log message - def formatter - @formatter ||= SimpleFormatter.new + alias :old_initialize :initialize + # Overwrite initialize to set a default formatter. + def initialize(*args) + old_initialize(*args) + self.formatter = SimpleFormatter.new end # Simple formatter which only displays the message. @@ -79,30 +78,4 @@ class Logger "#{String === msg ? msg : msg.inspect}\n" end end - - private - alias old_format_message format_message - - # Ruby 1.8.3 transposed the msg and progname arguments to format_message. - # We can't test RUBY_VERSION because some distributions don't keep Ruby - # and its standard library in sync, leading to installations of Ruby 1.8.2 - # with Logger from 1.8.3 and vice versa. - if method_defined?(:formatter=) - def format_message(severity, timestamp, progname, msg) - formatter.call(severity, timestamp, progname, msg) - end - else - def format_message(severity, timestamp, msg, progname) - formatter.call(severity, timestamp, progname, msg) - end - - attr_writer :formatter - public :formatter= - - alias old_format_datetime format_datetime - def format_datetime(datetime) datetime end - - alias old_msg2str msg2str - def msg2str(msg) msg end - end end -- cgit v1.2.3 From 08f4713dba1ae013d5b3c9815cb7e33ea5533be5 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 6 Oct 2010 15:54:28 +0200 Subject: Refactored routes reloading to use RouteSet#append instead keeping block in Engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/lib/rails/application/routes_reloader.rb | 24 ++++++----------------- railties/lib/rails/engine.rb | 8 +++----- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb index 6da903c1ac..1d1f5e1b06 100644 --- a/railties/lib/rails/application/routes_reloader.rb +++ b/railties/lib/rails/application/routes_reloader.rb @@ -1,17 +1,15 @@ module Rails class Application class RoutesReloader < ::ActiveSupport::FileUpdateChecker + attr_reader :route_sets + def initialize super([]) { reload! } - end - - def blocks - @blocks ||= {} + @route_sets = [] end def reload! clear! - load_blocks load_paths finalize! ensure @@ -21,37 +19,27 @@ module Rails protected def clear! - routers.each do |routes| + route_sets.each do |routes| routes.disable_clear_and_finalize = true routes.clear! end end - def load_blocks - blocks.each do |routes, block| - routes.draw(&block) if block - end - end - def load_paths paths.each { |path| load(path) } end def finalize! - routers.each do |routes| + route_sets.each do |routes| ActiveSupport.on_load(:action_controller) { routes.finalize! } end end def revert - routers.each do |routes| + route_sets.each do |routes| routes.disable_clear_and_finalize = false end end - - def routers - blocks.keys - end end end end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 1aa24b6808..f8caaef213 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -419,9 +419,9 @@ module Rails } end - def routes(&block) + def routes @routes ||= ActionDispatch::Routing::RouteSet.new - self.routes_draw_block = block if block_given? + @routes.append(&Proc.new) if block_given? @routes end @@ -472,8 +472,8 @@ module Rails paths = self.paths["config/routes"].existent if routes? || paths.any? - app.routes_reloader.blocks[routes] = routes_draw_block app.routes_reloader.paths.unshift(*paths) + app.routes_reloader.route_sets << routes end end @@ -523,8 +523,6 @@ module Rails end protected - attr_accessor :routes_draw_block - def routes? defined?(@routes) end -- cgit v1.2.3 From e68c87bb65640146b0b40456f68b3f0b2571619d Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 8 Oct 2010 16:31:46 +0200 Subject: Fix engines test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/test/railties/engine_test.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index ee01a4d6de..0ce11b1f79 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -62,12 +62,14 @@ module RailtiesTest def call(env) response = @app.call(env) - response[2].upcase! + response[2].each { |b| b.upcase! } response end end test "engine is a rack app and can have his own middleware stack" do + add_to_config("config.action_dispatch.show_exceptions = false") + @plugin.write "lib/bukkits.rb", <<-RUBY class Bukkits class Engine < ::Rails::Engine -- cgit v1.2.3 From 5826c1730720e8b11f7cc82831a1c76427e9ada2 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 8 Oct 2010 16:17:36 +0530 Subject: Remove the final initializers since initializers += will return it anyway. [#3892 state:resolved] Signed-off-by: Santiago Pastorino --- railties/lib/rails/application.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 5559f49fbd..2c5d1661ff 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -131,7 +131,6 @@ module Rails initializers = Bootstrap.initializers_for(self) initializers += super initializers += Finisher.initializers_for(self) - initializers end def config -- cgit v1.2.3 From e9793c60b6fc2a2d048d2d7cadb7f8d0db83110b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 8 Oct 2010 12:58:24 -0200 Subject: Makes this code a bit more clear --- railties/lib/rails/application.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 2c5d1661ff..d13356ab4d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -128,9 +128,9 @@ module Rails end def initializers - initializers = Bootstrap.initializers_for(self) - initializers += super - initializers += Finisher.initializers_for(self) + Bootstrap.initializers_for(self) + + super + + Finisher.initializers_for(self) end def config -- cgit v1.2.3 From f415b3e6d18f0e018e08f2af8e19e40ac93a8524 Mon Sep 17 00:00:00 2001 From: James Mead Date: Fri, 8 Oct 2010 15:21:08 -0200 Subject: Remove old workaround for mocha bug. [#3886 state:committed] Signed-off-by: Santiago Pastorino --- actionmailer/test/old_base/mail_service_test.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/actionmailer/test/old_base/mail_service_test.rb b/actionmailer/test/old_base/mail_service_test.rb index 93921978b6..0b5b0b2da3 100644 --- a/actionmailer/test/old_base/mail_service_test.rb +++ b/actionmailer/test/old_base/mail_service_test.rb @@ -328,7 +328,6 @@ class ActionMailerTest < Test::Unit::TestCase mail end - # Replacing logger work around for mocha bug. Should be fixed in mocha 0.3.3 def setup set_delivery_method :test ActionMailer::Base.perform_deliveries = true @@ -336,14 +335,12 @@ class ActionMailerTest < Test::Unit::TestCase ActionMailer::Base.deliveries.clear ActiveSupport::Deprecation.silenced = true - @original_logger = TestMailer.logger @recipient = 'test@localhost' TestMailer.delivery_method = :test end def teardown - TestMailer.logger = @original_logger ActiveSupport::Deprecation.silenced = false restore_delivery_method end @@ -1097,4 +1094,4 @@ EOF ensure TestMailer.smtp_settings.merge!(:enable_starttls_auto => true) end -end \ No newline at end of file +end -- cgit v1.2.3 From 067c1aa0e098f293a99953c50babaf201bba60cd Mon Sep 17 00:00:00 2001 From: Andrew White Date: Fri, 8 Oct 2010 22:00:27 +0100 Subject: Refactor resource action scope methods --- actionpack/lib/action_dispatch/routing/mapper.rb | 58 ++++++++---------------- 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index bf10f81127..3c7dcea003 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -735,15 +735,15 @@ module ActionDispatch resource_scope(SingletonResource.new(resources.pop, options)) do yield if block_given? - collection_scope do + collection do post :create end if parent_resource.actions.include?(:create) - new_scope do + new do get :new end if parent_resource.actions.include?(:new) - member_scope do + member do get :edit if parent_resource.actions.include?(:edit) get :show if parent_resource.actions.include?(:show) put :update if parent_resource.actions.include?(:update) @@ -780,16 +780,16 @@ module ActionDispatch resource_scope(Resource.new(resources.pop, options)) do yield if block_given? - collection_scope do + collection do get :index if parent_resource.actions.include?(:index) post :create if parent_resource.actions.include?(:create) end - new_scope do + new do get :new end if parent_resource.actions.include?(:new) - member_scope do + member do get :edit if parent_resource.actions.include?(:edit) get :show if parent_resource.actions.include?(:show) put :update if parent_resource.actions.include?(:update) @@ -813,12 +813,14 @@ module ActionDispatch # create the search_photos_url and search_photos_path # route helpers. def collection - unless @scope[:scope_level] == :resources - raise ArgumentError, "can't use collection outside resources scope" + unless resource_scope? + raise ArgumentError, "can't use collection outside resource(s) scope" end - collection_scope do - yield + with_scope_level(:collection) do + scope(parent_resource.collection_scope) do + yield + end end end @@ -838,8 +840,10 @@ module ActionDispatch raise ArgumentError, "can't use member outside resource(s) scope" end - member_scope do - yield + with_scope_level(:member) do + scope(parent_resource.member_scope) do + yield + end end end @@ -848,8 +852,10 @@ module ActionDispatch raise ArgumentError, "can't use new outside resource(s) scope" end - new_scope do - yield + with_scope_level(:new) do + scope(parent_resource.new_scope(action_path(:new))) do + yield + end end end @@ -1034,30 +1040,6 @@ module ActionDispatch end end - def new_scope - with_scope_level(:new) do - scope(parent_resource.new_scope(action_path(:new))) do - yield - end - end - end - - def collection_scope - with_scope_level(:collection) do - scope(parent_resource.collection_scope) do - yield - end - end - end - - def member_scope - with_scope_level(:member) do - scope(parent_resource.member_scope) do - yield - end - end - end - def nested_options {}.tap do |options| options[:as] = parent_resource.member_name -- cgit v1.2.3 From b439c145164237cd8102f39f64e889a4d1df9334 Mon Sep 17 00:00:00 2001 From: Juan Maiz Date: Fri, 8 Oct 2010 10:58:09 -0300 Subject: Fixing two minor errors in Rails::Generators::Actions initializer method comments [#5771 state:committed] Signed-off-by: Santiago Pastorino --- railties/lib/rails/generators/actions.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 8f0d5ffff4..378c07cb0e 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -187,8 +187,8 @@ module Rails # initializer("globals.rb") do # data = "" # - # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do - # data << "#{const} = :entp" + # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do |const| + # data << "#{const} = :entp\n" # end # # data -- cgit v1.2.3 From e695c40e11135e54e40aef97718f88d20a0967c2 Mon Sep 17 00:00:00 2001 From: Andrea Campi Date: Sat, 9 Oct 2010 12:11:57 +0200 Subject: Fix example that became outdated after a code change. [#5770 state:resolved] Signed-off-by: Santiago Pastorino --- actionpack/lib/action_view/helpers/asset_tag_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index c1dfbe5dc3..3ff80579e2 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -152,7 +152,7 @@ module ActionView # # # Normally you'd calculate RELEASE_NUMBER at startup. # RELEASE_NUMBER = 12345 - # config.action_controller.asset_path_template = proc { |asset_path| + # config.action_controller.asset_path = proc { |asset_path| # "/release-#{RELEASE_NUMBER}#{asset_path}" # } # -- cgit v1.2.3 From e7f911d5ca58e83b94f58d5f44352794b27b2a10 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 9 Oct 2010 13:11:22 -0200 Subject: Test if test/performance/browsing_test.rb exists when --skip-activerecord is used [#4104] --- railties/test/generators/app_generator_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 3653b067c8..d2126f3433 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -168,6 +168,7 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_config_database_is_not_added_if_skip_active_record_is_given run_generator [destination_root, "--skip-active-record"] assert_no_file "config/database.yml" + assert_file "test/performance/browsing_test.rb" end def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given -- cgit v1.2.3 From 36862511e065d5ea02dae9d2dcb7f498af99cab1 Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Sat, 9 Oct 2010 13:31:32 -0200 Subject: test that skip active records does not load fixtures [#4104 state:committed] Signed-off-by: Santiago Pastorino --- railties/test/generators/app_generator_test.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index d2126f3433..d752d18285 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -168,6 +168,9 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_config_database_is_not_added_if_skip_active_record_is_given run_generator [destination_root, "--skip-active-record"] assert_no_file "config/database.yml" + assert_file "test/test_helper.rb" do |helper_content| + assert_no_match /fixtures :all/, helper_content + end assert_file "test/performance/browsing_test.rb" end -- cgit v1.2.3 From 6286629acab6361ab7046e3ec61157c3b4dbca93 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 9 Oct 2010 13:36:54 -0200 Subject: This test is not only testing config/database stuff anymore --- railties/test/generators/app_generator_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index d752d18285..51277b805b 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -165,7 +165,7 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "Gemfile", /^gem\s+["']mysql2["']$/ end - def test_config_database_is_not_added_if_skip_active_record_is_given + def test_generator_if_skip_active_record_is_given run_generator [destination_root, "--skip-active-record"] assert_no_file "config/database.yml" assert_file "test/test_helper.rb" do |helper_content| -- cgit v1.2.3 From afd76d7fe9bb5e1b90a3b1c75abe45488e871f72 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 9 Oct 2010 14:50:25 -0200 Subject: Fix error in routing guide edit_photo_path needs the id as param --- railties/guides/source/routing.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 7d4fb69d3b..a8a8ee58ec 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -91,7 +91,7 @@ Creating a resourceful route will also expose a number of helpers to the control * +photos_path+ returns +/photos+ * +new_photo_path+ returns +/photos/new+ -* +edit_photo_path+ returns +/photos/:id/edit+ +* +edit_photo_path(id)+ returns +/photos/:id/edit+ (for instance, +edit_photo_path(10)+ returns +/photos/10/edit+) * +photo_path(id)+ returns +/photos/:id+ (for instance, +photo_path(10)+ returns +/photos/10+) Each of these helpers has a corresponding +_url+ helper (such as +photos_url+) which returns the same path prefixed with the current host, port and path prefix. -- cgit v1.2.3 From 5d5eb2b18d364cb27d2062668bd3b1921b1040a8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 9 Oct 2010 20:59:20 +0200 Subject: Rename namespace method to isolate_namespace. This change caused by confusion caused by calling engine "namespaced". Stuff inside engine can be namespaced for every engine. This method is not actually namespacing anything, it's isolating engine within the given namespace. --- railties/lib/rails/engine.rb | 20 ++++++++++---------- .../test/generators/namespaced_generators_test.rb | 4 ++-- railties/test/railties/engine_test.rb | 16 ++++++++-------- railties/test/railties/mounted_engine_test.rb | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index f8caaef213..909840da04 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -214,11 +214,11 @@ module Rails # as they would be created inside application. One of the cosequences of that is including # application's helpers and url_helpers inside controller. Sometimes, especially when your # engine provides its own routes, you don't want that. To isolate engine's stuff from application - # you can use namespace method: + # you can use isolate_namespace method: # # module MyEngine # class Engine < Rails::Engine - # namespace MyEngine + # isolate_namespace MyEngine # end # end # @@ -252,7 +252,7 @@ module Rails # end # # - # Additionaly namespaced engine will set its name according to namespace, so in that case: + # Additionaly isolated engine will set its name according to namespace, so in that case: # MyEngine::Engine.engine_name #=> "my_engine" and it will set MyEngine.table_name_prefix # to "my_engine_". # @@ -315,7 +315,7 @@ module Rails autoload :Configuration, "rails/engine/configuration" class << self - attr_accessor :called_from, :namespaced + attr_accessor :called_from, :isolated alias :engine_name :railtie_name def inherited(base) @@ -350,12 +350,12 @@ module Rails @endpoint end - def namespace(mod) + def isolate_namespace(mod) engine_name(generate_railtie_name(mod)) name = engine_name self.routes.default_scope = {:module => name} - self.namespaced = true + self.isolated = true unless mod.respond_to?(:_railtie) _railtie = self @@ -371,13 +371,13 @@ module Rails end end - def namespaced? - !!namespaced + def isolated? + !!isolated end end delegate :middleware, :root, :paths, :to => :config - delegate :engine_name, :namespaced?, :to => "self.class" + delegate :engine_name, :isolated?, :to => "self.class" def load_tasks super @@ -506,7 +506,7 @@ module Rails end initializer :prepend_helpers_path do |app| - if !namespaced? || (app == self) + if !isolated? || (app == self) app.config.helpers_paths.unshift(*paths["app/helpers"].existent) end end diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb index 38b95a49ac..d1190fd17d 100644 --- a/railties/test/generators/namespaced_generators_test.rb +++ b/railties/test/generators/namespaced_generators_test.rb @@ -6,14 +6,14 @@ require 'rails/generators/mailer/mailer_generator' class NamespacedGeneratorTestCase < Rails::Generators::TestCase def setup - TestApp::Application.namespace(TestApp) + TestApp::Application.isolate_namespace(TestApp) end def teardown if TestApp.respond_to?(:_railtie) TestApp.singleton_class.send(:undef_method, :_railtie) TestApp.singleton_class.send(:undef_method, :table_name_prefix) - TestApp::Application.namespaced = false + TestApp::Application.isolated = false end end end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 0ce11b1f79..db74e41472 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -394,7 +394,7 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits class Engine < ::Rails::Engine - namespace Bukkits + isolate_namespace Bukkits end end RUBY @@ -511,7 +511,7 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits class Engine < ::Rails::Engine - namespace Bukkits + isolate_namespace Bukkits end end RUBY @@ -572,7 +572,7 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits class Engine < ::Rails::Engine - namespace(Bukkits) + isolate_namespace(Bukkits) end end RUBY @@ -593,7 +593,7 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits class Engine < ::Rails::Engine - namespace(Bukkits) + isolate_namespace(Bukkits) paths["public"] = "#{File.join(@plugin.path, "alternate_public")}" end end @@ -611,7 +611,7 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits class Engine < ::Rails::Engine - namespace(Bukkits) + isolate_namespace(Bukkits) paths["public"] = "#{File.join(@plugin.path, "not_existing")}" end end @@ -648,12 +648,12 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY module AppTemplate class Engine < ::Rails::Engine - namespace(AppTemplate) + isolate_namespace(AppTemplate) end end RUBY - add_to_config "namespace AppTemplate" + add_to_config "isolate_namespace AppTemplate" app_file "config/routes.rb", <<-RUBY AppTemplate::Application.routes.draw do end @@ -686,7 +686,7 @@ module RailtiesTest @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits class Engine < ::Rails::Engine - namespace(Bukkits) + isolate_namespace(Bukkits) end end RUBY diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb index b52ced92ec..47a4753e78 100644 --- a/railties/test/railties/mounted_engine_test.rb +++ b/railties/test/railties/mounted_engine_test.rb @@ -49,7 +49,7 @@ module ApplicationTests @plugin.write "lib/blog.rb", <<-RUBY module Blog class Engine < ::Rails::Engine - namespace(Blog) + isolate_namespace(Blog) end end RUBY -- cgit v1.2.3 From 4377f8eba2dde51fe5d3bc50248c0089e24c8d24 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 8 Oct 2010 21:17:14 +0200 Subject: Change the method for copying migrations, do not add scope. The purpose of this change is to allow copying fail on the same names. Migrations change database and they should be treated with caution, if 2 migrations are named the same it's much better to skip migration and allow user decide if it should be copied or not. --- activerecord/lib/active_record/migration.rb | 18 ++++----- activerecord/test/cases/migration_test.rb | 44 +++++++++++----------- .../test/migrations/to_copy2/1_create_articles.rb | 7 ++++ .../test/migrations/to_copy2/2_create_comments.rb | 7 ++++ .../20090101010101_create_articles.rb | 7 ++++ .../20090101010202_create_comments.rb | 7 ++++ 6 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 activerecord/test/migrations/to_copy2/1_create_articles.rb create mode 100644 activerecord/test/migrations/to_copy2/2_create_comments.rb create mode 100644 activerecord/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb create mode 100644 activerecord/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 9ac18f9939..3fc69d7af0 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -387,18 +387,18 @@ module ActiveRecord def copy(destination, sources) copied = [] - sources.each do |scope, path| + sources.each do |name, path| destination_migrations = ActiveRecord::Migrator.migrations(destination) source_migrations = ActiveRecord::Migrator.migrations(path) last = destination_migrations.last source_migrations.each do |migration| - next if destination_migrations.any? { |m| m.name == migration.name && m.scope == scope.to_s } + next if destination_migrations.any? { |m| m.name == migration.name } migration.version = next_migration_number(last ? last.version + 1 : 0).to_i last = migration - new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.#{scope}.rb") + new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.rb") FileUtils.cp(migration.filename, new_path) copied << new_path end @@ -419,9 +419,9 @@ module ActiveRecord # MigrationProxy is used to defer loading of the actual migration classes # until they are needed - class MigrationProxy < Struct.new(:name, :version, :filename, :scope) + class MigrationProxy < Struct.new(:name, :version, :filename) - def initialize(name, version, filename, scope) + def initialize(name, version, filename) super @migration = nil end @@ -510,18 +510,18 @@ module ActiveRecord seen = Hash.new false migrations = files.map do |file| - version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?.rb/).first + version, name = file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first raise IllegalMigrationNameError.new(file) unless version version = version.to_i name = name.camelize raise DuplicateMigrationVersionError.new(version) if seen[version] - raise DuplicateMigrationNameError.new(name) if seen[[name, scope]] + raise DuplicateMigrationNameError.new(name) if seen[name] - seen[version] = seen[[name, scope]] = true + seen[version] = seen[name] = true - MigrationProxy.new(name, version, file, scope) + MigrationProxy.new(name, version, file) end migrations.sort_by(&:version) diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 6e8ee95613..9635ab25fc 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -1910,9 +1910,9 @@ if ActiveRecord::Base.connection.supports_migrations? @existing_migrations = Dir[@migrations_path + "/*.rb"] copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) - assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb") - assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied + assert File.exists?(@migrations_path + "/4_people_have_hobbies.rb") + assert File.exists?(@migrations_path + "/5_people_have_descriptions.rb") + assert_equal [@migrations_path + "/4_people_have_hobbies.rb", @migrations_path + "/5_people_have_descriptions.rb"], copied files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) @@ -1928,12 +1928,13 @@ if ActiveRecord::Base.connection.supports_migrations? @existing_migrations = Dir[@migrations_path + "/*.rb"] sources = ActiveSupport::OrderedHash.new - sources[:bukkits] = sources[:omg] = MIGRATIONS_ROOT + "/to_copy" + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy" + sources[:omg] = MIGRATIONS_ROOT + "/to_copy2" ActiveRecord::Migration.copy(@migrations_path, sources) - assert File.exists?(@migrations_path + "/4_people_have_hobbies.omg.rb") - assert File.exists?(@migrations_path + "/5_people_have_descriptions.omg.rb") - assert File.exists?(@migrations_path + "/6_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/7_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/4_people_have_hobbies.rb") + assert File.exists?(@migrations_path + "/5_people_have_descriptions.rb") + assert File.exists?(@migrations_path + "/6_create_articles.rb") + assert File.exists?(@migrations_path + "/7_create_comments.rb") files_count = Dir[@migrations_path + "/*.rb"].length ActiveRecord::Migration.copy(@migrations_path, sources) @@ -1948,10 +1949,10 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(created_at = Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") - expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb", - @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"] + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") + expected = [@migrations_path + "/20100726101010_people_have_hobbies.rb", + @migrations_path + "/20100726101011_people_have_descriptions.rb"] assert_equal expected, copied files_count = Dir[@migrations_path + "/*.rb"].length @@ -1968,14 +1969,15 @@ if ActiveRecord::Base.connection.supports_migrations? @existing_migrations = Dir[@migrations_path + "/*.rb"] sources = ActiveSupport::OrderedHash.new - sources[:bukkits] = sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2" Time.travel_to(created_at = Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, sources) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.omg.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.omg.rb") - assert File.exists?(@migrations_path + "/20100726101012_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101013_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") + assert File.exists?(@migrations_path + "/20100726101012_create_articles.rb") + assert File.exists?(@migrations_path + "/20100726101013_create_comments.rb") assert_equal 4, copied.length files_count = Dir[@migrations_path + "/*.rb"].length @@ -1992,8 +1994,8 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(created_at = Time.utc(2010, 2, 20, 10, 10, 10)) do ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.rb") + assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.rb") files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) @@ -2010,8 +2012,8 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(created_at = Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") assert_equal 2, copied.length end ensure diff --git a/activerecord/test/migrations/to_copy2/1_create_articles.rb b/activerecord/test/migrations/to_copy2/1_create_articles.rb new file mode 100644 index 0000000000..0f048d90f7 --- /dev/null +++ b/activerecord/test/migrations/to_copy2/1_create_articles.rb @@ -0,0 +1,7 @@ +class CreateArticles < ActiveRecord::Migration + def self.up + end + + def self.down + end +end diff --git a/activerecord/test/migrations/to_copy2/2_create_comments.rb b/activerecord/test/migrations/to_copy2/2_create_comments.rb new file mode 100644 index 0000000000..0f048d90f7 --- /dev/null +++ b/activerecord/test/migrations/to_copy2/2_create_comments.rb @@ -0,0 +1,7 @@ +class CreateArticles < ActiveRecord::Migration + def self.up + end + + def self.down + end +end diff --git a/activerecord/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb b/activerecord/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb new file mode 100644 index 0000000000..0f048d90f7 --- /dev/null +++ b/activerecord/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb @@ -0,0 +1,7 @@ +class CreateArticles < ActiveRecord::Migration + def self.up + end + + def self.down + end +end diff --git a/activerecord/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb b/activerecord/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb new file mode 100644 index 0000000000..2b048edbb5 --- /dev/null +++ b/activerecord/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb @@ -0,0 +1,7 @@ +class CreateComments < ActiveRecord::Migration + def self.up + end + + def self.down + end +end -- cgit v1.2.3 From 022205be1d677d446437af0618697434472157e8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 9 Oct 2010 10:28:46 +0200 Subject: Add callback on skipped migration while copying migrations --- activerecord/lib/active_record/migration.rb | 27 ++++++++++++++++++++------- activerecord/test/cases/migration_test.rb | 22 ++++++++++++++++++++-- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 3fc69d7af0..a4c09b654a 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -384,23 +384,32 @@ module ActiveRecord end end - def copy(destination, sources) + def copy(destination, sources, options = {}) copied = [] + destination_migrations = ActiveRecord::Migrator.migrations(destination) + last = destination_migrations.last sources.each do |name, path| - destination_migrations = ActiveRecord::Migrator.migrations(destination) source_migrations = ActiveRecord::Migrator.migrations(path) - last = destination_migrations.last source_migrations.each do |migration| - next if destination_migrations.any? { |m| m.name == migration.name } + source = File.read(migration.filename) + source = "# This migration comes from #{name} (originally #{migration.version})\n#{source}" + + if duplicate = destination_migrations.detect { |m| m.name == migration.name } + options[:on_skip].call(name, migration) if File.read(duplicate.filename) != source && options[:on_skip] + next + end migration.version = next_migration_number(last ? last.version + 1 : 0).to_i + new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.rb") + old_path, migration.filename = migration.filename, new_path last = migration - new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.rb") - FileUtils.cp(migration.filename, new_path) - copied << new_path + FileUtils.cp(old_path, migration.filename) + copied << migration + options[:on_copy].call(name, migration, old_path) if options[:on_copy] + destination_migrations << migration end end @@ -426,6 +435,10 @@ module ActiveRecord @migration = nil end + def basename + File.basename(filename) + end + delegate :migrate, :announce, :write, :to=>:migration private diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 9635ab25fc..ef949300b0 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -1912,7 +1912,7 @@ if ActiveRecord::Base.connection.supports_migrations? copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) assert File.exists?(@migrations_path + "/4_people_have_hobbies.rb") assert File.exists?(@migrations_path + "/5_people_have_descriptions.rb") - assert_equal [@migrations_path + "/4_people_have_hobbies.rb", @migrations_path + "/5_people_have_descriptions.rb"], copied + assert_equal [@migrations_path + "/4_people_have_hobbies.rb", @migrations_path + "/5_people_have_descriptions.rb"], copied.map(&:filename) files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) @@ -1953,7 +1953,7 @@ if ActiveRecord::Base.connection.supports_migrations? assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") expected = [@migrations_path + "/20100726101010_people_have_hobbies.rb", @migrations_path + "/20100726101011_people_have_descriptions.rb"] - assert_equal expected, copied + assert_equal expected, copied.map(&:filename) files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) @@ -2006,6 +2006,24 @@ if ActiveRecord::Base.connection.supports_migrations? clear end + def test_skipping_migrations + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] + + sources = ActiveSupport::OrderedHash.new + sources[:bukkits] = sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + + skipped = [] + on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } + copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + assert_equal 2, copied.length + + assert_equal 2, skipped.length + assert_equal ["bukkits PeopleHaveHobbies", "bukkits PeopleHaveDescriptions"], skipped + ensure + clear + end + def test_copying_migrations_to_empty_directory @migrations_path = MIGRATIONS_ROOT + "/empty" @existing_migrations = [] -- cgit v1.2.3 From 8636f64defb4b6fd9f00c70ffc9dc7ffc017fe58 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 9 Oct 2010 12:15:36 +0200 Subject: Rename rake railties:copy_migrations to rake railties:install:migrations and fix it to work with new copying strategy --- .../lib/active_record/railties/databases.rake | 48 +++++++++++----------- railties/test/railties/shared_tests.rb | 27 +++++++----- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 4ef6c6f751..778bce697e 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -5,27 +5,6 @@ namespace :db do ActiveRecord::Migrator.migrations_path = Rails.application.paths["db/migrate"].first end - task :copy_migrations => :load_config do - to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map {|n| n.strip } - railties = {} - Rails.application.railties.all do |railtie| - next unless to_load == :all || to_load.include?(railtie.railtie_name) - - if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first) - railties[railtie.railtie_name] = path - end - end - - copied = ActiveRecord::Migration.copy(ActiveRecord::Migrator.migrations_path, railties) - - if copied.blank? - puts "No migrations were copied, project is up to date." - else - puts "The following migrations were copied:" - puts copied.map{ |path| File.basename(path) }.join("\n") - end - end - namespace :create do # desc 'Create all the local databases defined in config/database.yml' task :all => :load_config do @@ -501,8 +480,31 @@ namespace :db do end namespace :railties do - desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2" - task :copy_migrations => 'db:copy_migrations' + namespace :install do + desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2" + task :migrations => :"db:load_config" do + to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map {|n| n.strip } + railties = {} + Rails.application.railties.all do |railtie| + next unless to_load == :all || to_load.include?(railtie.railtie_name) + + if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first) + railties[railtie.railtie_name] = path + end + end + + on_skip = Proc.new do |name, migration| + $stderr.puts "WARNING: Migration #{migration.basename} from #{name} has been skipped. Migration with the same name already exists." + end + + on_copy = Proc.new do |name, migration, old_path| + puts "Copied migration #{migration.basename} from #{name}" + end + + ActiveRecord::Migration.copy( ActiveRecord::Migrator.migrations_path, railties, + :on_skip => on_skip, :on_copy => on_copy) + end + end end task 'test:prepare' => 'db:test:prepare' diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb index 9b62f88fd7..7bd65158b4 100644 --- a/railties/test/railties/shared_tests.rb +++ b/railties/test/railties/shared_tests.rb @@ -21,6 +21,11 @@ module RailtiesTest end RUBY + @plugin.write "db/migrate/3_create_sessions.rb", <<-RUBY + class CreateSessions < ActiveRecord::Migration + end + RUBY + app_file "db/migrate/1_create_sessions.rb", <<-RUBY class CreateSessions < ActiveRecord::Migration end @@ -38,24 +43,26 @@ module RailtiesTest add_to_config "ActiveRecord::Base.timestamped_migrations = false" Dir.chdir(app_path) do - output = `rake railties:copy_migrations FROM=bukkits` + output = `rake railties:install:migrations FROM=bukkits 2>&1` - assert File.exists?("#{app_path}/db/migrate/2_create_users.bukkits.rb") - assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.bukkits.rb") - assert_match /2_create_users/, output - assert_match /3_add_last_name_to_users/, output + assert File.exists?("#{app_path}/db/migrate/2_create_users.rb") + assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.rb") + assert_match /Copied migration 2_create_users.rb from bukkits/, output + assert_match /Copied migration 3_add_last_name_to_users.rb from bukkits/, output + assert_match /WARNING: Migration 3_create_sessions.rb from bukkits has been skipped/, output assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length - output = `rake railties:copy_migrations` + output = `rake railties:install:migrations 2>&1` - assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.acts_as_yaffle.rb") - assert_match /4_create_yaffles/, output + assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.rb") + assert_match /WARNING: Migration 3_create_sessions.rb from bukkits has been skipped/, output + assert_match /Copied migration 4_create_yaffles.rb from acts_as_yaffle/, output + assert_no_match /2_create_users/, output migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length - output = `rake railties:copy_migrations` + output = `rake railties:install:migrations 2>&1` assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length - assert_match /No migrations were copied/, output end end -- cgit v1.2.3 From b417cfbf01a17be7216d09e447f37bf1c19e4cb2 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 9 Oct 2010 20:11:36 +0200 Subject: Load rake tasks defined in superclasses in context of railties --- railties/lib/rails/railtie.rb | 7 +++++++ railties/test/railties/railtie_test.rb | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index 2b68a3c453..c76bc83377 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -191,6 +191,13 @@ module Rails def load_tasks self.class.rake_tasks.each(&:call) + + # load also tasks from all superclasses + klass = self.class.superclass + while klass.respond_to?(:rake_tasks) + klass.rake_tasks.each { |t| self.instance_exec(&t) } + klass = klass.superclass + end end def load_generators diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb index 406d5d764f..6d194eecba 100644 --- a/railties/test/railties/railtie_test.rb +++ b/railties/test/railties/railtie_test.rb @@ -103,6 +103,30 @@ module RailtiesTest assert $ran_block end + test "rake_tasks block defined in superclass of railtie is also executed" do + $ran_block = [] + + class Rails::Railtie + rake_tasks do + $ran_block << railtie_name + end + end + + class MyTie < Rails::Railtie + railtie_name "my_tie" + end + + require "#{app_path}/config/environment" + + assert_equal [], $ran_block + require 'rake' + require 'rake/testtask' + require 'rake/rdoctask' + + AppTemplate::Application.load_tasks + assert $ran_block.include?("my_tie") + end + test "generators block is executed when MyApp.load_generators is called" do $ran_block = false -- cgit v1.2.3 From a9bf91ea5640ab9ed9d6d7ba9da780ea1dfbd6e3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 9 Oct 2010 20:15:45 +0200 Subject: Add 'foo:install:migrations' task to copy migrations from foo engine --- railties/lib/rails/engine.rb | 14 ++++++++++++++ railties/test/railties/shared_tests.rb | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 909840da04..4acebb4769 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -522,6 +522,20 @@ module Rails # consistently executed after all the initializers above across all engines. end + rake_tasks do + next if self.is_a?(Rails::Application) + + namespace railtie_name do + namespace :install do + desc "Copy migrations from #{railtie_name} to application" + task :migrations do + ENV["FROM"] = railtie_name + Rake::Task["railties:install:migrations"].invoke + end + end + end + end + protected def routes? defined?(@routes) diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb index 7bd65158b4..b1d7580dff 100644 --- a/railties/test/railties/shared_tests.rb +++ b/railties/test/railties/shared_tests.rb @@ -43,7 +43,7 @@ module RailtiesTest add_to_config "ActiveRecord::Base.timestamped_migrations = false" Dir.chdir(app_path) do - output = `rake railties:install:migrations FROM=bukkits 2>&1` + output = `rake bukkits:install:migrations 2>&1` assert File.exists?("#{app_path}/db/migrate/2_create_users.rb") assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.rb") -- cgit v1.2.3 From 64c7f7e39244129e9330afed82da8a7ffeb948b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 9 Oct 2010 23:56:08 +0200 Subject: Add more docs and tests to templates. --- actionpack/lib/action_view/template.rb | 95 ++++++++++++++++++------------- actionpack/test/template/template_test.rb | 12 ++++ 2 files changed, 66 insertions(+), 41 deletions(-) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 1268b2f426..04ff752e64 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -125,34 +125,41 @@ module ActionView @compiled = false end + # Render a template. If the template was not compiled yet, it is done + # exactly before rendering. + # + # This method is instrumented as "!render_template.action_view". Notice that + # we use a bang in this instrumentation because you don't want to + # consume this in production. This is only slow if it's being listened to. def render(view, locals, &block) - # Notice that we use a bang in this instrumentation because you don't want to - # consume this in production. This is only slow if it's being listened to. ActiveSupport::Notifications.instrument("!render_template.action_view", :virtual_path => @virtual_path) do compile!(view) view.send(method_name, locals, &block) end rescue Exception => e - if e.is_a?(Template::Error) - e.sub_template_of(self) - raise e - else - raise Template::Error.new(refresh(view) || self, view.respond_to?(:assigns) ? view.assigns : {}, e) - end + handle_render_error(view, e) end def mime_type @mime_type ||= Mime::Type.lookup_by_extension(@formats.first.to_s) if @formats.first end - # TODO Remove me - def variable_name - @variable_name ||= @virtual_path[%r'_?(\w+)(\.\w+)*$', 1].to_sym - end - - # TODO Remove me - def counter_name - @counter_name ||= "#{variable_name}_counter".to_sym + # Receives a view object and return a template similar to self by using @virtual_path. + # + # This method is useful if you have a template object but it does not contain its source + # anymore since it was already compiled. In such cases, all you need to do is to call + # refresh passing in the view object. + # + # Notice this method raises an error if the template to be refreshed does not have a + # virtual path set (true just for inline templates). + def refresh(view) + raise "A template need to have a virtual path in order to be refreshed" unless @virtual_path + pieces = @virtual_path.split("/") + name = pieces.pop + partial = name.sub!(/^_/, "") + view.lookup_context.disable_cache do + view.find_template(name, pieces.join, partial || false, @locals) + end end def inspect @@ -164,24 +171,26 @@ module ActionView end end - def compile!(view) - return if @compiled + protected - if view.is_a?(ActionView::CompiledTemplates) - mod = ActionView::CompiledTemplates - else - mod = view.singleton_class - end + # Compile a template. This method ensures a template is compiled + # just once and removes the source after it is compiled. + def compile!(view) #:nodoc: + return if @compiled - compile(view, mod) + if view.is_a?(ActionView::CompiledTemplates) + mod = ActionView::CompiledTemplates + else + mod = view.singleton_class + end - # Just discard the source if we have a virtual path. This - # means we can get the template back. - @source = nil if @virtual_path - @compiled = true - end + compile(view, mod) - protected + # Just discard the source if we have a virtual path. This + # means we can get the template back. + @source = nil if @virtual_path + @compiled = true + end # Among other things, this method is responsible for properly setting # the encoding of the source. Until this point, we assume that the @@ -203,9 +212,8 @@ module ActionView # encode the source into Encoding.default_internal. In general, # this means that templates will be UTF-8 inside of Rails, # regardless of the original source encoding. - def compile(view, mod) + def compile(view, mod) #:nodoc: method_name = self.method_name - locals_code = @locals.map { |key| "#{key} = local_assigns[:#{key}];" }.join if source.encoding_aware? # Look for # encoding: *. If we find one, we'll encode the @@ -281,21 +289,26 @@ module ActionView end end - def refresh(view) - return unless @virtual_path - pieces = @virtual_path.split("/") - name = pieces.pop - partial = name.sub!(/^_/, "") - view.lookup_context.disable_cache do - view.find_template(name, pieces.join, partial || false, @locals) + def handle_render_error(view, e) #:nodoc: + if e.is_a?(Template::Error) + e.sub_template_of(self) + raise e + else + assigns = view.respond_to?(:assigns) ? view.assigns : {} + template = @virtual_path ? refresh(view) : self + raise Template::Error.new(template, assigns, e) end end - def method_name + def locals_code #:nodoc: + @locals.map { |key| "#{key} = local_assigns[:#{key}];" }.join + end + + def method_name #:nodoc: @method_name ||= "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}".gsub('-', "_") end - def identifier_method_name + def identifier_method_name #:nodoc: inspect.gsub(/[^a-z_]/, '_') end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 27b42006e3..00bfbbccd6 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -49,6 +49,18 @@ class TestERBTemplate < ActiveSupport::TestCase assert_equal "Hello", render end + def test_template_loses_its_source_after_rendering + @template = new_template + render + assert_nil @template.source + end + + def test_template_does_not_lose_its_source_after_rendering_if_it_does_not_have_a_virtual_path + @template = new_template("Hello", :virtual_path => nil) + render + assert_equal "Hello", @template.source + end + def test_locals @template = new_template("<%= my_local %>") @template.locals = [:my_local] -- cgit v1.2.3 From c7408a0e40545558872efb4129fe4bf097c9ce2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 01:14:50 +0200 Subject: Deprecate old template handler API. Remove old handlers. --- actionpack/lib/action_view/template/handler.rb | 10 ++++++++- actionpack/lib/action_view/template/handlers.rb | 10 +++------ .../lib/action_view/template/handlers/builder.rb | 8 +++---- .../lib/action_view/template/handlers/erb.rb | 25 +++++++++++++--------- .../lib/action_view/template/handlers/rjs.rb | 12 ++++------- actionpack/test/controller/content_type_test.rb | 24 ++++++++++----------- actionpack/test/controller/layout_test.rb | 18 ++++++++-------- .../test/fixtures/layout_tests/alt/hello.erb | 1 + .../test/fixtures/layout_tests/alt/hello.rhtml | 1 - .../test/fixtures/layout_tests/alt/layouts/alt.erb | 0 .../fixtures/layout_tests/alt/layouts/alt.rhtml | 0 .../layouts/controller_name_space/nested.erb | 1 + .../layouts/controller_name_space/nested.rhtml | 1 - .../test/fixtures/layout_tests/layouts/item.erb | 1 + .../test/fixtures/layout_tests/layouts/item.rhtml | 1 - .../fixtures/layout_tests/layouts/layout_test.erb | 1 + .../layout_tests/layouts/layout_test.rhtml | 1 - .../test/fixtures/layout_tests/views/goodbye.erb | 1 + .../test/fixtures/layout_tests/views/goodbye.rhtml | 1 - .../test/fixtures/layout_tests/views/hello.erb | 1 + .../test/fixtures/layout_tests/views/hello.rhtml | 1 - .../render_default_for_builder.builder | 1 + .../old_content_type/render_default_for_erb.erb | 1 + .../render_default_for_rhtml.rhtml | 1 - .../old_content_type/render_default_for_rxml.rxml | 1 - actionpack/test/template/template_test.rb | 4 ++-- 26 files changed, 66 insertions(+), 61 deletions(-) create mode 100644 actionpack/test/fixtures/layout_tests/alt/hello.erb delete mode 100644 actionpack/test/fixtures/layout_tests/alt/hello.rhtml create mode 100644 actionpack/test/fixtures/layout_tests/alt/layouts/alt.erb delete mode 100644 actionpack/test/fixtures/layout_tests/alt/layouts/alt.rhtml create mode 100644 actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.erb delete mode 100644 actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml create mode 100644 actionpack/test/fixtures/layout_tests/layouts/item.erb delete mode 100644 actionpack/test/fixtures/layout_tests/layouts/item.rhtml create mode 100644 actionpack/test/fixtures/layout_tests/layouts/layout_test.erb delete mode 100644 actionpack/test/fixtures/layout_tests/layouts/layout_test.rhtml create mode 100644 actionpack/test/fixtures/layout_tests/views/goodbye.erb delete mode 100644 actionpack/test/fixtures/layout_tests/views/goodbye.rhtml create mode 100644 actionpack/test/fixtures/layout_tests/views/hello.erb delete mode 100644 actionpack/test/fixtures/layout_tests/views/hello.rhtml create mode 100644 actionpack/test/fixtures/old_content_type/render_default_for_builder.builder create mode 100644 actionpack/test/fixtures/old_content_type/render_default_for_erb.erb delete mode 100644 actionpack/test/fixtures/old_content_type/render_default_for_rhtml.rhtml delete mode 100644 actionpack/test/fixtures/old_content_type/render_default_for_rxml.rxml diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb index c6a1bc6235..0a9d299807 100644 --- a/actionpack/lib/action_view/template/handler.rb +++ b/actionpack/lib/action_view/template/handler.rb @@ -1,4 +1,4 @@ -require "action_dispatch/http/mime_type" +require 'action_dispatch/http/mime_type' require 'active_support/core_ext/class/attribute' # Legacy TemplateHandler stub @@ -7,6 +7,8 @@ module ActionView module Handlers #:nodoc: module Compilable def self.included(base) + ActiveSupport::Deprecation.warn "Including Compilable in your template handler is deprecated. " << + "All the API your template handler needs to implement is to respond to #call." base.extend(ClassMethods) end @@ -26,6 +28,12 @@ module ActionView class_attribute :default_format self.default_format = Mime::HTML + def self.inherited(base) + ActiveSupport::Deprecation.warn "Inheriting from ActionView::Template::Handler is deprecated. " << + "All the API your template handler needs to implement is to respond to #call." + super + end + def self.call(template) raise "Need to implement #{self.class.name}#call(template)" end diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index ed397699b0..60347e2a95 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -7,13 +7,9 @@ module ActionView #:nodoc: autoload :Builder, 'action_view/template/handlers/builder' def self.extended(base) - base.register_default_template_handler :erb, ERB - base.register_template_handler :rjs, RJS - base.register_template_handler :builder, Builder - - # TODO: Depreciate old template extensions - base.register_template_handler :rhtml, ERB - base.register_template_handler :rxml, Builder + base.register_default_template_handler :erb, ERB.new + base.register_template_handler :rjs, RJS.new + base.register_template_handler :builder, Builder.new end @@template_handlers = {} diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb index a93cfca8aa..2c52cfd90e 100644 --- a/actionpack/lib/action_view/template/handlers/builder.rb +++ b/actionpack/lib/action_view/template/handlers/builder.rb @@ -1,11 +1,11 @@ module ActionView module Template::Handlers - class Builder < Template::Handler - include Compilable - + class Builder + # Default format used by Builder. + class_attribute :default_format self.default_format = Mime::XML - def compile(template) + def call(template) require 'builder' "xml = ::Builder::XmlMarkup.new(:indent => 2);" + "self.output_buffer = xml.target!;" + diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 24e1e44c1d..b827610456 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/string/output_safety' -require "action_view/template" +require 'action_view/template' +require 'action_view/template/handler' require 'erubis' module ActionView @@ -47,28 +48,31 @@ module ActionView end end - class ERB < Handler - include Compilable - - ## - # :singleton-method: + class ERB # Specify trim mode for the ERB compiler. Defaults to '-'. # See ERb documentation for suitable values. - cattr_accessor :erb_trim_mode + class_attribute :erb_trim_mode self.erb_trim_mode = '-' + # Default format used by ERB. + class_attribute :default_format self.default_format = Mime::HTML - cattr_accessor :erb_implementation + # Default implemenation used. + class_attribute :erb_implementation self.erb_implementation = Erubis ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*") - def self.handles_encoding? + def self.call(template) + new.call(template) + end + + def handles_encoding? true end - def compile(template) + def call(template) if template.source.encoding_aware? # First, convert to BINARY, so in case the encoding is # wrong, we can still find an encoding tag @@ -94,6 +98,7 @@ module ActionView end private + def valid_encoding(string, encoding) # If a magic encoding comment was found, tag the # String with this encoding. This is for a case diff --git a/actionpack/lib/action_view/template/handlers/rjs.rb b/actionpack/lib/action_view/template/handlers/rjs.rb index 128be5077c..9d71059134 100644 --- a/actionpack/lib/action_view/template/handlers/rjs.rb +++ b/actionpack/lib/action_view/template/handlers/rjs.rb @@ -1,17 +1,13 @@ module ActionView module Template::Handlers - class RJS < Template::Handler - include Compilable - + class RJS + # Default format used by RJS. + class_attribute :default_format self.default_format = Mime::JS - def compile(template) + def call(template) "update_page do |page|;#{template.source}\nend" end - - def default_format - Mime::JS - end end end end diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index 967107853b..9500c25a32 100644 --- a/actionpack/test/controller/content_type_test.rb +++ b/actionpack/test/controller/content_type_test.rb @@ -29,18 +29,18 @@ class OldContentTypeController < ActionController::Base render :text => "hello world!" end - def render_default_for_rhtml + def render_default_for_erb end - def render_default_for_rxml + def render_default_for_builder end def render_default_for_rjs end - def render_change_for_rxml + def render_change_for_builder response.content_type = Mime::HTML - render :action => "render_default_for_rxml" + render :action => "render_default_for_builder" end def render_default_content_types_for_respond_to @@ -108,23 +108,23 @@ class ContentTypeTest < ActionController::TestCase assert_equal "utf-8", @response.charset, @response.headers.inspect end - def test_nil_default_for_rhtml + def test_nil_default_for_erb OldContentTypeController.default_charset = nil - get :render_default_for_rhtml + get :render_default_for_erb assert_equal Mime::HTML, @response.content_type assert_nil @response.charset, @response.headers.inspect ensure OldContentTypeController.default_charset = "utf-8" end - def test_default_for_rhtml - get :render_default_for_rhtml + def test_default_for_erb + get :render_default_for_erb assert_equal Mime::HTML, @response.content_type assert_equal "utf-8", @response.charset end - def test_default_for_rxml - get :render_default_for_rxml + def test_default_for_builder + get :render_default_for_builder assert_equal Mime::XML, @response.content_type assert_equal "utf-8", @response.charset end @@ -135,8 +135,8 @@ class ContentTypeTest < ActionController::TestCase assert_equal "utf-8", @response.charset end - def test_change_for_rxml - get :render_change_for_rxml + def test_change_for_builder + get :render_change_for_builder assert_equal Mime::HTML, @response.content_type assert_equal "utf-8", @response.charset end diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index 32a0f40614..cafe2b9320 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -46,13 +46,13 @@ class LayoutAutoDiscoveryTest < ActionController::TestCase def test_application_layout_is_default_when_no_controller_match @controller = ProductController.new get :hello - assert_equal 'layout_test.rhtml hello.rhtml', @response.body + assert_equal 'layout_test.erb hello.erb', @response.body end def test_controller_name_layout_name_match @controller = ItemController.new get :hello - assert_equal 'item.rhtml hello.rhtml', @response.body + assert_equal 'item.erb hello.erb', @response.body end def test_third_party_template_library_auto_discovers_layout @@ -65,13 +65,13 @@ class LayoutAutoDiscoveryTest < ActionController::TestCase def test_namespaced_controllers_auto_detect_layouts1 @controller = ControllerNameSpace::NestedController.new get :hello - assert_equal 'controller_name_space/nested.rhtml hello.rhtml', @response.body + assert_equal 'controller_name_space/nested.erb hello.erb', @response.body end def test_namespaced_controllers_auto_detect_layouts2 @controller = MultipleExtensions.new get :hello - assert_equal 'multiple_extensions.html.erb hello.rhtml', @response.body.strip + assert_equal 'multiple_extensions.html.erb hello.erb', @response.body.strip end end @@ -79,7 +79,7 @@ class DefaultLayoutController < LayoutTest end class AbsolutePathLayoutController < LayoutTest - layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/layouts/layout_test.rhtml') + layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/layouts/layout_test.erb') end class HasOwnLayoutController < LayoutTest @@ -137,7 +137,7 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_layout_only_exception_when_excepted @controller = OnlyLayoutController.new get :goodbye - assert !@response.body.include?("item.rhtml"), "#{@response.body.inspect} included 'item.rhtml'" + assert !@response.body.include?("item.erb"), "#{@response.body.inspect} included 'item.erb'" end def test_layout_except_exception_when_included @@ -149,7 +149,7 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_layout_except_exception_when_excepted @controller = ExceptLayoutController.new get :goodbye - assert !@response.body.include?("item.rhtml"), "#{@response.body.inspect} included 'item.rhtml'" + assert !@response.body.include?("item.erb"), "#{@response.body.inspect} included 'item.erb'" end def test_layout_set_when_using_render @@ -173,7 +173,7 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_absolute_pathed_layout @controller = AbsolutePathLayoutController.new get :hello - assert_equal "layout_test.rhtml hello.rhtml", @response.body.strip + assert_equal "layout_test.erb hello.erb", @response.body.strip end end @@ -184,7 +184,7 @@ class RenderWithTemplateOptionController < LayoutTest end class SetsNonExistentLayoutFile < LayoutTest - layout "nofile.rhtml" + layout "nofile.erb" end class LayoutExceptionRaised < ActionController::TestCase diff --git a/actionpack/test/fixtures/layout_tests/alt/hello.erb b/actionpack/test/fixtures/layout_tests/alt/hello.erb new file mode 100644 index 0000000000..1055c36659 --- /dev/null +++ b/actionpack/test/fixtures/layout_tests/alt/hello.erb @@ -0,0 +1 @@ +alt/hello.erb diff --git a/actionpack/test/fixtures/layout_tests/alt/hello.rhtml b/actionpack/test/fixtures/layout_tests/alt/hello.rhtml deleted file mode 100644 index fcda6cf97a..0000000000 --- a/actionpack/test/fixtures/layout_tests/alt/hello.rhtml +++ /dev/null @@ -1 +0,0 @@ -alt/hello.rhtml diff --git a/actionpack/test/fixtures/layout_tests/alt/layouts/alt.erb b/actionpack/test/fixtures/layout_tests/alt/layouts/alt.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/actionpack/test/fixtures/layout_tests/alt/layouts/alt.rhtml b/actionpack/test/fixtures/layout_tests/alt/layouts/alt.rhtml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.erb b/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.erb new file mode 100644 index 0000000000..121bc079a1 --- /dev/null +++ b/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.erb @@ -0,0 +1 @@ +controller_name_space/nested.erb <%= yield %> \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml b/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml deleted file mode 100644 index 5f86a7de4d..0000000000 --- a/actionpack/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +++ /dev/null @@ -1 +0,0 @@ -controller_name_space/nested.rhtml <%= yield %> \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/layouts/item.erb b/actionpack/test/fixtures/layout_tests/layouts/item.erb new file mode 100644 index 0000000000..60f04d77d5 --- /dev/null +++ b/actionpack/test/fixtures/layout_tests/layouts/item.erb @@ -0,0 +1 @@ +item.erb <%= yield %> \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/layouts/item.rhtml b/actionpack/test/fixtures/layout_tests/layouts/item.rhtml deleted file mode 100644 index 1bc7cbda06..0000000000 --- a/actionpack/test/fixtures/layout_tests/layouts/item.rhtml +++ /dev/null @@ -1 +0,0 @@ -item.rhtml <%= yield %> \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/layouts/layout_test.erb b/actionpack/test/fixtures/layout_tests/layouts/layout_test.erb new file mode 100644 index 0000000000..b74ac0840d --- /dev/null +++ b/actionpack/test/fixtures/layout_tests/layouts/layout_test.erb @@ -0,0 +1 @@ +layout_test.erb <%= yield %> \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/layouts/layout_test.rhtml b/actionpack/test/fixtures/layout_tests/layouts/layout_test.rhtml deleted file mode 100644 index c0f2642b40..0000000000 --- a/actionpack/test/fixtures/layout_tests/layouts/layout_test.rhtml +++ /dev/null @@ -1 +0,0 @@ -layout_test.rhtml <%= yield %> \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/views/goodbye.erb b/actionpack/test/fixtures/layout_tests/views/goodbye.erb new file mode 100644 index 0000000000..4ee911188e --- /dev/null +++ b/actionpack/test/fixtures/layout_tests/views/goodbye.erb @@ -0,0 +1 @@ +hello.erb \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/views/goodbye.rhtml b/actionpack/test/fixtures/layout_tests/views/goodbye.rhtml deleted file mode 100644 index bbccf0913e..0000000000 --- a/actionpack/test/fixtures/layout_tests/views/goodbye.rhtml +++ /dev/null @@ -1 +0,0 @@ -hello.rhtml \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/views/hello.erb b/actionpack/test/fixtures/layout_tests/views/hello.erb new file mode 100644 index 0000000000..4ee911188e --- /dev/null +++ b/actionpack/test/fixtures/layout_tests/views/hello.erb @@ -0,0 +1 @@ +hello.erb \ No newline at end of file diff --git a/actionpack/test/fixtures/layout_tests/views/hello.rhtml b/actionpack/test/fixtures/layout_tests/views/hello.rhtml deleted file mode 100644 index bbccf0913e..0000000000 --- a/actionpack/test/fixtures/layout_tests/views/hello.rhtml +++ /dev/null @@ -1 +0,0 @@ -hello.rhtml \ No newline at end of file diff --git a/actionpack/test/fixtures/old_content_type/render_default_for_builder.builder b/actionpack/test/fixtures/old_content_type/render_default_for_builder.builder new file mode 100644 index 0000000000..598d62e2fc --- /dev/null +++ b/actionpack/test/fixtures/old_content_type/render_default_for_builder.builder @@ -0,0 +1 @@ +xml.p "Hello world!" \ No newline at end of file diff --git a/actionpack/test/fixtures/old_content_type/render_default_for_erb.erb b/actionpack/test/fixtures/old_content_type/render_default_for_erb.erb new file mode 100644 index 0000000000..c7926d48bb --- /dev/null +++ b/actionpack/test/fixtures/old_content_type/render_default_for_erb.erb @@ -0,0 +1 @@ +<%= 'hello world!' %> \ No newline at end of file diff --git a/actionpack/test/fixtures/old_content_type/render_default_for_rhtml.rhtml b/actionpack/test/fixtures/old_content_type/render_default_for_rhtml.rhtml deleted file mode 100644 index c7926d48bb..0000000000 --- a/actionpack/test/fixtures/old_content_type/render_default_for_rhtml.rhtml +++ /dev/null @@ -1 +0,0 @@ -<%= 'hello world!' %> \ No newline at end of file diff --git a/actionpack/test/fixtures/old_content_type/render_default_for_rxml.rxml b/actionpack/test/fixtures/old_content_type/render_default_for_rxml.rxml deleted file mode 100644 index 598d62e2fc..0000000000 --- a/actionpack/test/fixtures/old_content_type/render_default_for_rxml.rxml +++ /dev/null @@ -1 +0,0 @@ -xml.p "Hello world!" \ No newline at end of file diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 00bfbbccd6..eb2d4aab36 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -1,7 +1,7 @@ require "abstract_unit" class TestERBTemplate < ActiveSupport::TestCase - ERBHandler = ActionView::Template::Handlers::ERB + ERBHandler = ActionView::Template::Handlers::ERB.new class Context def initialize @@ -121,7 +121,7 @@ class TestERBTemplate < ActiveSupport::TestCase def test_encoding_can_be_specified_with_magic_comment_in_erb with_external_encoding Encoding::UTF_8 do - @template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat") + @template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat", :virtual_path => nil) result = render assert_equal Encoding::UTF_8, render.encoding assert_equal "hello \u{fc}mlat", render -- cgit v1.2.3 From 38d78f99d52801d8392a7229b40edae74cc3d142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 09:24:17 +0200 Subject: Resolvers now consider timestamps. Before this patch, every request in development caused the template to be compiled, regardless if it was updated in the filesystem or not. This patch now checks the timestamp and only compiles it again if any change was done. While this probably won't show any difference for current setups, but it will be useful for asset template handlers (like SASS), as compiling their templates is slower than ERb, Haml, etc. --- actionpack/lib/action_view/template.rb | 25 ++++----- actionpack/lib/action_view/template/resolver.rb | 67 +++++++++++++++++-------- actionpack/lib/action_view/testing/resolvers.rb | 5 +- actionpack/test/template/lookup_context_test.rb | 45 +++++++++++++++++ 4 files changed, 107 insertions(+), 35 deletions(-) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 04ff752e64..3cc9bb2710 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -98,10 +98,9 @@ module ActionView extend Template::Handlers - attr_accessor :locals + attr_accessor :locals, :formats, :virtual_path - attr_reader :source, :identifier, :handler, :virtual_path, :formats, - :original_encoding + attr_reader :source, :identifier, :handler, :original_encoding, :updated_at # This finalizer is needed (and exactly with a proc inside another proc) # otherwise templates leak in development. @@ -114,15 +113,17 @@ module ActionView end def initialize(source, identifier, handler, details) - @source = source - @identifier = identifier - @handler = handler - @original_encoding = nil - @method_names = {} - @locals = details[:locals] || [] - @formats = Array.wrap(details[:format] || :html).map(&:to_sym) - @virtual_path = details[:virtual_path] - @compiled = false + format = details[:format] || (handler.default_format if handler.respond_to?(:default_format)) + + @source = source + @identifier = identifier + @handler = handler + @compiled = false + @original_encoding = nil + @locals = details[:locals] || [] + @virtual_path = details[:virtual_path] + @updated_at = details[:updated_at] || Time.now + @formats = Array.wrap(format).map(&:to_sym) end # Render a template. If the template was not compiled yet, it is done diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 9ec39b16f0..5c6877a923 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -16,7 +16,7 @@ module ActionView # Normalizes the arguments and passes it on to find_template. def find_all(name, prefix=nil, partial=false, details={}, locals=[], key=nil) - cached(key, prefix, name, partial, locals) do + cached(key, [name, prefix, partial], details, locals) do find_templates(name, prefix, partial, details) end end @@ -35,37 +35,55 @@ module ActionView end # Helpers that builds a path. Useful for building virtual paths. - def build_path(name, prefix, partial, details) + def build_path(name, prefix, partial) path = "" path << "#{prefix}/" unless prefix.empty? path << (partial ? "_#{name}" : name) path end - # Get the handler and format from the given parameters. - def retrieve_handler_and_format(handler, format, default_formats=nil) - handler = Template.handler_class_for_extension(handler) - format = format && Mime[format] - format ||= handler.default_format if handler.respond_to?(:default_format) - format ||= default_formats - [handler, format] - end - - def cached(key, prefix, name, partial, locals) + # Hnadles templates caching. If a key is given and caching is on + # always check the cache before hitting the resolver. Otherwise, + # it always hits the resolver but check if the resolver is fresher + # before returning it. + def cached(key, path_info, details, locals) #:nodoc: + name, prefix, partial = path_info locals = sort_locals(locals) - unless key && caching? - yield.each { |t| t.locals = locals } + + if key && caching? + @cached[key][name][prefix][partial][locals] ||= decorate(yield, path_info, details, locals) else - @cached[key][prefix][name][partial][locals] ||= yield.each { |t| t.locals = locals } + fresh = decorate(yield, path_info, details, locals) + return fresh unless key + + scope = @cached[key][name][prefix][partial] + cache = scope[locals] + mtime = cache && cache.map(&:updated_at).max + + if !mtime || fresh.empty? || fresh.any? { |t| t.updated_at > mtime } + scope[locals] = fresh + else + cache + end + end + end + + # Ensures all the resolver information is set in the template. + def decorate(templates, path_info, details, locals) #:nodoc: + cached = nil + templates.each do |t| + t.locals = locals + t.formats = details[:formats] || [:html] if t.formats.empty? + t.virtual_path ||= (cached ||= build_path(*path_info)) end end - if :locale.respond_to?("<=>") - def sort_locals(locals) + if :symbol.respond_to?("<=>") + def sort_locals(locals) #:nodoc: locals.sort.freeze end else - def sort_locals(locals) + def sort_locals(locals) #:nodoc: locals = locals.map{ |l| l.to_s } locals.sort! locals.freeze @@ -79,7 +97,7 @@ module ActionView private def find_templates(name, prefix, partial, details) - path = build_path(name, prefix, partial, details) + path = build_path(name, prefix, partial) query(path, EXTENSION_ORDER.map { |ext| details[ext] }, details[:formats]) end @@ -96,17 +114,24 @@ module ActionView contents = File.open(p, "rb") {|io| io.read } Template.new(contents, File.expand_path(p), handler, - :virtual_path => path, :format => format) + :virtual_path => path, :format => format, :updated_at => mtime(p)) end end + # Returns the file mtime from the filesystem. + def mtime(p) + File.stat(p).mtime + end + # Extract handler and formats from path. If a format cannot be a found neither # from the path, or the handler, we should return the array of formats given # to the resolver. def extract_handler_and_format(path, default_formats) pieces = File.basename(path).split(".") pieces.shift - retrieve_handler_and_format(pieces.pop, pieces.pop, default_formats) + handler = Template.handler_class_for_extension(pieces.pop) + format = pieces.last && Mime[pieces.last] + [handler, format] end end diff --git a/actionpack/lib/action_view/testing/resolvers.rb b/actionpack/lib/action_view/testing/resolvers.rb index ec0db48379..55583096e0 100644 --- a/actionpack/lib/action_view/testing/resolvers.rb +++ b/actionpack/lib/action_view/testing/resolvers.rb @@ -23,11 +23,12 @@ module ActionView #:nodoc: query = /^(#{Regexp.escape(path)})#{query}$/ templates = [] - @hash.each do |_path, source| + @hash.each do |_path, array| + source, updated_at = array next unless _path =~ query handler, format = extract_handler_and_format(_path, formats) templates << Template.new(source, _path, handler, - :virtual_path => $1, :format => format) + :virtual_path => $1, :format => format, :updated_at => updated_at) end templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size } diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index 55d581e512..23dfc1ba75 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -184,4 +184,49 @@ class LookupContextTest < ActiveSupport::TestCase test "can have cache disabled on initialization" do assert !ActionView::LookupContext.new(FIXTURE_LOAD_PATH, :cache => false).cache end +end + +class LookupContextWithFalseCaching < ActiveSupport::TestCase + def setup + @resolver = ActionView::FixtureResolver.new("test/_foo.erb" => ["Foo", Time.utc(2000)]) + @resolver.stubs(:caching?).returns(false) + @lookup_context = ActionView::LookupContext.new(@resolver, {}) + end + + test "templates are always found in the resolver but timestamp is checked before being compiled" do + template = @lookup_context.find("foo", "test", true) + assert_equal "Foo", template.source + + # Now we are going to change the template, but it won't change the returned template + # since the timestamp is the same. + @resolver.hash["test/_foo.erb"][0] = "Bar" + template = @lookup_context.find("foo", "test", true) + assert_equal "Foo", template.source + + # Now update the timestamp. + @resolver.hash["test/_foo.erb"][1] = Time.now.utc + template = @lookup_context.find("foo", "test", true) + assert_equal "Bar", template.source + end + + test "if no template was found in the second lookup, give it higher preference" do + template = @lookup_context.find("foo", "test", true) + assert_equal "Foo", template.source + + @resolver.hash.clear + assert_raise ActionView::MissingTemplate do + @lookup_context.find("foo", "test", true) + end + end + + test "if no template was cached in the first lookup, do not use the cache in the second" do + @resolver.hash.clear + assert_raise ActionView::MissingTemplate do + @lookup_context.find("foo", "test", true) + end + + @resolver.hash["test/_foo.erb"] = ["Foo", Time.utc(2000)] + template = @lookup_context.find("foo", "test", true) + assert_equal "Foo", template.source + end end \ No newline at end of file -- cgit v1.2.3 From 8cb2cfbf71092f95090335cbdde0340cc74db748 Mon Sep 17 00:00:00 2001 From: wycats Date: Sun, 10 Oct 2010 00:51:52 -0700 Subject: Fix a few bugs when trying to use Head standalone --- actionpack/lib/abstract_controller/base.rb | 1 + actionpack/lib/action_controller/metal.rb | 5 +++++ actionpack/lib/action_controller/metal/head.rb | 6 ++---- actionpack/test/controller/new_base/bare_metal_test.rb | 15 +++++++++++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index f9f6eb945e..f83eaded88 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -13,6 +13,7 @@ module AbstractController class Base attr_internal :response_body attr_internal :action_name + attr_internal :formats include ActiveSupport::Configurable extend ActiveSupport::DescendantsTracker diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index ace1aabe03..329798e84f 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -119,6 +119,11 @@ module ActionController headers["Location"] = url end + # basic url_for that can be overridden for more robust functionality + def url_for(string) + string + end + def status @_status end diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb index 2b4a3b9392..8abcad55a2 100644 --- a/actionpack/lib/action_controller/metal/head.rb +++ b/actionpack/lib/action_controller/metal/head.rb @@ -2,8 +2,6 @@ module ActionController module Head extend ActiveSupport::Concern - include ActionController::UrlFor - # Return a response that has no content (merely headers). The options # argument is interpreted to be a hash of header names and values. # This allows you to easily return a response that consists only of @@ -27,8 +25,8 @@ module ActionController self.status = status self.location = url_for(location) if location - self.content_type = Mime[formats.first] + self.content_type = Mime[formats.first] if formats self.response_body = " " end end -end \ No newline at end of file +end diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb index 8a06e8d2a0..44922cecff 100644 --- a/actionpack/test/controller/new_base/bare_metal_test.rb +++ b/actionpack/test/controller/new_base/bare_metal_test.rb @@ -24,4 +24,19 @@ module BareMetalTest assert_equal "Hello world", string end end + + class HeadController < ActionController::Metal + include ActionController::Head + + def index + head :not_found + end + end + + class HeadTest < ActiveSupport::TestCase + test "head works on its own" do + status, headers, body = HeadController.action(:index).call(Rack::MockRequest.env_for("/")) + assert_equal 404, status + end + end end -- cgit v1.2.3 From b3cadf338b948640e2203d677cc2b19fd2422ae8 Mon Sep 17 00:00:00 2001 From: wycats Date: Sun, 10 Oct 2010 00:52:43 -0700 Subject: Rendering doesn't need RackDelegation --- actionpack/lib/action_controller/metal/rendering.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 86bb810947..e524e546ad 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -2,7 +2,6 @@ module ActionController module Rendering extend ActiveSupport::Concern - include ActionController::RackDelegation include AbstractController::Rendering # Before processing, set the request formats in current controller formats. -- cgit v1.2.3 From ab2f2b22a6d0656f719c294d40e35d21c752ba8c Mon Sep 17 00:00:00 2001 From: David Calavera Date: Fri, 8 Oct 2010 18:16:40 +0530 Subject: prevent rake test to run the test suite three times when ENV['TEST'] is set [#3572 state:resolved] Signed-off-by: Xavier Noria --- actionpack/RUNNING_UNIT_TESTS | 13 ++++++++----- railties/lib/rails/test_unit/testing.rake | 7 ++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/actionpack/RUNNING_UNIT_TESTS b/actionpack/RUNNING_UNIT_TESTS index d6a1ccf871..1e3ba7abe7 100644 --- a/actionpack/RUNNING_UNIT_TESTS +++ b/actionpack/RUNNING_UNIT_TESTS @@ -8,15 +8,18 @@ Rake can be found at http://rake.rubyforge.org == Running by hand -If you only want to run a single test suite, or don't want to bother with Rake, -you can do so with something like: +To run a single test suite - ruby -Itest test/controller/base_tests.rb + rake test TEST=path/to/test.rb -== Dependency on ActiveRecord and database setup +which can be further narrowed down to one test: + + rake test TEST=path/to/test.rb TESTOPTS="--name=test_something" + +== Dependency on Active Record and database setup Test cases in the test/controller/active_record/ directory depend on having -activerecord and sqlite installed. If ActiveRecord is not in +activerecord and sqlite installed. If Active Record is not in actionpack/../activerecord directory, or the sqlite rubygem is not installed, these tests are skipped. diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index 713833f884..28dc40379b 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -73,7 +73,8 @@ end desc 'Runs test:units, test:functionals, test:integration together (also available: test:benchmark, test:profile, test:plugins)' task :test do - errors = %w(test:units test:functionals test:integration).collect do |task| + tests_to_run = ENV['TEST'] ? ["test:single"] : %w(test:units test:functionals test:integration) + errors = tests_to_run.collect do |task| begin Rake::Task[task].invoke nil @@ -123,6 +124,10 @@ namespace :test do end Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion and Git)" + Rake::TestTask.new(:single => "test:prepare") do |t| + t.libs << "test" + end + TestTaskWithoutDescription.new(:units => "test:prepare") do |t| t.libs << "test" t.pattern = 'test/unit/**/*_test.rb' -- cgit v1.2.3 From b88f4ca93bcaef9a6bfd21d95acc8f432a3c8e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 11:03:18 +0200 Subject: Clean up the house before moving in the new furniture. This commit moves all the template rendering logic that was hanging around AV::Base to renderer objects. --- actionpack/lib/action_view.rb | 8 +- actionpack/lib/action_view/base.rb | 9 +- .../lib/action_view/helpers/prototype_helper.rb | 2 +- actionpack/lib/action_view/render/layouts.rb | 83 ---------- actionpack/lib/action_view/render/partials.rb | 177 +-------------------- actionpack/lib/action_view/render/rendering.rb | 101 +++++++----- .../lib/action_view/renderer/abstract_renderer.rb | 36 +++++ .../lib/action_view/renderer/partial_renderer.rb | 167 +++++++++++++++++++ .../lib/action_view/renderer/template_renderer.rb | 66 ++++++++ actionpack/lib/action_view/template.rb | 5 +- 10 files changed, 348 insertions(+), 306 deletions(-) delete mode 100644 actionpack/lib/action_view/render/layouts.rb create mode 100644 actionpack/lib/action_view/renderer/abstract_renderer.rb create mode 100644 actionpack/lib/action_view/renderer/partial_renderer.rb create mode 100644 actionpack/lib/action_view/renderer/template_renderer.rb diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 5f9dc70766..ad96f6c66d 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -38,11 +38,17 @@ module ActionView autoload :Helpers autoload :Base autoload :LookupContext + autoload :Render autoload :PathSet, "action_view/paths" autoload :TestCase, "action_view/test_case" + autoload_under "renderer" do + autoload :AbstractRenderer + autoload :PartialRenderer + autoload :TemplateRenderer + end + autoload_under "render" do - autoload :Layouts autoload :Partials autoload :Rendering end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 0bef3e3a08..2a601c7cee 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -158,7 +158,7 @@ module ActionView #:nodoc: module Subclasses end - include Helpers, Rendering, Partials, Layouts, ::ERB::Util, Context + include Helpers, Rendering, Partials, ::ERB::Util, Context # Specify whether RJS responses should be wrapped in a try/catch block # that alert()s the caught exception (and then re-raises it). @@ -180,8 +180,7 @@ module ActionView #:nodoc: attr_accessor :base_path, :assigns, :template_extension, :lookup_context attr_internal :captures, :request, :controller, :template, :config - delegate :find_template, :template_exists?, :formats, :formats=, :locale, :locale=, - :view_paths, :view_paths=, :with_fallbacks, :update_details, :with_layout_format, :to => :lookup_context + delegate :formats, :formats=, :locale, :locale=, :view_paths, :view_paths=, :to => :lookup_context delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, :flash, :action_name, :controller_name, :to => :controller @@ -220,6 +219,10 @@ module ActionView #:nodoc: @lookup_context.formats = formats if formats end + def store_content_for(key, value) + @_content_for[key] = value + end + def controller_path @controller_path ||= controller && controller.controller_path end diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 300207dfac..41cd8d5171 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -546,7 +546,7 @@ module ActionView end def with_formats(*args) - @context ? @context.update_details(:formats => args) { yield } : yield + @context ? @context.lookup_context.update_details(:formats => args) { yield } : yield end def javascript_object_for(object) diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb deleted file mode 100644 index 08162f7fd5..0000000000 --- a/actionpack/lib/action_view/render/layouts.rb +++ /dev/null @@ -1,83 +0,0 @@ -module ActionView - # = Action View Layouts - module Layouts - # Returns the contents that are yielded to a layout, given a name or a block. - # - # You can think of a layout as a method that is called with a block. If the user calls - # yield :some_name, the block, by default, returns content_for(:some_name). - # If the user calls simply +yield+, the default block returns content_for(:layout). - # - # The user can override this default by passing a block to the layout: - # - # # The template - # <%= render :layout => "my_layout" do %> - # Content - # <% end %> - # - # # The layout - # - # <%= yield %> - # - # - # In this case, instead of the default block, which would return content_for(:layout), - # this method returns the block that was passed in to render :layout, and the response - # would be - # - # - # Content - # - # - # Finally, the block can take block arguments, which can be passed in by +yield+: - # - # # The template - # <%= render :layout => "my_layout" do |customer| %> - # Hello <%= customer.name %> - # <% end %> - # - # # The layout - # - # <%= yield Struct.new(:name).new("David") %> - # - # - # In this case, the layout would receive the block passed into render :layout, - # and the struct specified would be passed into the block as an argument. The result - # would be - # - # - # Hello David - # - # - def _layout_for(*args, &block) #:nodoc: - name = args.first - - if name.is_a?(Symbol) - @_content_for[name].html_safe - elsif block - capture(*args, &block) - else - @_content_for[:layout].html_safe - end - end - - # This is the method which actually finds the layout using details in the lookup - # context object. If no layout is found, it checks if at least a layout with - # the given name exists across all details before raising the error. - def find_layout(layout, keys) - begin - with_layout_format do - layout =~ /^\// ? - with_fallbacks { find_template(layout, nil, false, keys) } : find_template(layout, nil, false, keys) - end - rescue ActionView::MissingTemplate => e - update_details(:formats => nil) do - raise unless template_exists?(layout) - end - end - end - - # Contains the logic that actually renders the layout. - def _render_layout(layout, locals, &block) #:nodoc: - layout.render(self, locals){ |*name| _layout_for(*name, &block) } - end - end -end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 4e03d43358..844c3e9572 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -210,181 +210,12 @@ module ActionView # <%- end -%> # <% end %> module Partials - extend ActiveSupport::Concern - - class PartialRenderer - PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} } - - def initialize(view_context, options, block) - @view = view_context - @partial_names = PARTIAL_NAMES[@view.controller.class.name] - setup(options, block) - end - - def setup(options, block) - partial = options[:partial] - - @options = options - @locals = options[:locals] || {} - @block = block - - if String === partial - @object = options[:object] - @path = partial - @collection = collection - else - @object = partial - - if @collection = collection_from_object || collection - paths = @collection_data = @collection.map { |o| partial_path(o) } - @path = paths.uniq.size == 1 ? paths.first : nil - else - @path = partial_path - end - end - - if @path - @variable, @variable_counter = retrieve_variable(@path) - else - paths.map! { |path| retrieve_variable(path).unshift(path) } - end - end - - def retrieve_variable(path) - variable = @options[:as] || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym - variable_counter = :"#{variable}_counter" if @collection - [variable, variable_counter] - end - - def render - identifier = ((@template = find_partial) ? @template.identifier : @path) - - if @collection - ActiveSupport::Notifications.instrument("render_collection.action_view", - :identifier => identifier || "collection", :count => @collection.size) do - render_collection - end - else - if !@block && (layout = @options[:layout]) - layout = find_template(layout) - end - - content = ActiveSupport::Notifications.instrument("render_partial.action_view", - :identifier => identifier) do - render_partial - end - - content = @view._render_layout(layout, @locals){ content } if layout - content - end - end - - def render_collection - return nil if @collection.blank? - - if @options.key?(:spacer_template) - spacer = find_template(@options[:spacer_template]).render(@view, @locals) - end - - result = @template ? collection_with_template : collection_without_template - result.join(spacer).html_safe - end - - def collection_with_template - segments, locals, template = [], @locals, @template - as, counter = @variable, @variable_counter - - locals[counter] = -1 - - @collection.each do |object| - locals[counter] += 1 - locals[as] = object - segments << template.render(@view, locals) - end - - segments - end - - def collection_without_template - segments, locals, collection_data = [], @locals, @collection_data - index, template, cache = -1, nil, {} - keys = @locals.keys - - @collection.each_with_index do |object, i| - path, *data = collection_data[i] - template = (cache[path] ||= find_template(path, keys + data)) - locals[data[0]] = object - locals[data[1]] = (index += 1) - segments << template.render(@view, locals) - end - - @template = template - segments - end - - def render_partial - locals, view = @locals, @view - object, as = @object, @variable - - object ||= locals[as] - locals[as] = object - - @template.render(view, locals) do |*name| - view._layout_for(*name, &@block) - end - end - - private - - def collection - if @options.key?(:collection) - @options[:collection] || [] - end - end - - def collection_from_object - if @object.respond_to?(:to_ary) - @object - end - end - - def find_partial - if path = @path - locals = @locals.keys - locals << @variable - locals << @variable_counter if @collection - find_template(path, locals) - end - end - - def find_template(path=@path, locals=@locals.keys) - prefix = @view.controller_path unless path.include?(?/) - @view.find_template(path, prefix, true, locals) - end - - def partial_path(object = @object) - @partial_names[object.class.name] ||= begin - object = object.to_model if object.respond_to?(:to_model) - - object.class.model_name.partial_path.dup.tap do |partial| - path = @view.controller_path - partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/) - end - end - end - end - def _render_partial(options, &block) #:nodoc: - _wrap_formats(options[:partial]) do - if defined?(@renderer) - @renderer.setup(options, block) - else - @renderer = PartialRenderer.new(self, options, block) - end - - @renderer.render - end + _partial_renderer.setup(options, block).render end + def _partial_renderer #:nodoc: + @_partial_renderer ||= PartialRenderer.new(self) + end end end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 8e599c71df..adbb6bc626 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -21,11 +21,7 @@ module ActionView elsif options.key?(:partial) _render_partial(options) else - _wrap_formats(options[:template] || options[:file]) do - template = _determine_template(options) - lookup_context.freeze_formats(template.formats, true) - _render_template(template, options[:layout], options) - end + _render_template(options) end when :update update_page(&block) @@ -34,51 +30,70 @@ module ActionView end end - # Checks if the given path contains a format and if so, change - # the lookup context to take this new format into account. - def _wrap_formats(value) - return yield unless value.is_a?(String) - @@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/ + # Returns the contents that are yielded to a layout, given a name or a block. + # + # You can think of a layout as a method that is called with a block. If the user calls + # yield :some_name, the block, by default, returns content_for(:some_name). + # If the user calls simply +yield+, the default block returns content_for(:layout). + # + # The user can override this default by passing a block to the layout: + # + # # The template + # <%= render :layout => "my_layout" do %> + # Content + # <% end %> + # + # # The layout + # + # <%= yield %> + # + # + # In this case, instead of the default block, which would return content_for(:layout), + # this method returns the block that was passed in to render :layout, and the response + # would be + # + # + # Content + # + # + # Finally, the block can take block arguments, which can be passed in by +yield+: + # + # # The template + # <%= render :layout => "my_layout" do |customer| %> + # Hello <%= customer.name %> + # <% end %> + # + # # The layout + # + # <%= yield Struct.new(:name).new("David") %> + # + # + # In this case, the layout would receive the block passed into render :layout, + # and the struct specified would be passed into the block as an argument. The result + # would be + # + # + # Hello David + # + # + def _layout_for(*args, &block) + name = args.first - if value.sub!(@@formats_regexp, "") - update_details(:formats => [$1.to_sym]){ yield } + if name.is_a?(Symbol) + @_content_for[name].html_safe + elsif block + capture(*args, &block) else - yield + @_content_for[:layout].html_safe end end - # Determine the template to be rendered using the given options. - def _determine_template(options) #:nodoc: - keys = (options[:locals] ||= {}).keys - - if options.key?(:inline) - handler = Template.handler_class_for_extension(options[:type] || "erb") - Template.new(options[:inline], "inline template", handler, { :locals => keys }) - elsif options.key?(:text) - Template::Text.new(options[:text], formats.try(:first)) - elsif options.key?(:file) - with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } - elsif options.key?(:template) - options[:template].respond_to?(:render) ? - options[:template] : find_template(options[:template], options[:prefix], false, keys) - end + def _render_template(options) #:nodoc: + _template_renderer.render(options) end - # Renders the given template. An string representing the layout can be - # supplied as well. - def _render_template(template, layout = nil, options = {}) #:nodoc: - locals = options[:locals] || {} - layout = find_layout(layout, locals.keys) if layout - - ActiveSupport::Notifications.instrument("render_template.action_view", - :identifier => template.identifier, :layout => layout.try(:virtual_path)) do - - content = template.render(self, locals) { |*name| _layout_for(*name) } - @_content_for[:layout] = content if layout - - content = _render_layout(layout, locals) if layout - content - end + def _template_renderer #:nodoc: + @_template_renderer ||= TemplateRenderer.new(self) end end end diff --git a/actionpack/lib/action_view/renderer/abstract_renderer.rb b/actionpack/lib/action_view/renderer/abstract_renderer.rb new file mode 100644 index 0000000000..f9fa63ce7f --- /dev/null +++ b/actionpack/lib/action_view/renderer/abstract_renderer.rb @@ -0,0 +1,36 @@ +module ActionView + class AbstractRenderer #:nodoc: + attr_reader :vew, :lookup_context + + delegate :find_template, :template_exists?, :with_fallbacks, :update_details, + :with_layout_format, :formats, :to => :lookup_context + + def initialize(view) + @view = view + @lookup_context = view.lookup_context + end + + def render + raise NotImplementedError + end + + # Contains the logic that actually renders the layout. + def render_layout(layout, locals, &block) #:nodoc: + view = @view + layout.render(view, locals){ |*name| view._layout_for(*name, &block) } + end + + # Checks if the given path contains a format and if so, change + # the lookup context to take this new format into account. + def wrap_formats(value) + return yield unless value.is_a?(String) + @@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/ + + if value.sub!(@@formats_regexp, "") + update_details(:formats => [$1.to_sym]){ yield } + else + yield + end + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb new file mode 100644 index 0000000000..3be1702f9e --- /dev/null +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -0,0 +1,167 @@ +require 'action_view/renderer/abstract_renderer' + +module ActionView + class PartialRenderer < AbstractRenderer #:nodoc: + N = ::ActiveSupport::Notifications + PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} } + + def initialize(view) + super + @partial_names = PARTIAL_NAMES[@view.controller.class.name] + end + + def setup(options, block) + partial = options[:partial] + + @options = options + @locals = options[:locals] || {} + @block = block + + if String === partial + @object = options[:object] + @path = partial + @collection = collection + else + @object = partial + + if @collection = collection_from_object || collection + paths = @collection_data = @collection.map { |o| partial_path(o) } + @path = paths.uniq.size == 1 ? paths.first : nil + else + @path = partial_path + end + end + + if @path + @variable, @variable_counter = retrieve_variable(@path) + else + paths.map! { |path| retrieve_variable(path).unshift(path) } + end + + self + end + + def render + wrap_formats(@path) do + identifier = ((@template = find_partial) ? @template.identifier : @path) + + if @collection + N.instrument("render_collection.action_view", :identifier => identifier || "collection", :count => @collection.size) do + render_collection + end + else + N.instrument("render_partial.action_view", :identifier => identifier) do + render_partial + end + end + end + end + + def render_collection + return nil if @collection.blank? + + if @options.key?(:spacer_template) + spacer = find_template(@options[:spacer_template]).render(@view, @locals) + end + + result = @template ? collection_with_template : collection_without_template + result.join(spacer).html_safe + end + + def render_partial + locals, view, block = @locals, @view, @block + object, as = @object, @variable + + if !block && (layout = @options[:layout]) + layout = find_template(layout) + end + + object ||= locals[as] + locals[as] = object + + content = @template.render(view, locals) do |*name| + view._layout_for(*name, &block) + end + + content = render_layout(layout, locals){ content } if layout + content + end + + private + + def collection + if @options.key?(:collection) + @options[:collection] || [] + end + end + + def collection_from_object + if @object.respond_to?(:to_ary) + @object + end + end + + def find_partial + if path = @path + locals = @locals.keys + locals << @variable + locals << @variable_counter if @collection + find_template(path, locals) + end + end + + def find_template(path=@path, locals=@locals.keys) + prefix = @view.controller_path unless path.include?(?/) + @lookup_context.find_template(path, prefix, true, locals) + end + + def collection_with_template + segments, locals, template = [], @locals, @template + as, counter = @variable, @variable_counter + + locals[counter] = -1 + + @collection.each do |object| + locals[counter] += 1 + locals[as] = object + segments << template.render(@view, locals) + end + + segments + end + + def collection_without_template + segments, locals, collection_data = [], @locals, @collection_data + index, template, cache = -1, nil, {} + keys = @locals.keys + + @collection.each_with_index do |object, i| + path, *data = collection_data[i] + template = (cache[path] ||= find_template(path, keys + data)) + locals[data[0]] = object + locals[data[1]] = (index += 1) + segments << template.render(@view, locals) + end + + @template = template + segments + end + + def partial_path(object = @object) + @partial_names[object.class.name] ||= begin + object = object.to_model if object.respond_to?(:to_model) + + object.class.model_name.partial_path.dup.tap do |partial| + path = @view.controller_path + partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/) + end + end + end + + def retrieve_variable(path) + variable = @options[:as] || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym + variable_counter = :"#{variable}_counter" if @collection + [variable, variable_counter] + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb new file mode 100644 index 0000000000..3acc68dcac --- /dev/null +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -0,0 +1,66 @@ +require 'action_view/renderer/abstract_renderer' + +module ActionView + class TemplateRenderer < AbstractRenderer #:nodoc: + def render(options) + wrap_formats(options[:template] || options[:file]) do + template = determine_template(options) + lookup_context.freeze_formats(template.formats, true) + render_template(template, options[:layout], options) + end + end + + # Determine the template to be rendered using the given options. + def determine_template(options) #:nodoc: + keys = (options[:locals] ||= {}).keys + + if options.key?(:inline) + handler = Template.handler_class_for_extension(options[:type] || "erb") + Template.new(options[:inline], "inline template", handler, { :locals => keys }) + elsif options.key?(:text) + Template::Text.new(options[:text], formats.try(:first)) + elsif options.key?(:file) + with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } + elsif options.key?(:template) + options[:template].respond_to?(:render) ? + options[:template] : find_template(options[:template], options[:prefix], false, keys) + end + end + + # Renders the given template. An string representing the layout can be + # supplied as well. + def render_template(template, layout = nil, options = {}) #:nodoc: + view, locals = @view, options[:locals] || {} + layout = find_layout(layout, locals.keys) if layout + + ActiveSupport::Notifications.instrument("render_template.action_view", + :identifier => template.identifier, :layout => layout.try(:virtual_path)) do + + content = template.render(view, locals) { |*name| view._layout_for(*name) } + + if layout + view.store_content_for(:layout, content) + content = render_layout(layout, locals) + end + + content + end + end + + # This is the method which actually finds the layout using details in the lookup + # context object. If no layout is found, it checks if at least a layout with + # the given name exists across all details before raising the error. + def find_layout(layout, keys) + begin + with_layout_format do + layout =~ /^\// ? + with_fallbacks { find_template(layout, nil, false, keys) } : find_template(layout, nil, false, keys) + end + rescue ActionView::MissingTemplate => e + update_details(:formats => nil) do + raise unless template_exists?(layout) + end + end + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 3cc9bb2710..074daa5d28 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -155,11 +155,12 @@ module ActionView # virtual path set (true just for inline templates). def refresh(view) raise "A template need to have a virtual path in order to be refreshed" unless @virtual_path + lookup = view.lookup_context pieces = @virtual_path.split("/") name = pieces.pop partial = name.sub!(/^_/, "") - view.lookup_context.disable_cache do - view.find_template(name, pieces.join, partial || false, @locals) + lookup.disable_cache do + lookup.find_template(name, pieces.join, partial || false, @locals) end end -- cgit v1.2.3 From 940b57789fb9166658974c591e68d22ecab29f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 12:34:31 +0200 Subject: Add support to render :once. This will be used internally by sprockets to ensure requires are executed just once. --- actionpack/lib/abstract_controller/rendering.rb | 2 +- actionpack/lib/action_view/render/rendering.rb | 7 +++ .../lib/action_view/renderer/abstract_renderer.rb | 12 ++-- .../lib/action_view/renderer/partial_renderer.rb | 7 +-- .../lib/action_view/renderer/template_renderer.rb | 67 ++++++++++++++------ .../test/controller/new_base/render_once_test.rb | 73 ++++++++++++++++++++++ 6 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 actionpack/test/controller/new_base/render_once_test.rb diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index e88e5aefc0..1c63fb2d14 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -155,7 +155,7 @@ module AbstractController options[:partial] = action_name end - if (options.keys & [:partial, :file, :template]).empty? + if (options.keys & [:partial, :file, :template, :once]).empty? options[:prefix] ||= _prefix end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index adbb6bc626..0cd5d9d437 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -10,6 +10,7 @@ module ActionView # * :file - Renders an explicit template file (this used to be the old default), add :locals to pass in those. # * :inline - Renders an inline template similar to how it's done in the controller. # * :text - Renders the text passed in out. + # * :once - Receives :template paths and ensures they are rendered just once. # # If no options hash is passed or :update specified, the default is to render a partial and use the second parameter # as the locals hash. @@ -20,6 +21,8 @@ module ActionView _render_partial(options.merge(:partial => options[:layout]), &block) elsif options.key?(:partial) _render_partial(options) + elsif options.key?(:once) + _render_once(options) else _render_template(options) end @@ -88,6 +91,10 @@ module ActionView end end + def _render_once(options) #:nodoc: + _template_renderer.render_once(options) + end + def _render_template(options) #:nodoc: _template_renderer.render(options) end diff --git a/actionpack/lib/action_view/renderer/abstract_renderer.rb b/actionpack/lib/action_view/renderer/abstract_renderer.rb index f9fa63ce7f..77cfa51dff 100644 --- a/actionpack/lib/action_view/renderer/abstract_renderer.rb +++ b/actionpack/lib/action_view/renderer/abstract_renderer.rb @@ -14,12 +14,6 @@ module ActionView raise NotImplementedError end - # Contains the logic that actually renders the layout. - def render_layout(layout, locals, &block) #:nodoc: - view = @view - layout.render(view, locals){ |*name| view._layout_for(*name, &block) } - end - # Checks if the given path contains a format and if so, change # the lookup context to take this new format into account. def wrap_formats(value) @@ -32,5 +26,11 @@ module ActionView yield end end + + protected + + def instrument(name, options={}) + ActiveSupport::Notifications.instrument("render_#{name}.action_view", options){ yield } + end end end \ No newline at end of file diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index 3be1702f9e..eff425687b 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -2,7 +2,6 @@ require 'action_view/renderer/abstract_renderer' module ActionView class PartialRenderer < AbstractRenderer #:nodoc: - N = ::ActiveSupport::Notifications PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} } def initialize(view) @@ -46,11 +45,11 @@ module ActionView identifier = ((@template = find_partial) ? @template.identifier : @path) if @collection - N.instrument("render_collection.action_view", :identifier => identifier || "collection", :count => @collection.size) do + instrument(:collection, :identifier => identifier || "collection", :count => @collection.size) do render_collection end else - N.instrument("render_partial.action_view", :identifier => identifier) do + instrument(:partial, :identifier => identifier) do render_partial end end @@ -83,7 +82,7 @@ module ActionView view._layout_for(*name, &block) end - content = render_layout(layout, locals){ content } if layout + content = layout.render(view, locals){ content } if layout content end diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb index 3acc68dcac..9f9df15347 100644 --- a/actionpack/lib/action_view/renderer/template_renderer.rb +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -1,26 +1,51 @@ +require 'set' +require 'active_support/core_ext/object/try' +require 'active_support/core_ext/array/wrap' require 'action_view/renderer/abstract_renderer' module ActionView class TemplateRenderer < AbstractRenderer #:nodoc: + attr_reader :rendered + + def initialize(view) + super + @rendered = Set.new + end + def render(options) wrap_formats(options[:template] || options[:file]) do template = determine_template(options) - lookup_context.freeze_formats(template.formats, true) - render_template(template, options[:layout], options) + render_template(template, options[:layout], options[:locals]) + end + end + + def render_once(options) + paths, locals = options[:once], options[:locals] || {} + layout, keys, prefix = options[:layout], locals.keys, options[:prefix] + + raise "render :once expects a String or an Array to be given" unless paths + + render_with_layout(layout, locals) do + contents = [] + Array.wrap(paths).each do |path| + template = find_template(path, prefix, false, keys) + contents << render_template(template, nil, locals) if @rendered.add?(template) + end + contents.join("\n") end end # Determine the template to be rendered using the given options. def determine_template(options) #:nodoc: - keys = (options[:locals] ||= {}).keys + keys = options[:locals].try(:keys) || [] - if options.key?(:inline) - handler = Template.handler_class_for_extension(options[:type] || "erb") - Template.new(options[:inline], "inline template", handler, { :locals => keys }) - elsif options.key?(:text) + if options.key?(:text) Template::Text.new(options[:text], formats.try(:first)) elsif options.key?(:file) with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } + elsif options.key?(:inline) + handler = Template.handler_class_for_extension(options[:type] || "erb") + Template.new(options[:inline], "inline template", handler, { :locals => keys }) elsif options.key?(:template) options[:template].respond_to?(:render) ? options[:template] : find_template(options[:template], options[:prefix], false, keys) @@ -29,20 +54,26 @@ module ActionView # Renders the given template. An string representing the layout can be # supplied as well. - def render_template(template, layout = nil, options = {}) #:nodoc: - view, locals = @view, options[:locals] || {} - layout = find_layout(layout, locals.keys) if layout + def render_template(template, layout_name = nil, locals = {}) #:nodoc: + lookup_context.freeze_formats(template.formats, true) + view, locals = @view, locals || {} - ActiveSupport::Notifications.instrument("render_template.action_view", - :identifier => template.identifier, :layout => layout.try(:virtual_path)) do - - content = template.render(view, locals) { |*name| view._layout_for(*name) } - - if layout - view.store_content_for(:layout, content) - content = render_layout(layout, locals) + render_with_layout(layout_name, locals) do |layout| + instrument(:template, :identifier => template.identifier, :layout => layout.try(:virtual_path)) do + template.render(view, locals) { |*name| view._layout_for(*name) } end + end + end + + def render_with_layout(path, locals) #:nodoc: + layout = path && find_layout(path, locals.keys) + content = yield(layout) + if layout + view = @view + view.store_content_for(:layout, content) + layout.render(view, locals){ |*name| view._layout_for(*name) } + else content end end diff --git a/actionpack/test/controller/new_base/render_once_test.rb b/actionpack/test/controller/new_base/render_once_test.rb new file mode 100644 index 0000000000..12892b7255 --- /dev/null +++ b/actionpack/test/controller/new_base/render_once_test.rb @@ -0,0 +1,73 @@ +require 'abstract_unit' + +module RenderTemplate + class RenderOnceController < ActionController::Base + layout false + + RESOLVER = ActionView::FixtureResolver.new( + "test/a.html.erb" => "a", + "test/b.html.erb" => "<>", + "test/c.html.erb" => "c", + "test/one.html.erb" => "<%= render :once => 'test/result' %>", + "test/two.html.erb" => "<%= render :once => 'test/result' %>", + "test/three.html.erb" => "<%= render :once => 'test/result' %>", + "test/result.html.erb" => "YES!", + "layouts/test.html.erb" => "l<%= yield %>l" + ) + + self.view_paths = [RESOLVER] + + def multiple + render :once => %w(test/a test/b test/c) + end + + def once + render :once => %w(test/one test/two test/three) + end + + def duplicate + render :once => %w(test/a test/a test/a) + end + + def with_layout + render :once => %w(test/a test/b test/c), :layout => "test" + end + end + + module Tests + def test_mutliple_arguments_get_all_rendered + get :multiple + assert_response "a\n<>\nc" + end + + def test_referenced_templates_get_rendered_once + get :once + assert_response "YES!\n\n" + end + + def test_duplicated_templates_get_rendered_once + get :duplicate + assert_response "a" + end + + def test_layout_wraps_all_rendered_templates + get :with_layout + assert_response "la\n<>\ncl" + end + end + + class TestWithResolverCache < Rack::TestCase + testing RenderTemplate::RenderOnceController + include Tests + end + + # TODO This still needs to be implemented and supported. + # class TestWithoutResolverCache < Rack::TestCase + # testing RenderTemplate::RenderOnceController + # include Tests + # + # def setup + # RenderTemplate::RenderOnceController::RESOLVER.stubs(:caching?).returns(false) + # end + # end +end -- cgit v1.2.3 From cba395dab9812d86d48cc0574061cd6dcd18009b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 12:40:47 +0200 Subject: Update CHANGELOG. --- actionpack/CHANGELOG | 8 ++++++++ actionpack/lib/action_view/render/rendering.rb | 2 +- railties/CHANGELOG | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 6352b97a6b..3f8188b1f7 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,13 @@ *Rails 3.1.0 (unreleased)* +* Added render :once. You can pass either a string or an array of strings and Rails will ensure they each of them are rendered just once. [José Valim] + +* Deprecate old template handler API. The new API simply requires a template handler to respond to call. [José Valim] + +* :rhtml and :rxml were finally removed as template handlers. [José Valim] + +* Moved etag responsibility from ActionDispatch::Response to the middleware stack. [José Valim] + * Rely on Rack::Session stores API for more compatibility across the Ruby world. This is backwards incompatible since Rack::Session expects #get_session to accept 4 arguments and requires #destroy_session instead of simply #destroy. [José Valim] * file_field automatically adds :multipart => true to the enclosing form. [Santiago Pastorino] diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 0cd5d9d437..baa5d2c3fd 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -10,7 +10,7 @@ module ActionView # * :file - Renders an explicit template file (this used to be the old default), add :locals to pass in those. # * :inline - Renders an inline template similar to how it's done in the controller. # * :text - Renders the text passed in out. - # * :once - Receives :template paths and ensures they are rendered just once. + # * :once - Accepts a string or an array of strings and Rails will ensure they each of them are rendered just once. # # If no options hash is passed or :update specified, the default is to render a partial and use the second parameter # as the locals hash. diff --git a/railties/CHANGELOG b/railties/CHANGELOG index d2a4add375..b38a9ce750 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,6 +1,8 @@ *Rails 3.1.0 (unreleased)* -* Added Rack::Cache to the default middleware stack +* Added Rack::Etag and Rack::ConditionalGet to the default middleware stack [José Valim] + +* Added Rack::Cache to the default middleware stack [Yehuda Katz and Carl Lerche] * Engine is now rack application [Piotr Sarnacki] -- cgit v1.2.3 From ffa32714bd339ae32355a6827750e1af81454a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 13:17:01 +0200 Subject: Add some unit tests to Template#refresh. --- actionpack/test/template/template_test.rb | 32 +++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index eb2d4aab36..34679962b2 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -1,9 +1,16 @@ require "abstract_unit" +require "logger" class TestERBTemplate < ActiveSupport::TestCase ERBHandler = ActionView::Template::Handlers::ERB.new class Context + class LookupContext + def disable_cache + yield + end + end + def initialize @output_buffer = "original" @_virtual_path = nil @@ -22,8 +29,11 @@ class TestERBTemplate < ActiveSupport::TestCase ) end + def lookup_context + @lookup_context ||= LookupContext.new + end + def logger - require "logger" Logger.new(STDERR) end @@ -37,11 +47,11 @@ class TestERBTemplate < ActiveSupport::TestCase end def render(locals = {}) - @template.render(@obj, locals) + @template.render(@context, locals) end def setup - @obj = Context.new + @context = Context.new end def test_basic_template @@ -70,7 +80,7 @@ class TestERBTemplate < ActiveSupport::TestCase def test_restores_buffer @template = new_template assert_equal "Hello", render - assert_equal "original", @obj.my_buffer + assert_equal "original", @context.my_buffer end def test_virtual_path @@ -80,6 +90,20 @@ class TestERBTemplate < ActiveSupport::TestCase assert_equal "hellopartialhello", render end + def test_refresh + @template = new_template("Hello", :virtual_path => "test/foo") + @template.locals = [:key] + @context.lookup_context.expects(:find_template).with("foo", "test", false, [:key]).returns("template") + assert_equal "template", @template.refresh(@context) + end + + def test_refresh_raises_an_error_without_virtual_path + @template = new_template("Hello", :virtual_path => nil) + assert_raise RuntimeError, /OMG/ do + @template.refresh(@context) + end + end + if "ruby".encoding_aware? def test_resulting_string_is_utf8 @template = new_template -- cgit v1.2.3 From 11aa5157355d06ddbc9cad8fd0aa43a75ac8431e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 13:43:32 +0200 Subject: Add expire! and rerender to the template API. This will be used by SASS template handler. --- actionpack/lib/action_view/template.rb | 23 +++++++++++++-- actionpack/test/template/template_test.rb | 49 +++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 074daa5d28..5c3e0e899b 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -154,13 +154,30 @@ module ActionView # Notice this method raises an error if the template to be refreshed does not have a # virtual path set (true just for inline templates). def refresh(view) - raise "A template need to have a virtual path in order to be refreshed" unless @virtual_path + raise "A template needs to have a virtual path in order to be refreshed" unless @virtual_path lookup = view.lookup_context pieces = @virtual_path.split("/") name = pieces.pop - partial = name.sub!(/^_/, "") + partial = !!name.sub!(/^_/, "") lookup.disable_cache do - lookup.find_template(name, pieces.join, partial || false, @locals) + lookup.find_template(name, pieces.join, partial, @locals) + end + end + + # Expires this template by setting his updated_at date to Jan 1st, 1970. + def expire! + @updated_at = Time.utc(1970) + end + + # Receives a view context and renders a template exactly like self by using + # the @virtual_path. It raises an error if no @virtual_path was given. + def rerender(view) + raise "A template needs to have a virtual path in order to be rerendered" unless @virtual_path + name = @virtual_path.dup + if name.sub!(/(^|\/)_([^\/]*)$/, '\1\2') + view.render :partial => name + else + view.render :template => @virtual_path end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 34679962b2..22401dd145 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -90,20 +90,65 @@ class TestERBTemplate < ActiveSupport::TestCase assert_equal "hellopartialhello", render end - def test_refresh + def test_refresh_with_templates @template = new_template("Hello", :virtual_path => "test/foo") @template.locals = [:key] @context.lookup_context.expects(:find_template).with("foo", "test", false, [:key]).returns("template") assert_equal "template", @template.refresh(@context) end + def test_refresh_with_partials + @template = new_template("Hello", :virtual_path => "test/_foo") + @template.locals = [:key] + @context.lookup_context.expects(:find_template).with("foo", "test", true, [:key]).returns("partial") + assert_equal "partial", @template.refresh(@context) + end + def test_refresh_raises_an_error_without_virtual_path @template = new_template("Hello", :virtual_path => nil) - assert_raise RuntimeError, /OMG/ do + assert_raise RuntimeError do @template.refresh(@context) end end + def test_template_expire_sets_the_timestamp_to_1970 + @template = new_template("Hello", :updated_at => Time.utc(2010)) + assert_equal Time.utc(2010), @template.updated_at + @template.expire! + assert_equal Time.utc(1970), @template.updated_at + end + + def test_template_rerender_renders_a_template_like_self + @template = new_template("Hello", :virtual_path => "test/foo_bar") + @context.expects(:render).with(:template => "test/foo_bar").returns("template") + assert_equal "template", @template.rerender(@context) + end + + def test_template_rerender_renders_a_root_template_like_self + @template = new_template("Hello", :virtual_path => "foo_bar") + @context.expects(:render).with(:template => "foo_bar").returns("template") + assert_equal "template", @template.rerender(@context) + end + + def test_template_rerender_renders_a_partial_like_self + @template = new_template("Hello", :virtual_path => "test/_foo_bar") + @context.expects(:render).with(:partial => "test/foo_bar").returns("partial") + assert_equal "partial", @template.rerender(@context) + end + + def test_template_rerender_renders_a_root_partial_like_self + @template = new_template("Hello", :virtual_path => "_foo_bar") + @context.expects(:render).with(:partial => "foo_bar").returns("partial") + assert_equal "partial", @template.rerender(@context) + end + + def test_rerender_raises_an_error_without_virtual_path + @template = new_template("Hello", :virtual_path => nil) + assert_raise RuntimeError do + @template.rerender(@context) + end + end + if "ruby".encoding_aware? def test_resulting_string_is_utf8 @template = new_template -- cgit v1.2.3 From 49b6f33f99a28d68f18203a696fb47854a9085d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 14:47:11 +0200 Subject: Clean up unused methods from AV::Base and pass in the template object on rendering. --- actionpack/lib/action_view/base.rb | 29 ++++++++++------------ .../lib/action_view/helpers/translation_helper.rb | 4 +-- actionpack/lib/action_view/template.rb | 7 ++++-- actionpack/test/template/template_test.rb | 18 ++++++++------ .../test/template/translation_helper_test.rb | 4 +-- actionpack/test/template/url_helper_test.rb | 2 +- 6 files changed, 33 insertions(+), 31 deletions(-) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 2a601c7cee..a7a6bbd3a4 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -155,9 +155,6 @@ module ActionView #:nodoc: # # See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator::GeneratorMethods documentation for more details. class Base - module Subclasses - end - include Helpers, Rendering, Partials, ::ERB::Util, Context # Specify whether RJS responses should be wrapped in a try/catch block @@ -177,12 +174,12 @@ module ActionView #:nodoc: delegate :logger, :to => 'ActionController::Base', :allow_nil => true end - attr_accessor :base_path, :assigns, :template_extension, :lookup_context - attr_internal :captures, :request, :controller, :template, :config + attr_accessor :_template + attr_internal :request, :controller, :config, :assigns, :lookup_context delegate :formats, :formats=, :locale, :locale=, :view_paths, :view_paths=, :to => :lookup_context - delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, + delegate :request_forgery_protection_token, :params, :session, :cookies, :response, :headers, :flash, :action_name, :controller_name, :to => :controller delegate :logger, :to => :controller, :allow_nil => true @@ -197,26 +194,26 @@ module ActionView #:nodoc: end def assign(new_assigns) # :nodoc: - self.assigns = new_assigns.each { |key, value| instance_variable_set("@#{key}", value) } + @_assigns = new_assigns.each { |key, value| instance_variable_set("@#{key}", value) } end def initialize(lookup_context = nil, assigns_for_first_render = {}, controller = nil, formats = nil) #:nodoc: assign(assigns_for_first_render) - self.helpers = self.class.helpers || Module.new - - if @_controller = controller - @_request = controller.request if controller.respond_to?(:request) - end - - @_config = controller && controller.respond_to?(:config) ? controller.config.inheritable_copy : {} + self.helpers = Module.new unless self.class.helpers + @_config = {} @_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new } @_virtual_path = nil @output_buffer = nil - @lookup_context = lookup_context.is_a?(ActionView::LookupContext) ? + if @_controller = controller + @_request = controller.request if controller.respond_to?(:request) + @_config = controller.config.inheritable_copy if controller.respond_to?(:config) + end + + @_lookup_context = lookup_context.is_a?(ActionView::LookupContext) ? lookup_context : ActionView::LookupContext.new(lookup_context) - @lookup_context.formats = formats if formats + @_lookup_context.formats = formats if formats end def store_content_for(key, value) diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index 13767a09f9..8574ca6595 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -45,8 +45,8 @@ module ActionView private def scope_key_by_partial(key) if key.to_s.first == "." - if @_virtual_path - @_virtual_path.gsub(%r{/_?}, ".") + key.to_s + if (path = @_template && @_template.virtual_path) + path.gsub(%r{/_?}, ".") + key.to_s else raise "Cannot use t(#{key.inspect}) shortcut because path is not available" end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 5c3e0e899b..7dd8acf37b 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -133,12 +133,15 @@ module ActionView # we use a bang in this instrumentation because you don't want to # consume this in production. This is only slow if it's being listened to. def render(view, locals, &block) + old_template, view._template = view._template, self ActiveSupport::Notifications.instrument("!render_template.action_view", :virtual_path => @virtual_path) do compile!(view) view.send(method_name, locals, &block) end rescue Exception => e handle_render_error(view, e) + ensure + view._template = old_template end def mime_type @@ -272,9 +275,9 @@ module ActionView # encoding of the code source = <<-end_src def #{method_name}(local_assigns) - _old_virtual_path, @_virtual_path = @_virtual_path, #{@virtual_path.inspect};_old_output_buffer = @output_buffer;#{locals_code};#{code} + _old_output_buffer = @output_buffer;#{locals_code};#{code} ensure - @_virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer + @output_buffer = _old_output_buffer end end_src diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 22401dd145..63f792d328 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -4,12 +4,14 @@ require "logger" class TestERBTemplate < ActiveSupport::TestCase ERBHandler = ActionView::Template::Handlers::ERB.new - class Context - class LookupContext - def disable_cache - yield - end + class LookupContext + def disable_cache + yield end + end + + class Context + attr_accessor :_template def initialize @output_buffer = "original" @@ -22,7 +24,7 @@ class TestERBTemplate < ActiveSupport::TestCase def partial ActionView::Template.new( - "<%= @_virtual_path %>", + "<%= @_template.virtual_path %>", "partial", ERBHandler, :virtual_path => "partial" @@ -84,9 +86,9 @@ class TestERBTemplate < ActiveSupport::TestCase end def test_virtual_path - @template = new_template("<%= @_virtual_path %>" \ + @template = new_template("<%= @_template.virtual_path %>" \ "<%= partial.render(self, {}) %>" \ - "<%= @_virtual_path %>") + "<%= @_template.virtual_path %>") assert_equal "hellopartialhello", render end diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb index 952719a589..763080550b 100644 --- a/actionpack/test/template/translation_helper_test.rb +++ b/actionpack/test/template/translation_helper_test.rb @@ -31,13 +31,13 @@ class TranslationHelperTest < ActiveSupport::TestCase def test_scoping_by_partial I18n.expects(:translate).with("test.translation.helper", :raise => true).returns("helper") - @view = ActionView::Base.new(ActionController::Base.view_paths, {}) + @view = ::ActionView::Base.new(ActionController::Base.view_paths, {}) assert_equal "helper", @view.render(:file => "test/translation") end def test_scoping_by_partial_of_an_array I18n.expects(:translate).with("test.scoped_translation.foo.bar", :raise => true).returns(["foo", "bar"]) - @view = ActionView::Base.new(ActionController::Base.view_paths, {}) + @view = ::ActionView::Base.new(ActionController::Base.view_paths, {}) assert_equal "foobar", @view.render(:file => "test/scoped_translation") end diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 98276da559..b8a7d4259d 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -9,7 +9,7 @@ class UrlHelperTest < ActiveSupport::TestCase # or request. # # In those cases, we'll set up a simple mock - attr_accessor :controller, :request + attr_accessor :controller, :request, :_template routes = ActionDispatch::Routing::RouteSet.new routes.draw do -- cgit v1.2.3 From d80afed620dde5b9356c883ae187db2332d4c18e Mon Sep 17 00:00:00 2001 From: Andrea Campi Date: Sat, 9 Oct 2010 19:28:43 +0200 Subject: Override #store to be consistent with #[]. [#5775 state:resolved] Signed-off-by: Santiago Pastorino --- .../lib/active_support/hash_with_indifferent_access.rb | 2 ++ activesupport/test/core_ext/hash_ext_test.rb | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index e8215bc566..c406dd3c2e 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -45,6 +45,8 @@ module ActiveSupport regular_writer(convert_key(key), convert_value(value)) end + alias_method :store, :[]= + # Updates the instantized hash with values from the second: # # hash_1 = HashWithIndifferentAccess.new diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 0f35eb9e78..545fed2684 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -316,6 +316,16 @@ class HashExtTest < Test::Unit::TestCase assert_equal expected, hash_1 end + def test_store_on_indifferent_access + hash = HashWithIndifferentAccess.new + hash.store(:test1, 1) + hash.store('test1', 11) + hash[:test2] = 2 + hash['test2'] = 22 + expected = { "test1" => 11, "test2" => 22 } + assert_equal expected, hash + end + def test_reverse_merge defaults = { :a => "x", :b => "y", :c => 10 }.freeze options = { :a => 1, :b => 2 } -- cgit v1.2.3 From f659a1576fc4a447bbfbd866c7244d8d790a3d9c Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Fri, 3 Sep 2010 01:23:15 +0200 Subject: Fix misleading advice to add 'memcache' to Gemfile [#5539 state:committed] Commit 57144388f removed the hard-coded dependency on the memcache-client gem, and added this warning advising people to install it if needed. The problem is, however, that if people follow the advice literally and install the 'memcache' gem, they will wind up with a completely different thing, which is not API compatible with the memcache-client gem and which Rails can't work with. So, be explicit and tell users to install the 'memcache-client' gem. Signed-off-by: Santiago Pastorino --- activesupport/lib/active_support/cache/mem_cache_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index 9eee3fc5e3..45263d482f 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -1,7 +1,7 @@ begin require 'memcache' rescue LoadError => e - $stderr.puts "You don't have memcache installed in your application. Please add it to your Gemfile and run bundle install" + $stderr.puts "You don't have memcache-client installed in your application. Please add it to your Gemfile and run bundle install" raise e end require 'digest/md5' -- cgit v1.2.3 From 682368d4ba0bb4548f896d02bc4e038ee8ba6b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 22:40:13 +0200 Subject: Use identifiers for template equality. --- .../lib/action_view/renderer/template_renderer.rb | 2 +- actionpack/lib/action_view/template.rb | 9 +++++++++ actionpack/lib/action_view/template/inline.rb | 20 ++++++++++++++++++++ .../test/controller/new_base/render_once_test.rb | 17 ++++++++--------- actionpack/test/template/template_test.rb | 8 ++++++++ 5 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 actionpack/lib/action_view/template/inline.rb diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb index 9f9df15347..a9076760c5 100644 --- a/actionpack/lib/action_view/renderer/template_renderer.rb +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -45,7 +45,7 @@ module ActionView with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } elsif options.key?(:inline) handler = Template.handler_class_for_extension(options[:type] || "erb") - Template.new(options[:inline], "inline template", handler, { :locals => keys }) + Template::Inline.new(options[:inline], handler, :locals => keys) elsif options.key?(:template) options[:template].respond_to?(:render) ? options[:template] : find_template(options[:template], options[:prefix], false, keys) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 7dd8acf37b..3ba18cbfae 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -93,6 +93,7 @@ module ActionView autoload :Error autoload :Handler autoload :Handlers + autoload :Inline autoload :Text end @@ -184,6 +185,14 @@ module ActionView end end + def hash + identifier.hash + end + + def eql?(other) + other.is_a?(Template) && other.identifier == identifier + end + def inspect @inspect ||= if defined?(Rails.root) diff --git a/actionpack/lib/action_view/template/inline.rb b/actionpack/lib/action_view/template/inline.rb new file mode 100644 index 0000000000..be08065b6b --- /dev/null +++ b/actionpack/lib/action_view/template/inline.rb @@ -0,0 +1,20 @@ +require 'digest/md5' + +module ActionView + class Template + class Inline < ::ActionView::Template + def initialize(source, handler, options={}) + super(source, "inline template", handler, options) + end + + def md5_source + @md5_source ||= Digest::MD5.hexdigest(source) + end + + def eql?(other) + other.is_a?(Inline) && other.md5_source == md5_source + end + end + end +end + \ No newline at end of file diff --git a/actionpack/test/controller/new_base/render_once_test.rb b/actionpack/test/controller/new_base/render_once_test.rb index 12892b7255..63de25be52 100644 --- a/actionpack/test/controller/new_base/render_once_test.rb +++ b/actionpack/test/controller/new_base/render_once_test.rb @@ -61,13 +61,12 @@ module RenderTemplate include Tests end - # TODO This still needs to be implemented and supported. - # class TestWithoutResolverCache < Rack::TestCase - # testing RenderTemplate::RenderOnceController - # include Tests - # - # def setup - # RenderTemplate::RenderOnceController::RESOLVER.stubs(:caching?).returns(false) - # end - # end + class TestWithoutResolverCache < Rack::TestCase + testing RenderTemplate::RenderOnceController + include Tests + + def setup + RenderTemplate::RenderOnceController::RESOLVER.stubs(:caching?).returns(false) + end + end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 63f792d328..f2156c31de 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -151,6 +151,14 @@ class TestERBTemplate < ActiveSupport::TestCase end end + def test_inline_template_is_only_equal_if_source_match + inline1 = ActionView::Template::Inline.new("sample", ERBHandler) + inline2 = ActionView::Template::Inline.new("sample", ERBHandler) + inline3 = ActionView::Template::Inline.new("other", ERBHandler) + assert inline1.eql?(inline2) + assert !inline1.eql?(inline3) + end + if "ruby".encoding_aware? def test_resulting_string_is_utf8 @template = new_template -- cgit v1.2.3 From 5ec27189b8b433145baa7270cf4219c5041f6a4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 10 Oct 2010 23:11:50 +0200 Subject: Do not allow templates coming from Fallback resolvers to store a virtual path. --- actionpack/lib/action_view.rb | 1 + actionpack/lib/action_view/lookup_context.rb | 2 +- actionpack/lib/action_view/template/resolver.rb | 13 +++++++++++++ actionpack/test/template/lookup_context_test.rb | 4 ++-- actionpack/test/template/render_test.rb | 13 ++++++++++++- 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index ad96f6c66d..0f9d35d062 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -57,6 +57,7 @@ module ActionView autoload :Resolver autoload :PathResolver autoload :FileSystemResolver + autoload :FallbackFileSystemResolver end autoload_at "action_view/template/error" do diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 0cff888ac1..80451798b1 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -10,7 +10,7 @@ module ActionView # this key is generated just once during the request, it speeds up all cache accesses. class LookupContext #:nodoc: mattr_accessor :fallbacks - @@fallbacks = [FileSystemResolver.new(""), FileSystemResolver.new("/")] + @@fallbacks = FallbackFileSystemResolver.instances mattr_accessor :registered_details self.registered_details = [] diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 5c6877a923..7707dbcf98 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -135,6 +135,7 @@ module ActionView end end + # A resolver that loads files from the filesystem. class FileSystemResolver < PathResolver def initialize(path) raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver) @@ -152,4 +153,16 @@ module ActionView end alias :== :eql? end + + # The same as FileSystemResolver but does not allow templates to store + # a virtual path since it is invalid for such resolvers. + class FallbackFileSystemResolver < FileSystemResolver + def self.instances + [new(""), new("/")] + end + + def decorate(*) + super.each { |t| t.virtual_path = nil } + end + end end diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index 23dfc1ba75..850589b13b 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -100,8 +100,8 @@ class LookupContextTest < ActiveSupport::TestCase @lookup_context.with_fallbacks do assert_equal 3, @lookup_context.view_paths.size - assert @lookup_context.view_paths.include?(ActionView::FileSystemResolver.new("")) - assert @lookup_context.view_paths.include?(ActionView::FileSystemResolver.new("/")) + assert @lookup_context.view_paths.include?(ActionView::FallbackFileSystemResolver.new("")) + assert @lookup_context.view_paths.include?(ActionView::FallbackFileSystemResolver.new("/")) end end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 756d8d05d2..17bb610b6a 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -114,7 +114,7 @@ module RenderTestCases end def test_render_sub_template_with_errors - @view.render(:file => "test/sub_template_raise") + @view.render(:template => "test/sub_template_raise") flunk "Render did not raise Template::Error" rescue ActionView::Template::Error => e assert_match %r!method.*doesnt_exist!, e.message @@ -123,6 +123,17 @@ module RenderTestCases assert_equal File.expand_path("#{FIXTURE_LOAD_PATH}/test/_raise.html.erb"), e.file_name end + def test_render_file_with_errors + @view.render(:file => File.expand_path("test/_raise", FIXTURE_LOAD_PATH)) + flunk "Render did not raise Template::Error" + rescue ActionView::Template::Error => e + assert_match %r!method.*doesnt_exist!, e.message + assert_equal "", e.sub_template_message + assert_equal "1", e.line_number + assert_equal "1: <%= doesnt_exist %>", e.annoted_source_code.strip + assert_equal File.expand_path("#{FIXTURE_LOAD_PATH}/test/_raise.html.erb"), e.file_name + end + def test_render_object assert_equal "Hello: david", @view.render(:partial => "test/customer", :object => Customer.new("david")) end -- cgit v1.2.3 From de05e1c33ce13069025d1531e082adc5fe62e79a Mon Sep 17 00:00:00 2001 From: Barry Sears Date: Wed, 29 Sep 2010 18:31:58 -0500 Subject: Make ActiveSupport load own version. [#5739 state:committed] Signed-off-by: Santiago Pastorino --- activesupport/lib/active_support.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index ba91e8bba3..d2a845db3a 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -43,6 +43,7 @@ module ActiveSupport autoload :FileUpdateChecker autoload :LogSubscriber autoload :Notifications + autoload :VERSION # TODO: Narrow this list down eager_autoload do -- cgit v1.2.3 From cc8e386d08d83ca1ad0c5da863f588b4c4fbe62c Mon Sep 17 00:00:00 2001 From: wycats Date: Sun, 10 Oct 2010 16:11:04 -0700 Subject: Always pull in version for frameworks (standardize autoload / require / none) --- actionmailer/lib/action_mailer.rb | 1 + activemodel/lib/active_model.rb | 3 +-- activerecord/lib/active_record.rb | 4 ++-- activeresource/lib/active_resource.rb | 1 + activesupport/lib/active_support.rb | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 05ba12197a..02a9916703 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -26,6 +26,7 @@ $:.unshift(actionpack_path) if File.directory?(actionpack_path) && !$:.include?( require 'abstract_controller' require 'action_view' +require 'action_mailer/version' # Common Active Support usage in Action Mailer require 'active_support/core_ext/class' diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index 9b8f843432..be0f24ff92 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -24,7 +24,7 @@ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) require 'active_support' - +require 'active_model/version' module ActiveModel extend ActiveSupport::Autoload @@ -45,7 +45,6 @@ module ActiveModel autoload :Serialization autoload :TestCase autoload :Translation - autoload :VERSION autoload :Validations autoload :Validator diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index f692e5ac89..c80bce2849 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -33,12 +33,12 @@ require 'active_support/i18n' require 'active_model' require 'arel' +require 'active_record/version' + module ActiveRecord extend ActiveSupport::Autoload eager_autoload do - autoload :VERSION - autoload :ActiveRecordError, 'active_record/errors' autoload :ConnectionNotEstablished, 'active_record/errors' diff --git a/activeresource/lib/active_resource.rb b/activeresource/lib/active_resource.rb index 3e4a1dd4a1..186865f811 100644 --- a/activeresource/lib/active_resource.rb +++ b/activeresource/lib/active_resource.rb @@ -29,6 +29,7 @@ $:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include require 'active_support' require 'active_model' +require 'active_resource/version' module ActiveResource extend ActiveSupport::Autoload diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index d2a845db3a..6b87774978 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -35,6 +35,7 @@ module ActiveSupport end require "active_support/dependencies/autoload" +require "active_support/version" module ActiveSupport extend ActiveSupport::Autoload @@ -43,7 +44,6 @@ module ActiveSupport autoload :FileUpdateChecker autoload :LogSubscriber autoload :Notifications - autoload :VERSION # TODO: Narrow this list down eager_autoload do -- cgit v1.2.3 From cb26eee54d34eda966b4c9da810b700cce24f824 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 10 Oct 2010 21:07:53 -0200 Subject: Revert "Make InstanceTagMethods#value_before_type_cast raise if the model don't respond to attr_before_type_cast or attr method" And "Makes form_helper use overriden model accessors" This reverts commit 3ba8e3100548f10fce0c9784981a4589531476dd and fb0bd8c1092db51888ec4bb72af6c595e13c31fa. --- actionpack/lib/action_view/helpers/form_helper.rb | 11 +++------ actionpack/test/template/form_helper_test.rb | 30 ----------------------- 2 files changed, 3 insertions(+), 38 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 3cd8b02bc4..b34a74788e 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1020,14 +1020,9 @@ module ActionView def value_before_type_cast(object, method_name) unless object.nil? - if object.respond_to?(method_name) - object.send(method_name) - # FIXME: this is AR dependent - elsif object.respond_to?(method_name + "_before_type_cast") - object.send(method_name + "_before_type_cast") - else - raise NoMethodError, "Model #{object.class} does not respond to #{method_name}" - end + object.respond_to?(method_name + "_before_type_cast") ? + object.send(method_name + "_before_type_cast") : + object.send(method_name) end end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 8809e510fb..0bfdbeebd1 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -4,18 +4,6 @@ require 'controller/fake_models' class FormHelperTest < ActionView::TestCase tests ActionView::Helpers::FormHelper - class Developer - def name_before_type_cast - "David" - end - - def name - "Santiago" - end - - attr_writer :language - end - def form_for(*) @output_buffer = super end @@ -278,24 +266,6 @@ class FormHelperTest < ActionView::TestCase text_field("user", "email", :type => "email") end - def test_text_field_from_a_user_defined_method - @developer = Developer.new - assert_dom_equal( - '', text_field("developer", "name") - ) - end - - def test_text_field_on_a_model_with_undefined_attr_reader - @developer = Developer.new - @developer.language = 'ruby' - begin - text_field("developer", "language") - rescue NoMethodError => error - message = error.message - end - assert_equal "Model #{Developer} does not respond to language", message - end - def test_check_box assert_dom_equal( '', -- cgit v1.2.3 From 9074e8c644c952a639617ed190b915a54a835e1b Mon Sep 17 00:00:00 2001 From: Nathan Zook and Ryan Bigg Date: Mon, 11 Oct 2010 11:15:38 +1100 Subject: Updated RUNNING_UNIT_TESTS documentation with mention of the build_databases rake tasks. --- activerecord/RUNNING_UNIT_TESTS | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/activerecord/RUNNING_UNIT_TESTS b/activerecord/RUNNING_UNIT_TESTS index 324df2c025..18e3936d8a 100644 --- a/activerecord/RUNNING_UNIT_TESTS +++ b/activerecord/RUNNING_UNIT_TESTS @@ -31,8 +31,13 @@ That'll run the base suite using the MySQL-Ruby adapter. Some tests rely on the being initialized - you can initialize the schema with: rake test_mysql TEST=test/cases/aaa_create_tables_test.rb + rake mysql:build_databases + +To setup the testing environment for PostgreSQL use this command: + + rake postgresql:build_databases The incantation for running a particular test looks like this - ruby -w -I"lib:test:test/connections/native_postgresql" test/cases/datatype_test_postgresql.rb -n test_timestamp_with_zone_values_without_rails_time_zone_support + rake test TEST=test/cases/datatype_test_postgresql.rb TESTOPTS="-n test_timestamp_with_zone_values_without_rails_time_zone_support" -- cgit v1.2.3 From 7d081162222e5334fe42a7fbc07354aa4f5e5d50 Mon Sep 17 00:00:00 2001 From: Utkarsh Kukreti Date: Wed, 8 Sep 2010 00:00:10 +0530 Subject: Fix typo 'configation' [#5575 state:resolved] --- .../rails/generators/rails/app/templates/config/databases/oracle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml index fddf8b8144..b661a60389 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml @@ -10,7 +10,7 @@ # # By default prefetch_rows (OCI_ATTR_PREFETCH_ROWS) is set to 100. And # until true bind variables are supported, cursor_sharing is set by default -# to 'similar'. Both can be changed in the configation below; the defaults +# to 'similar'. Both can be changed in the configuration below; the defaults # are equivalent to specifying: # # prefetch_rows: 100 -- cgit v1.2.3 From ef74ad8e0c0a1c46f7e8983e9d5460dea9bec95e Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Mon, 11 Oct 2010 13:28:50 +1100 Subject: Remove mention to register_javascript_include_default in documentation --- actionpack/lib/action_view/helpers/asset_tag_helper.rb | 3 --- railties/guides/source/action_view_overview.textile | 3 --- 2 files changed, 6 deletions(-) diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index c1dfbe5dc3..b97c73aff9 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -292,9 +292,6 @@ module ActionView # # * = The application.js file is only referenced if it exists # - # Though it's not really recommended practice, if you need to extend the default JavaScript set for any reason - # (e.g., you're going to be using a certain .js file in every action), then take a look at the register_javascript_include_default method. - # # You can also include all javascripts in the +javascripts+ directory using :all as the source: # # javascript_include_tag :all # => diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index 843dfe530d..0e1a352ebd 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -253,9 +253,6 @@ javascript_include_tag :monkey # => -h5. register_javascript_include_default - -Register one or more additional JavaScript files to be included when +javascript_include_tag :defaults+ is called. This method is typically intended to be called from plugin initialization to register additional +.js+ files that the plugin installed in +public/javascripts+. h5. register_stylesheet_expansion -- cgit v1.2.3 From 234a4ca7ddb7794a92f266af48fd38edbdb03003 Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Mon, 11 Oct 2010 13:32:04 +1100 Subject: Add missing CHANGELOG entry about reset_javascript_include_default --- actionpack/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 6352b97a6b..966d1ae47d 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -33,6 +33,8 @@ * Upgrade to Rack 1.2.1 [Jeremy Kemper] +* Removed reset_javascript_include_default, use config.action_view.javascript_expansions in config/application.rb for this instead [José Valim] + * Allow :path to be given to match/get/post/put/delete instead of :path_names in the new router [Carlos Antônio da Silva] * Added resources_path_names to the new router DSL [José Valim] -- cgit v1.2.3 From 70ad6e499f405efb8b0a2e58c9742d4957c6b7c5 Mon Sep 17 00:00:00 2001 From: "Philip R. Dutton" Date: Sun, 10 Oct 2010 22:31:30 -0400 Subject: I corrected a code snippet typo in the railties/guides/source/initialization.textile file [#5779 state:resolved] --- railties/guides/source/initialization.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 599ddccdd6..3e02bc0158 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -3070,7 +3070,7 @@ The +Rails::Plugin::Configuration+ class may be a bit difficult to find at first module Rails - class Plugin < Railtie + class Plugin < Engine ... end end -- cgit v1.2.3 From a8b1780410a86be58ac0f341ae6b079800783fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 11 Oct 2010 10:29:31 +0200 Subject: Updated DOCS for engines and added a couple TODOs. Also, commented internal railties rake tasks description. --- .../lib/active_record/railties/databases.rake | 2 +- railties/lib/rails/engine.rb | 82 +++++++++++++--------- railties/lib/rails/tasks/railties.rake | 2 +- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 778bce697e..5ad440e58d 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -481,7 +481,7 @@ end namespace :railties do namespace :install do - desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2" + # desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2" task :migrations => :"db:load_config" do to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map {|n| n.strip } railties = {} diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 4acebb4769..e9ce9610b8 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -77,14 +77,14 @@ module Rails # you need to do is: # # class MyEngine < Rails::Engine - # paths.app.controllers = "lib/controllers" + # paths["app/controllers"] = "lib/controllers" # end # # You can also have your controllers being loaded from both "app/controllers" and # "lib/controllers": # # class MyEngine < Rails::Engine - # paths.app.controllers << "lib/controllers" + # paths["app/controllers"] << "lib/controllers" # end # # The available paths in an Engine are: @@ -185,19 +185,21 @@ module Rails # == Serving static files # # By default, rails use ActionDispatch::Static to serve static files in development mode. This is ok - # while you develop your application, but when you want to deploy it, assets from engine will not be served. + # while you develop your application, but when you want to deploy it, assets from engine will not be + # served by default. You should choose one of the two following strategies: # - # You can fix it in one of two ways: # * enable serving static files by setting config.serve_static_assets to true # * symlink engines' public directories in application's public directory by running - # `rake railties:create_symlinks` + # `rake ENGINE_NAME:install:assets`, where ENGINE_NAME is usually my_engine for the + # examples above # # == Engine name # # There are some places where engine's name is used. + # # * routes: when you mount engine with mount(MyEngine::Engine => '/my_engine'), it's used as default :as option - # * migrations: when you copy engine's migrations, they will be decorated with suffix based on engine_name, for example: - # 2010010203121314_create_users.my_engine.rb + # + # * rake tasks: engines have a few rake tasks. They are usually under my_engine namespace. # # Engine name is set by default based on class name. For MyEngine::Engine it will be my_engine_engine. # You can change it manually it manually using engine_name method: @@ -210,11 +212,13 @@ module Rails # # == Namespaced Engine # - # Normally, when you create controllers, helpers and models inside engine, they are treated - # as they would be created inside application. One of the cosequences of that is including - # application's helpers and url_helpers inside controller. Sometimes, especially when your - # engine provides its own routes, you don't want that. To isolate engine's stuff from application - # you can use isolate_namespace method: + # Normally when you create controllers, helpers and models inside engine, they are treated + # as they were created inside the application. This means all applications helpers and named routes + # will be available to your engine controllers. + # + # However, sometimes you want to isolate your engine from the application, specially if your engine + # have its own router. To do that, you simply need to call +isolate_namespace+. This method requires + # you to pass a module where all your controllers, helpers and models should be nested to: # # module MyEngine # class Engine < Rails::Engine @@ -235,15 +239,21 @@ module Rails # url_helpers from MyEngine::Engine.routes. # # The next thing that changes in isolated engine is routes behaviour. Normally, when you namespace - # your controllers, you need to use scope or namespace method in routes. With isolated engine, - # the namespace is applied by default, so you can ignore it in routes. Further more, you don't need - # to use longer url helpers like "my_engine_articles_path". As the prefix is not set you can just use - # articles_path as you would normally do. + # your controllers, you also need to do namespace all your routes. With isolated engine, + # the namespace is applied by default, so you can ignore it in routes: + # + # MyEngine::Engine.routes.draw do + # resources :articles + # end + # + # The routes above will automatically point to MyEngine::ApplicationContoller. Further more, you don't + # need to use longer url helpers like "my_engine_articles_path". Instead, you shuold simply use + # articles_path as you would do with your application. # # To make that behaviour consistent with other parts of framework, isolated engine has influence also on # ActiveModel::Naming. When you use namespaced model, like MyEngine::Article, it will normally - # use the prefix "my_engine". In isolated engine, the prefix will be ommited in most of the places, - # like url helpers or form fields. + # use the prefix "my_engine". In isolated engine, the prefix will be ommited in url helpers and + # form fields for convenience. # # polymorphic_url(MyEngine::Article.new) #=> "articles_path" # @@ -251,16 +261,15 @@ module Rails # text_field :title #=> # end # - # - # Additionaly isolated engine will set its name according to namespace, so in that case: - # MyEngine::Engine.engine_name #=> "my_engine" and it will set MyEngine.table_name_prefix - # to "my_engine_". + # Additionaly isolated engine will set its name according to namespace, so + # MyEngine::Engine.engine_name #=> "my_engine". It will also set MyEngine.table_name_prefix + # to "my_engine_", changing MyEngine::Article model to use my_engine_article table. # # == Using Engine's routes outside Engine # - # Since you can mount engine inside application's routes now, you do not have direct access to engine's - # url_helpers inside application. When you mount Engine in application's routes special helper is - # created to allow doing that. Consider such scenario: + # Since now you can mount engine inside application's routes, you do not have direct access to engine's + # url_helpers inside application. When you mount Engine in application's routes, a special helper is + # created to allow you to do that. Consider such scenario: # # # APP/config/routes.rb # MyApplication::Application.routes.draw do @@ -268,7 +277,7 @@ module Rails # match "/foo" => "foo#index" # end # - # Now, you can use my_engine helper: + # Now, you can use my_engine helper inside your application: # # class FooController < ApplicationController # def index @@ -280,20 +289,23 @@ module Rails # # module MyEngine # class BarController - # main_app.foo_path #=> /foo + # def index + # main_app.foo_path #=> /foo + # end # end # end # - # Note that :as option takes engine_name as default, so most of the time you can ommit it. - # - # If you want to generate url to engine's route using polymorphic_url, you can also use that helpers. + # Note that the :as option given to mount takes the engine_name as default, so most of the time + # you can simply ommit it. # - # Let's say that you want to create a form pointing to one of the engine's routes. All you need to do - # is passing helper as the first element in array with attributes for url: + # Finally, if you want to generate url to engine's route using polymorphic_url, you also need + # to pass the engine helper. Let's say that you want to create a form pointing to one of the + # engine's routes. All you need to do is pass the helper as the first element in array with + # attributes for url: # # form_for([my_engine, @user]) # - # This code will use my_engine.user_path(@user) to generate proper route. + # This code will use my_engine.user_path(@user) to generate the proper route. # # == Migrations & seed data # @@ -303,7 +315,7 @@ module Rails # To use engine's migrations in application you can use rake task, which copies them to # application's dir: # - # rake railties:copy_migrations + # rake ENGINE_NAME:install:migrations # # If your engine has migrations, you may also want to prepare data for the database in # seeds.rb file. You can load that data using load_seed method, e.g. @@ -527,6 +539,8 @@ module Rails namespace railtie_name do namespace :install do + # TODO Add assets copying to this list + # TODO Skip this if there is no paths["db/migrate"] for the engine desc "Copy migrations from #{railtie_name} to application" task :migrations do ENV["FROM"] = railtie_name diff --git a/railties/lib/rails/tasks/railties.rake b/railties/lib/rails/tasks/railties.rake index 0c1ee0f17a..e08bd9687d 100644 --- a/railties/lib/rails/tasks/railties.rake +++ b/railties/lib/rails/tasks/railties.rake @@ -1,5 +1,5 @@ namespace :railties do - desc "Create symlinks to railties public directories in application's public directory." + # desc "Create symlinks to railties public directories in application's public directory." task :create_symlinks => :environment do paths = Rails.application.config.static_asset_paths.dup app_public_path = Rails.application.paths["public"].first -- cgit v1.2.3 From e6b45b8111cc375be57a1e1ca2b2b47eb21a2e01 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Mon, 11 Oct 2010 12:00:37 +0200 Subject: Revert "Add missing CHANGELOG entry about reset_javascript_include_default" This reverts commit 234a4ca7ddb7794a92f266af48fd38edbdb03003. Reason: No big deal Ryan, only there's a very strict policy in docrails which allows public write access on the other hand. CHANGELOGs can only be edited in master. If this is added I'll make sure you get the credit for the patch. --- actionpack/CHANGELOG | 2 -- 1 file changed, 2 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 966d1ae47d..6352b97a6b 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -33,8 +33,6 @@ * Upgrade to Rack 1.2.1 [Jeremy Kemper] -* Removed reset_javascript_include_default, use config.action_view.javascript_expansions in config/application.rb for this instead [José Valim] - * Allow :path to be given to match/get/post/put/delete instead of :path_names in the new router [Carlos Antônio da Silva] * Added resources_path_names to the new router DSL [José Valim] -- cgit v1.2.3 From 0744d36f479ad35a89a50efaadb66674cac0a323 Mon Sep 17 00:00:00 2001 From: Krekoten' Marjan Date: Tue, 12 Oct 2010 22:55:19 +0300 Subject: Fix small typo in documentation --- actionpack/lib/action_controller/metal/conditional_get.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 8930c13a68..a5e37172c9 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -66,7 +66,7 @@ module ActionController # Examples: # expires_in 20.minutes # expires_in 3.hours, :public => true - # expires in 3.hours, 'max-stale' => 5.hours, :public => true + # expires_in 3.hours, 'max-stale' => 5.hours, :public => true # # This method will overwrite an existing Cache-Control header. # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. -- cgit v1.2.3 From a0b53b25b6dc422bf29d2879a8f1a53b9983ac77 Mon Sep 17 00:00:00 2001 From: Aditya Sanghi Date: Wed, 13 Oct 2010 01:39:22 +0530 Subject: fix time.to_formatted_time(:time) example --- activesupport/lib/active_support/core_ext/time/conversions.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb index 025c619783..d4ae3131ec 100644 --- a/activesupport/lib/active_support/core_ext/time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/time/conversions.rb @@ -19,8 +19,8 @@ class Time # # time = Time.now # => Thu Jan 18 06:10:17 CST 2007 # - # time.to_formatted_s(:time) # => "06:10:17" - # time.to_s(:time) # => "06:10:17" + # time.to_formatted_s(:time) # => "06:10" + # time.to_s(:time) # => "06:10" # # time.to_formatted_s(:db) # => "2007-01-18 06:10:17" # time.to_formatted_s(:number) # => "20070118061017" -- cgit v1.2.3 From aec5ef243a0c85a9e3bafa89ce873d3837a6ce59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 13 Oct 2010 15:59:57 -0300 Subject: Remove doc for debugging callbacks. Methods don't exist in Rails master --- activerecord/lib/active_record/callbacks.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 49671a1042..47428cfd0f 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -218,16 +218,6 @@ module ActiveRecord # needs to be aware of it because an ordinary +save+ will raise such exception # instead of quietly returning +false+. # - # == Debugging callbacks - # - # To list the methods and procs registered with a particular callback, append _callback_chain to - # the callback name that you wish to list and send that to your class from the Rails console: - # - # >> Topic.after_save_callback_chain - # => [#, kind:after_save, identifiernil, - # options{}] - # module Callbacks extend ActiveSupport::Concern -- cgit v1.2.3 From a37e1a6a692cd2cc82b9b885f2a289d28bc35a33 Mon Sep 17 00:00:00 2001 From: Ugis Ozols Date: Wed, 13 Oct 2010 23:31:37 +0300 Subject: Removed miscelenous letters. --- railties/guides/source/command_line.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile index cbdfda9215..752b5926f7 100644 --- a/railties/guides/source/command_line.textile +++ b/railties/guides/source/command_line.textile @@ -145,7 +145,7 @@ $ rails generate controller Greetings hello What all did this generate? It made sure a bunch of directories were in our application, and created a controller file, a functional test file, a helper for the view, and a view file. -Check out the controller and modify it a little (in +app/controllers/greetings_controller.rb+):ma +Check out the controller and modify it a little (in +app/controllers/greetings_controller.rb+): class GreetingsController < ApplicationController -- cgit v1.2.3 From cfb1ba023b11f82d776f9744ddbe7c826c8d7fbc Mon Sep 17 00:00:00 2001 From: Ryan Bigg and Xavier Noria Date: Thu, 14 Oct 2010 08:12:25 +1100 Subject: Use rather than underscores to fix display issue with 4.1.1.1 in the asssociation basics guide --- railties/guides/source/association_basics.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile index 6996dab8c5..f6d61373e1 100644 --- a/railties/guides/source/association_basics.textile +++ b/railties/guides/source/association_basics.textile @@ -550,7 +550,7 @@ build_customer create_customer -h6(#belongs_to-association). _association_(force_reload = false) +h6(#belongs_to-association). association(force_reload = false) The association method returns the associated object, if any. If no associated object is found, it returns +nil+. -- cgit v1.2.3 From a18cefbc3a9a025a076a0f5e18f6b9991e7df8e3 Mon Sep 17 00:00:00 2001 From: Nick Quaranto Date: Thu, 14 Oct 2010 17:24:59 -0400 Subject: Fixing a small typo in the generators guide --- railties/guides/source/generators.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index b1f8ea29da..0f2cbb76dc 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -144,7 +144,7 @@ generators/initializer_generator.rb If none is found you get an error message. -INFO: The examples above put files under the application's +lib+ because said directoty belongs to +$LOAD_PATH+. +INFO: The examples above put files under the application's +lib+ because said directory belongs to +$LOAD_PATH+. h3. Customizing Your Workflow -- cgit v1.2.3 From 8be96a3bcf1a21bac38437512cac10ac9c1f952f Mon Sep 17 00:00:00 2001 From: Neil Middleton Date: Thu, 14 Oct 2010 23:11:34 +0100 Subject: Fixed casing of JavaScript (and RJS) [#183 state:resolved] --- railties/guides/source/layouts_and_rendering.textile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index 50c5986a64..088e1f817c 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -90,7 +90,7 @@ If we want to display the properties of all the books in our view, we can do so <%= link_to 'New book', new_book_path %> -NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), +.rjs+ for RJS (javascript with embedded ruby) and +.builder+ for Builder (XML generator). +NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), +.rjs+ for RJS (JavaScript with embedded ruby) and +.builder+ for Builder (XML generator). h4. Using +render+ @@ -252,7 +252,7 @@ render :inline => h5. Using +render+ with +:update+ -You can also render javascript-based page updates inline using the +:update+ option to +render+: +You can also render JavaScript-based page updates inline using the +:update+ option to +render+: render :update do |page| @@ -260,7 +260,7 @@ render :update do |page| end -WARNING: Placing javascript updates in your controller may seem to streamline small updates, but it defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. We recommend using a separate rjs template instead, no matter how small the update. +WARNING: Placing JavaScript updates in your controller may seem to streamline small updates, but it defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. We recommend using a separate RJS template instead, no matter how small the update. h5. Rendering Text @@ -276,7 +276,7 @@ NOTE: By default, if you use the +:text+ option, the text is rendered without us h5. Rendering JSON -JSON is a javascript data format used by many AJAX libraries. Rails has built-in support for converting objects to JSON and rendering that JSON back to the browser: +JSON is a JavaScript data format used by many AJAX libraries. Rails has built-in support for converting objects to JSON and rendering that JSON back to the browser: render :json => @product @@ -655,7 +655,7 @@ I'll discuss each of these in turn. h4. Asset Tags -Asset tags provide methods for generating HTML that links views to assets like images, videos, audio, javascript, stylesheets, and feeds. There are six types of include tag: +Asset tags provide methods for generating HTML that links views to assets like images, videos, audio, JavaScript, stylesheets, and feeds. There are six types of include tag: * +auto_discovery_link_tag+ * +javascript_include_tag+ @@ -715,7 +715,7 @@ The +defaults+ option loads the Prototype and Scriptaculous libraries: <%= javascript_include_tag :defaults %> -The +all+ option loads every javascript file in +public/javascripts+, starting with the Prototype and Scriptaculous libraries: +The +all+ option loads every JavaScript file in +public/javascripts+, starting with the Prototype and Scriptaculous libraries: <%= javascript_include_tag :all %> @@ -727,7 +727,7 @@ You can supply the +:recursive+ option to load files in subfolders of +public/ja <%= javascript_include_tag :all, :recursive => true %> -If you're loading multiple javascript files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify +:cache => true+ in your +javascript_include_tag+: +If you're loading multiple JavaScript files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify +:cache => true+ in your +javascript_include_tag+: <%= javascript_include_tag "main", "columns", :cache => true %> @@ -962,7 +962,7 @@ The result of rendering this page into the supplied layout would be this HTML: -The +content_for+ method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It's also useful for inserting tags that load page-specific javascript or css files into the header of an otherwise generic layout. +The +content_for+ method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It's also useful for inserting tags that load page-specific JavaScript or css files into the header of an otherwise generic layout. h4. Using Partials -- cgit v1.2.3 From ebe61bf37c174a98019225d4aa227c6d45e69a59 Mon Sep 17 00:00:00 2001 From: Rob Zolkos Date: Fri, 15 Oct 2010 21:40:32 +1100 Subject: WEBrick is the default web server, not Mongrel [#186 state:resolved] --- railties/guides/source/getting_started.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 42b3313752..3f433c9704 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -282,7 +282,7 @@ You actually have a functional Rails application already. To see it, you need to $ rails server -This will fire up an instance of the Mongrel web server by default (Rails can also use several other web servers). To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see Rails' default information page: +This will fire up an instance of the WEBrick web server by default (Rails can also use several other web servers). To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see Rails' default information page: !images/rails_welcome.png(Welcome Aboard screenshot)! -- cgit v1.2.3 From cffae06a4f1b7aac86a7e99cfb244890f837f976 Mon Sep 17 00:00:00 2001 From: Rob Zolkos Date: Fri, 15 Oct 2010 23:38:31 +1100 Subject: remove Mongrel from debugger docs --- railties/guides/source/debugging_rails_applications.textile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile index 35069f33ad..b9d45fb13a 100644 --- a/railties/guides/source/debugging_rails_applications.textile +++ b/railties/guides/source/debugging_rails_applications.textile @@ -250,7 +250,7 @@ Make sure you have started your web server with the option +--debugger+: ~/PathTo/rails_project$ rails server --debugger -=> Booting Mongrel (use 'rails server webrick' to force WEBrick) +=> Booting WEBrick => Rails 3.0.0 application starting on http://0.0.0.0:3000 => Debugger enabled ... @@ -258,8 +258,6 @@ Make sure you have started your web server with the option +--debugger+: TIP: In development mode, you can dynamically +require \'ruby-debug\'+ instead of restarting the server, if it was started without +--debugger+. -In order to use Rails debugging you'll need to be running either *WEBrick* or *Mongrel*. For the moment, no alternative servers are supported. - h4. The Shell As soon as your application calls the +debugger+ method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at ruby-debug's prompt +(rdb:n)+. The _n_ is the thread number. The prompt will also show you the next line of code that is waiting to run. -- cgit v1.2.3