diff options
4 files changed, 31 insertions, 15 deletions
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 947391b725..d869b62398 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -90,17 +90,21 @@ module ActionDispatch def initialize @routes = {} - @helpers = [] + @helpers = Set.new @module = Module.new end + def route_defined?(name) + @helpers.include? name.to_sym + end + def helper_names @helpers.map(&:to_s) end def clear! @helpers.each do |helper| - @module.remove_possible_method helper + @module.send :undef_method, helper end @routes.clear @@ -108,8 +112,12 @@ module ActionDispatch end def add(name, route) - routes[name.to_sym] = route - define_named_route_methods(name, route) + key = name.to_sym + if routes.key? key + undef_named_route_methods @module, name + end + routes[key] = route + define_named_route_methods(@module, name, route) end def get(name) @@ -253,11 +261,10 @@ module ActionDispatch # # foo_url(bar, baz, bang, sort_by: 'baz') # - def define_url_helper(route, name, opts, route_key, url_strategy) + def define_url_helper(mod, route, name, opts, route_key, url_strategy) helper = UrlHelper.create(route, opts, route_key, url_strategy) - @module.remove_possible_method name - @module.module_eval do + mod.module_eval do define_method(name) do |*args| options = nil options = args.pop if args.last.is_a? Hash @@ -268,9 +275,14 @@ module ActionDispatch helpers << name end - def define_named_route_methods(name, route) - define_url_helper route, :"#{name}_path", route.defaults, name, PATH - define_url_helper route, :"#{name}_url", route.defaults, name, FULL + def define_named_route_methods(mod, name, route) + define_url_helper mod, route, :"#{name}_path", route.defaults, name, PATH + define_url_helper mod, route, :"#{name}_url", route.defaults, name, FULL + end + + def undef_named_route_methods(mod, name) + mod.send :undef_method, :"#{name}_path" + mod.send :undef_method, :"#{name}_url" end end @@ -334,6 +346,7 @@ module ActionDispatch mapper.instance_exec(&block) end end + private :eval_block def finalize! return if @finalized @@ -400,14 +413,16 @@ module ActionDispatch def url_options; {}; end end + route_methods = routes.named_routes.module + # Make named_routes available in the module singleton # as well, so one can do: # Rails.application.routes.url_helpers.posts_path - extend routes.named_routes.module + extend route_methods # Any class that includes this module will get all # named routes... - include routes.named_routes.module + include route_methods # plus a singleton class method called _routes ... included do diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index f1f998d932..2cf38a9c2d 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -165,7 +165,7 @@ module ActionDispatch # ROUTES TODO: These assertions should really work in an integration context def method_missing(selector, *args, &block) - if defined?(@controller) && @controller && @routes && @routes.named_routes.helpers.include?(selector) + if defined?(@controller) && @controller && @routes && @routes.named_routes.route_defined?(selector) @controller.send(selector, *args, &block) else super diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 3a266512a9..33cc22425d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -72,7 +72,7 @@ module ActiveRecord end class TransactionState - attr_accessor :parent + attr_reader :parent VALID_STATES = Set.new([:committed, :rolledback, nil]) @@ -245,7 +245,6 @@ module ActiveRecord def perform_commit @state.set_state(:committed) - @state.parent = parent.state connection.release_savepoint(@savepoint_name) end end diff --git a/guides/source/routing.md b/guides/source/routing.md index 7a7334f25b..af8c1bbcc4 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -645,6 +645,8 @@ match 'photos', to: 'photos#show', via: :all NOTE: Routing both `GET` and `POST` requests to a single action has security implications. In general, you should avoid routing all verbs to an action unless you have a good reason to. +NOTE: 'GET' in Rails won't check for CSRF token. You should never write to the database from 'GET' requests, for more information see the [security guide](security.html#csrf-countermeasures) on CSRF countermeasures. + ### Segment Constraints You can use the `:constraints` option to enforce a format for a dynamic segment: |