has_scope 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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