Changeset 5268
- Timestamp:
- 10/09/06 06:11:40 (2 years ago)
- Files:
-
- trunk/actionpack/CHANGELOG (modified) (1 diff)
- trunk/actionpack/lib/action_controller/filters.rb (modified) (8 diffs)
- trunk/actionpack/test/controller/filters_test.rb (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/actionpack/CHANGELOG
r5253 r5268 1 1 *SVN* 2 3 * Fix filter skipping in controller subclasses. #5949, #6297, #6299 [Martin Emde] 2 4 3 5 * render_text may optionally append to the response body. render_javascript appends by default. This allows you to chain multiple render :update calls by setting @performed_render = false between them (awaiting a better public API). [Jeremy Kemper] trunk/actionpack/lib/action_controller/filters.rb
r5196 r5268 363 363 # Returns a mapping between filters and the actions that may run them. 364 364 def included_actions #:nodoc: 365 filter_chain.inject({}) { |h,f| h[f.filter] = f.included_actions; h}365 read_inheritable_attribute("included_actions") || {} 366 366 end 367 367 368 368 # Returns a mapping between filters and actions that may not run them. 369 369 def excluded_actions #:nodoc: 370 filter_chain.inject({}) { |h,f| h[f.filter] = f.excluded_actions; h}370 read_inheritable_attribute("excluded_actions") || {} 371 371 end 372 372 … … 378 378 def find_filter(filter, &block) #:nodoc: 379 379 filter_chain.select { |f| f.filter == filter && (!block_given? || yield(f)) }.first 380 end 381 382 # Returns true if the filter is excluded from the given action 383 def filter_excluded_from_action?(filter,action) #:nodoc: 384 if (ia = included_actions[filter]) && !ia.empty? 385 !ia.include?(action) 386 else 387 (excluded_actions[filter] || []).include?(action) 388 end 380 389 end 381 390 … … 385 394 attr_reader :filter, :included_actions, :excluded_actions 386 395 387 def initialize(filter , options={})396 def initialize(filter) 388 397 @filter = filter 389 @position = options[:position]390 update_conditions(options)391 end392 393 def update_conditions(conditions)394 if conditions[:only]395 @included_actions = [conditions[:only]].flatten.map(&:to_s)396 else397 @excluded_actions = [conditions[:except]].flatten.compact.map(&:to_s)398 end399 build_excluded_actions_hash400 end401 402 def remove_actions_from_included_actions!(*actions)403 if @included_actions404 actions.flatten.map(&:to_s).each { |action| @included_actions.delete(action) }405 build_excluded_actions_hash406 end407 398 end 408 399 … … 415 406 end 416 407 417 def excluded_from?(action)418 @excluded_actions_hash[action]419 end420 421 408 def call(controller, &block) 422 409 raise(ActionControllerError, 'No filter type: Nothing to do here.') 423 end424 425 private426 def build_excluded_actions_hash427 @excluded_actions_hash =428 if @included_actions429 @included_actions.inject(Hash.new(true)){|h, a| h[a] = false; h}430 else431 @excluded_actions.inject(Hash.new(false)){|h, a| h[a] = true; h}432 end433 410 end 434 411 end … … 512 489 def create_filters(filters, position, &block) #:nodoc: 513 490 filters, conditions = extract_conditions(filters, &block) 514 conditions.merge!(:position => position) 515 516 # conditions should be blank for a filter behind a filter proxy since the proxy will take care of all conditions. 517 proxy_conditions, conditions = conditions, {} unless :around == position 518 519 filters.map do |filter| 491 492 filters.map! do |filter| 520 493 # change all the filters into instances of Filter derived classes 521 class_for_filter(filter).new(filter, conditions) 522 end.collect do |filter| 494 class_for_filter(filter).new(filter) 495 end 496 497 filters.map! do |filter| 523 498 # apply proxy to filter if necessary 524 499 case position 525 500 when :before 526 BeforeFilterProxy.new(filter , proxy_conditions)501 BeforeFilterProxy.new(filter) 527 502 when :after 528 AfterFilterProxy.new(filter , proxy_conditions)503 AfterFilterProxy.new(filter) 529 504 else 530 505 filter 531 506 end 532 507 end 508 509 update_conditions(filters, conditions) 510 511 filters 533 512 end 534 513 … … 554 533 end 555 534 535 def extract_conditions(*filters, &block) #:nodoc: 536 filters.flatten! 537 conditions = filters.last.is_a?(Hash) ? filters.pop : {} 538 filters << block if block_given? 539 return filters, conditions 540 end 541 542 def update_conditions(filters, conditions) 543 return if conditions.empty? 544 if conditions[:only] 545 write_inheritable_hash('included_actions', condition_hash(filters, conditions[:only])) 546 else 547 write_inheritable_hash('excluded_actions', condition_hash(filters, conditions[:except])) if conditions[:except] 548 end 549 end 550 551 def condition_hash(filters, *actions) 552 actions = actions.flatten.map(&:to_s) 553 filters.inject({}) { |h,f| h.update( f => (actions.blank? ? nil : actions)) } 554 end 555 556 def skip_filter_in_chain(*filters, &test) #:nodoc: 557 filters, conditions = extract_conditions(filters) 558 filters.map! { |f| block_given? ? find_filter(f, &test) : find_filter(f) } 559 filters.compact! 560 561 if conditions.empty? 562 delete_filters_in_chain(filters) 563 else 564 remove_actions_from_included_actions!(filters,conditions[:only] || []) 565 conditions[:only], conditions[:except] = conditions[:except], conditions[:only] 566 update_conditions(filters,conditions) 567 end 568 end 569 570 def remove_actions_from_included_actions!(filters,*actions) 571 actions = actions.flatten.map(&:to_s) 572 updated_hash = filters.inject(included_actions) do |hash,filter| 573 ia = (hash[filter] || []) - actions 574 ia.blank? ? hash.delete(filter) : hash[filter] = ia 575 hash 576 end 577 write_inheritable_attribute('included_actions', updated_hash) 578 end 579 580 def delete_filters_in_chain(filters) #:nodoc: 581 write_inheritable_attribute('filter_chain', filter_chain.reject { |f| filters.include?(f) }) 582 end 583 556 584 def filter_responds_to_before_and_after(filter) #:nodoc: 557 585 filter.respond_to?(:before) && filter.respond_to?(:after) … … 570 598 end 571 599 end 572 573 def extract_conditions(*filters, &block) #:nodoc:574 filters.flatten!575 conditions = filters.last.is_a?(Hash) ? filters.pop : {}576 filters << block if block_given?577 return filters.flatten, conditions578 end579 580 def skip_filter_in_chain(*filters, &test) #:nodoc:581 filters, conditions = extract_conditions(filters)582 finder_proc = block_given? ?583 proc { |f| find_filter(f, &test) } :584 proc { |f| find_filter(f) }585 586 filters.map(&finder_proc).reject(&:nil?).each do |filter|587 if conditions.empty?588 delete_filter_in_chain(filter)589 else590 filter.remove_actions_from_included_actions!(conditions[:only] || [])591 conditions[:only], conditions[:except] = conditions[:except], conditions[:only]592 filter.update_conditions(conditions)593 end594 end595 end596 597 def delete_filter_in_chain(filter) #:nodoc:598 write_inheritable_attribute('filter_chain', filter_chain.reject { |f| f == filter })599 end600 600 end 601 601 … … 628 628 return (performed? || perform_action_without_filters) if index >= chain.size 629 629 filter = chain[index] 630 return call_filter(chain, index.next) if filter.excluded_from?(action_name)630 return call_filter(chain, index.next) if self.class.filter_excluded_from_action?(filter,action_name) 631 631 632 632 halted = false trunk/actionpack/test/controller/filters_test.rb
r5196 r5268 155 155 end 156 156 end 157 157 158 158 class ConditionalParentOfConditionalSkippingController < ConditionalFilterController 159 159 before_filter :conditional_in_parent, :only => [:show, :another_action] … … 171 171 skip_before_filter :conditional_in_parent, :only => :another_action 172 172 skip_after_filter :conditional_in_parent, :only => :another_action 173 end 174 175 class AnotherChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController 176 skip_before_filter :conditional_in_parent, :only => :show 173 177 end 174 178 … … 414 418 end 415 419 420 def test_condition_skipping_of_filters_when_siblings_also_have_conditions 421 assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'], "1" 422 assert_equal nil, test_process(AnotherChildOfConditionalParentController).template.assigns['ran_filter'] 423 assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'] 424 end 425 416 426 private 417 427 def test_process(controller, action = "show")