has_scope 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,7 @@ Now, if you want to apply them to an specific resource, you just need to call <t
20
20
  class GraduationsController < ApplicationController
21
21
  has_scope :featured, :type => :boolean
22
22
  has_scope :by_degree
23
+ has_scope :by_period, :using => [:started_at, :ended_at]
23
24
 
24
25
  def index
25
26
  @graduations = apply_scopes(Graduation).all
@@ -37,6 +38,9 @@ Then for each request:
37
38
  /graduations?featured=true&by_degree=phd
38
39
  #=> brings featured graduations with phd degree
39
40
 
41
+ /graduations?params[by_period][started_at]=20100701&params[by_period][ended_at]=20101013
42
+ #=> brings graduations in the given period
43
+
40
44
  You can retrieve all the scopes applied in one action with <tt>current_scopes</tt> method.
41
45
  In the last case, it would return: { :featured => true, :by_degree => "phd" }.
42
46
 
@@ -62,6 +66,8 @@ HasScope supports several options:
62
66
 
63
67
  * <tt>:as</tt> - The key in the params hash expected to find the scope. Defaults to the scope name.
64
68
 
69
+ * <tt>:using</tt> - The subkeys to be used as args when type is a hash.
70
+
65
71
  * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the scope should apply.
66
72
 
67
73
  * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the scope should NOT apply.
data/Rakefile CHANGED
@@ -27,7 +27,7 @@ begin
27
27
  require 'jeweler'
28
28
  Jeweler::Tasks.new do |s|
29
29
  s.name = "has_scope"
30
- s.version = "0.4.2"
30
+ s.version = "0.5.0"
31
31
  s.summary = "Maps controller filters to your resource scopes"
32
32
  s.email = "contact@plataformatec.com.br"
33
33
  s.homepage = "http://github.com/plataformatec/has_scope"
@@ -33,6 +33,9 @@ module HasScope
33
33
  # * <tt>:as</tt> - The key in the params hash expected to find the scope.
34
34
  # Defaults to the scope name.
35
35
  #
36
+ # * <tt>:using</tt> - If type is a hash, you can provide :using to convert the hash to
37
+ # a named scope call with several arguments.
38
+ #
36
39
  # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
37
40
  # if the scope should apply
38
41
  #
@@ -61,7 +64,17 @@ module HasScope
61
64
  def has_scope(*scopes, &block)
62
65
  options = scopes.extract_options!
63
66
  options.symbolize_keys!
64
- options.assert_valid_keys(:type, :only, :except, :if, :unless, :default, :as, :allow_blank)
67
+ options.assert_valid_keys(:type, :only, :except, :if, :unless, :default, :as, :using, :allow_blank)
68
+
69
+ if options.key?(:using)
70
+ if options.key?(:type) && options[:type] != :hash
71
+ raise "You cannot use :using with another :type different than :hash"
72
+ else
73
+ options[:type] = :hash
74
+ end
75
+
76
+ options[:using] = Array(options[:using])
77
+ end
65
78
 
66
79
  options[:only] = Array(options[:only])
67
80
  options[:except] = Array(options[:except])
@@ -80,7 +93,7 @@ module HasScope
80
93
  # Receives an object where scopes will be applied to.
81
94
  #
82
95
  # class GraduationsController < InheritedResources::Base
83
- # has_scope :featured, :boolean => true, :only => :index
96
+ # has_scope :featured, :type => true, :only => :index
84
97
  # has_scope :by_degree, :only => :index
85
98
  #
86
99
  # def index
@@ -88,23 +101,25 @@ module HasScope
88
101
  # end
89
102
  # end
90
103
  #
91
- def apply_scopes(target)
104
+ def apply_scopes(target, hash=params)
92
105
  return target unless scopes_configuration
93
106
 
94
107
  self.scopes_configuration.each do |scope, options|
95
108
  next unless apply_scope_to_action?(options)
96
109
  key = options[:as]
97
110
 
98
- if params.key?(key)
99
- value, call_scope = params[key], true
111
+ if hash.key?(key)
112
+ value, call_scope = hash[key], true
100
113
  elsif options.key?(:default)
101
114
  value, call_scope = options[:default], true
102
115
  value = value.call(self) if value.is_a?(Proc)
103
116
  end
104
117
 
118
+ value = parse_value(options[:type], key, value)
119
+
105
120
  if call_scope && (value.present? || options[:allow_blank])
106
- set_current_scope(options[:type], key, value)
107
- target = apply_scope_by_type(options[:type], scope, target, current_scopes[key], options[:block])
121
+ current_scopes[key] = value
122
+ target = call_scope_by_type(options[:type], scope, target, value, options)
108
123
  end
109
124
  end
110
125
 
@@ -112,24 +127,25 @@ module HasScope
112
127
  end
113
128
 
114
129
  # Set the real value for the current scope if type check.
115
- def set_current_scope(type, key, value) #:nodoc:
130
+ def parse_value(type, key, value) #:nodoc:
116
131
  if type == :boolean
117
- current_scopes[key] = TRUE_VALUES.include?(value)
118
- elsif ALLOWED_TYPES[type].none?{ |klass| value.is_a?(klass) }
132
+ TRUE_VALUES.include?(value)
133
+ elsif value && ALLOWED_TYPES[type].none?{ |klass| value.is_a?(klass) }
119
134
  raise "Expected type :#{type} in params[:#{key}], got #{value.class}"
120
135
  else
121
- current_scopes[key] = value
136
+ value
122
137
  end
123
138
  end
124
139
 
125
- # Apply the scope taking into account its type.
126
- def apply_scope_by_type(type, scope, target, value, block) #:nodoc:
140
+ # Call the scope taking into account its type.
141
+ def call_scope_by_type(type, scope, target, value, options) #:nodoc:
142
+ block = options[:block]
143
+
127
144
  if type == :boolean
128
- if value
129
- block ? block.call(self, target) : target.send(scope)
130
- else
131
- target
132
- end
145
+ block ? block.call(self, target) : target.send(scope)
146
+ elsif value && options.key?(:using)
147
+ value = value.values_at(*options[:using])
148
+ block ? block.call(self, target, value) : target.send(scope, *value)
133
149
  else
134
150
  block ? block.call(self, target, value) : target.send(scope, value)
135
151
  end
@@ -10,6 +10,7 @@ class TreesController < ApplicationController
10
10
  has_scope :root_type, :as => :root, :allow_blank => true
11
11
  has_scope :calculate_height, :default => proc {|c| c.session[:height] || 20 }, :only => :new
12
12
  has_scope :paginate, :type => :hash
13
+ has_scope :args_paginate, :type => :hash, :using => [:page, :per_page]
13
14
  has_scope :categories, :type => :array
14
15
 
15
16
  has_scope :only_short, :type => :boolean do |controller, scope|
@@ -63,7 +64,7 @@ class HasScopeTest < ActionController::TestCase
63
64
  Tree.expects(:all).returns([mock_tree])
64
65
  get :index, :only_tall => 'false'
65
66
  assert_equal([mock_tree], assigns(:trees))
66
- assert_equal({ :only_tall => false }, current_scopes)
67
+ assert_equal({}, current_scopes)
67
68
  end
68
69
 
69
70
  def test_scope_is_called_only_on_index
@@ -134,7 +135,7 @@ class HasScopeTest < ActionController::TestCase
134
135
  end
135
136
 
136
137
  def test_scope_of_type_hash
137
- hash = { "page" => "1", "per_page" => "1" }
138
+ hash = { "page" => "1", "per_page" => "10" }
138
139
  Tree.expects(:paginate).with(hash).returns(Tree)
139
140
  Tree.expects(:all).returns([mock_tree])
140
141
  get :index, :paginate => hash
@@ -142,6 +143,15 @@ class HasScopeTest < ActionController::TestCase
142
143
  assert_equal({ :paginate => hash }, current_scopes)
143
144
  end
144
145
 
146
+ def test_scope_of_type_hash_with_using
147
+ hash = { "page" => "1", "per_page" => "10" }
148
+ Tree.expects(:args_paginate).with("1", "10").returns(Tree)
149
+ Tree.expects(:all).returns([mock_tree])
150
+ get :index, :args_paginate => hash
151
+ assert_equal([mock_tree], assigns(:trees))
152
+ assert_equal({ :args_paginate => hash }, current_scopes)
153
+ end
154
+
145
155
  def test_scope_of_type_array
146
156
  array = %w(book kitchen sport)
147
157
  Tree.expects(:categories).with(array).returns(Tree)
@@ -19,14 +19,21 @@ RAILS_ROOT = "anywhere"
19
19
 
20
20
  require 'active_support'
21
21
  require 'action_controller'
22
- require 'action_controller/test_case'
23
- require 'action_controller/test_process'
22
+ require 'action_dispatch/middleware/flash'
24
23
 
25
24
  class ApplicationController < ActionController::Base; end
26
25
 
27
26
  $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
28
27
  require 'has_scope'
29
28
 
30
- ActionController::Routing::Routes.draw do |map|
29
+ HasScope::Router = ActionDispatch::Routing::RouteSet.new
30
+ HasScope::Router.draw do |map|
31
31
  map.connect ':controller/:action/:id'
32
- end
32
+ map.connect ':controller/:action'
33
+ end
34
+
35
+ class ActiveSupport::TestCase
36
+ setup do
37
+ @router = HasScope::Router
38
+ end
39
+ end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_scope
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ - 0
9
+ version: 0.5.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - "Jos\xC3\xA9 Valim"
@@ -9,7 +14,7 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-02-05 00:00:00 +01:00
17
+ date: 2010-03-23 00:00:00 +01:00
13
18
  default_executable:
14
19
  dependencies: []
15
20
 
@@ -40,18 +45,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
40
45
  requirements:
41
46
  - - ">="
42
47
  - !ruby/object:Gem::Version
48
+ segments:
49
+ - 0
43
50
  version: "0"
44
- version:
45
51
  required_rubygems_version: !ruby/object:Gem::Requirement
46
52
  requirements:
47
53
  - - ">="
48
54
  - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
49
57
  version: "0"
50
- version:
51
58
  requirements: []
52
59
 
53
60
  rubyforge_project:
54
- rubygems_version: 1.3.5
61
+ rubygems_version: 1.3.6
55
62
  signing_key:
56
63
  specification_version: 3
57
64
  summary: Maps controller filters to your resource scopes