has_scope 0.7.2 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b023c16c60cb24ca941d55d69be48713962b661a68b92f32a0af40bf952686ea
4
- data.tar.gz: 45b61de129e41764aa08bbcbd17c1287a83542d2171cc69ad8452a6da4f22085
3
+ metadata.gz: c24a5ed875375fb5da93be3f90ac863b0c72d676ecc1fe0959933924452b043d
4
+ data.tar.gz: 2f8aacdef384ce75c7fc2e4b4b697ba62e68293deeac5754597d10dffc044052
5
5
  SHA512:
6
- metadata.gz: 35392817be681d709e897972514b215be8860f2b00216745cba37931c77aa27dbf1fc13f56b1cbc775210c266de902b4a79023a8637b8736089669543ee73b9e
7
- data.tar.gz: 8ce1d74c2cfb9a76d4c7a60752aee0d86ede19ba778f7e28983eb77b446162d60091ee7ff3437025b0c841bb75e7f34de8dc4fddfdbd99331dd66707d28b7af5
6
+ metadata.gz: 9541480b36218fb3c1b9b7c48a3297411c8875ec47bb1735b6b394127c02ad90010d79787931c0d0154d662b40f4c236627710ca7b2fa01edb7513f27e043fb9
7
+ data.tar.gz: 5927fbd54e4a019b2d9f9fd7f7a60cf929fd46eac8f15c4c0e8cdb0cab2cac80a2b432e4398a70013d6bf88a519df60d2b6f571fb4f7f5db2d141292762b9eba
data/README.md CHANGED
@@ -1,16 +1,15 @@
1
1
  ## HasScope
2
2
 
3
3
  [![Gem Version](https://fury-badge.herokuapp.com/rb/has_scope.svg)](http://badge.fury.io/rb/has_scope)
4
- [![Build Status](https://api.travis-ci.org/plataformatec/has_scope.svg?branch=master)](http://travis-ci.org/plataformatec/has_scope)
5
- [![Code Climate](https://codeclimate.com/github/plataformatec/has_scope.svg)](https://codeclimate.com/github/plataformatec/has_scope)
4
+ [![Code Climate](https://codeclimate.com/github/heartcombo/has_scope.svg)](https://codeclimate.com/github/heartcombo/has_scope)
6
5
 
7
6
  Has scope allows you to map incoming controller parameters to named scopes in your resources.
8
7
  Imagine the following model called graduations:
9
8
 
10
9
  ```ruby
11
10
  class Graduation < ActiveRecord::Base
12
- scope :featured, -> { where(:featured => true) }
13
- scope :by_degree, -> degree { where(:degree => degree) }
11
+ scope :featured, -> { where(featured: true) }
12
+ scope :by_degree, -> degree { where(degree: degree) }
14
13
  scope :by_period, -> started_at, ended_at { where("started_at = ? AND ended_at = ?", started_at, ended_at) }
15
14
  end
16
15
  ```
@@ -19,7 +18,7 @@ You can use those named scopes as filters by declaring them on your controller:
19
18
 
20
19
  ```ruby
21
20
  class GraduationsController < ApplicationController
22
- has_scope :featured, :type => :boolean
21
+ has_scope :featured, type: :boolean
23
22
  has_scope :by_degree
24
23
  end
25
24
  ```
@@ -28,9 +27,9 @@ Now, if you want to apply them to an specific resource, you just need to call `a
28
27
 
29
28
  ```ruby
30
29
  class GraduationsController < ApplicationController
31
- has_scope :featured, :type => :boolean
30
+ has_scope :featured, type: :boolean
32
31
  has_scope :by_degree
33
- has_scope :by_period, :using => [:started_at, :ended_at], :type => :hash
32
+ has_scope :by_period, using: %i[started_at ended_at], type: :hash
34
33
 
35
34
  def index
36
35
  @graduations = apply_scopes(Graduation).all
@@ -55,7 +54,7 @@ Then for each request:
55
54
  ```
56
55
 
57
56
  You can retrieve all the scopes applied in one action with `current_scopes` method.
58
- In the last case, it would return: { :featured => true, :by_degree => "phd" }.
57
+ In the last case, it would return: `{ featured: true, by_degree: 'phd' }`.
59
58
 
60
59
  ## Installation
61
60
 
@@ -83,23 +82,23 @@ HasScope supports several options:
83
82
 
84
83
  * `:using` - The subkeys to be used as args when type is a hash.
85
84
 
86
- * `:if` - Specifies a method, proc or string to call to determine if the scope should apply.
85
+ * `:in` - A shortcut for combining the `:using` option with nested hashes.
86
+
87
+ * `:if` - Specifies a method or proc to call to determine if the scope should apply. Passing a string is deprecated and it will be removed in a future version.
87
88
 
88
- * `:unless` - Specifies a method, proc or string to call to determine if the scope should NOT apply.
89
+ * `:unless` - Specifies a method or proc to call to determine if the scope should NOT apply. Passing a string is deprecated and it will be removed in a future version.
89
90
 
90
91
  * `:default` - Default value for the scope. Whenever supplied the scope is always called.
91
92
 
92
93
  * `:allow_blank` - Blank values are not sent to scopes by default. Set to true to overwrite.
93
94
 
94
- * `:in` - A shortcut for combining the `:using` option with nested hashes.
95
-
96
95
  ## Boolean usage
97
96
 
98
97
  If `type: :boolean` is set it just calls the named scope, without any arguments, when parameter
99
98
  is set to a "true" value. `'true'` and `'1'` are parsed as `true`, everything else as `false`.
100
99
 
101
- When boolean scope is set up with `allow_blank: true`, it will call the scope
102
- with the value as usual scope.
100
+ When boolean scope is set up with `allow_blank: true`, it will call the scope with the value as
101
+ any usual scope.
103
102
 
104
103
  ```ruby
105
104
  has_scope :visible, type: :boolean
@@ -110,6 +109,11 @@ scope :visible, -> { where(visible: true) }
110
109
  scope :active, ->(value = true) { where(active: value) }
111
110
  ```
112
111
 
112
+ _Note_: it is not possible to apply a boolean scope with just the query param being present, e.g.
113
+ `?active`, that's not considered a "true" value (the param value will be `nil`), and thus the
114
+ scope will be called with `false` as argument. In order for the scope to receive a `true` argument
115
+ the param value must be set to one of the "true" values above, e.g. `?active=true` or `?active=1`.
116
+
113
117
  ## Block usage
114
118
 
115
119
  `has_scope` also accepts a block. The controller, current scope and value are yielded
@@ -118,7 +122,7 @@ need to manipulate the given value:
118
122
 
119
123
  ```ruby
120
124
  has_scope :category do |controller, scope, value|
121
- value != "all" ? scope.by_category(value) : scope
125
+  value != 'all' ? scope.by_category(value) : scope
122
126
  end
123
127
  ```
124
128
 
@@ -126,7 +130,7 @@ When used with booleans without `:allow_blank`, it just receives two arguments
126
130
  and is just invoked if true is given:
127
131
 
128
132
  ```ruby
129
- has_scope :not_voted_by_me, :type => :boolean do |controller, scope|
133
+ has_scope :not_voted_by_me, type: :boolean do |controller, scope|
130
134
  scope.not_voted_by(controller.current_user.id)
131
135
  end
132
136
  ```
@@ -159,10 +163,22 @@ scope :available, ->(*) { where(blocked: false) }
159
163
  This will allow usual users to get only available items, but admins will
160
164
  be able to access blocked items too.
161
165
 
166
+ ## Check which scopes have been applied
167
+
168
+ To check which scopes have been applied, you can call `current_scopes` from the controller or view.
169
+ This returns a hash with the scope name as the key and the scope value as the value.
170
+
171
+ For example, if a boolean `:active` scope has been applied, `current_scopes` will return `{ active: true }`.
172
+
173
+ ## Supported Ruby / Rails versions
174
+
175
+ We intend to maintain support for all Ruby / Rails versions that haven't reached end-of-life.
176
+
177
+ For more information about specific versions please check [Ruby](https://www.ruby-lang.org/en/downloads/branches/)
178
+ and [Rails](https://guides.rubyonrails.org/maintenance_policy.html) maintenance policies, and our test matrix.
179
+
162
180
  ## Bugs and Feedback
163
181
 
164
182
  If you discover any bugs or want to drop a line, feel free to create an issue on GitHub.
165
183
 
166
- http://github.com/plataformatec/has_scope/issues
167
-
168
- MIT License. Copyright 2009-2016 Plataformatec. http://blog.plataformatec.com.br
184
+ MIT License. Copyright 2009-2019 Plataformatec. http://blog.plataformatec.com.br
data/lib/has_scope.rb CHANGED
@@ -1,17 +1,20 @@
1
+ require 'active_support'
2
+ require 'action_controller'
3
+
1
4
  module HasScope
2
5
  TRUE_VALUES = ["true", true, "1", 1]
3
6
 
4
7
  ALLOWED_TYPES = {
5
- :array => [[ Array ]],
6
- :hash => [[Hash, ActionController::Parameters]],
7
- :boolean => [[ Object ], -> v { TRUE_VALUES.include?(v) }],
8
- :default => [[ String, Numeric ]],
8
+ array: [[ Array ]],
9
+ hash: [[ Hash, ActionController::Parameters ]],
10
+ boolean: [[ Object ], -> v { TRUE_VALUES.include?(v) }],
11
+ default: [[ String, Numeric ]],
9
12
  }
10
13
 
11
14
  def self.included(base)
12
15
  base.class_eval do
13
16
  extend ClassMethods
14
- class_attribute :scopes_configuration, :instance_writer => false
17
+ class_attribute :scopes_configuration, instance_writer: false
15
18
  self.scopes_configuration = {}
16
19
  end
17
20
  end
@@ -36,6 +39,8 @@ module HasScope
36
39
  # * <tt>:using</tt> - If type is a hash, you can provide :using to convert the hash to
37
40
  # a named scope call with several arguments.
38
41
  #
42
+ # * <tt>:in</tt> - A shortcut for combining the `:using` option with nested hashes.
43
+ #
39
44
  # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
40
45
  # if the scope should apply
41
46
  #
@@ -57,7 +62,7 @@ module HasScope
57
62
  # value != "all" ? scope.by_category(value) : scope
58
63
  # end
59
64
  #
60
- # has_scope :not_voted_by_me, :type => :boolean do |controller, scope|
65
+ # has_scope :not_voted_by_me, type: :boolean do |controller, scope|
61
66
  # scope.not_voted_by(controller.current_user.id)
62
67
  # end
63
68
  #
@@ -69,6 +74,10 @@ module HasScope
69
74
  if options.key?(:in)
70
75
  options[:as] = options[:in]
71
76
  options[:using] = scopes
77
+
78
+ if options.key?(:default) && !options[:default].is_a?(Hash)
79
+ options[:default] = scopes.each_with_object({}) { |scope, hash| hash[scope] = options[:default] }
80
+ end
72
81
  end
73
82
 
74
83
  if options.key?(:using)
@@ -87,7 +96,7 @@ module HasScope
87
96
  self.scopes_configuration = scopes_configuration.dup
88
97
 
89
98
  scopes.each do |scope|
90
- scopes_configuration[scope] ||= { :as => scope, :type => :default, :block => block }
99
+ scopes_configuration[scope] ||= { as: scope, type: :default, block: block }
91
100
  scopes_configuration[scope] = self.scopes_configuration[scope].merge(options)
92
101
  end
93
102
  end
@@ -97,16 +106,16 @@ module HasScope
97
106
 
98
107
  # Receives an object where scopes will be applied to.
99
108
  #
100
- # class GraduationsController < InheritedResources::Base
101
- # has_scope :featured, :type => true, :only => :index
102
- # has_scope :by_degree, :only => :index
109
+ # class GraduationsController < ApplicationController
110
+ # has_scope :featured, type: true, only: :index
111
+ # has_scope :by_degree, only: :index
103
112
  #
104
113
  # def index
105
114
  # @graduations = apply_scopes(Graduation).all
106
115
  # end
107
116
  # end
108
117
  #
109
- def apply_scopes(target, hash=params)
118
+ def apply_scopes(target, hash = params)
110
119
  scopes_configuration.each do |scope, options|
111
120
  next unless apply_scope_to_action?(options)
112
121
  key = options[:as]
@@ -120,12 +129,20 @@ module HasScope
120
129
  end
121
130
  end
122
131
 
123
- value = parse_value(options[:type], key, value)
132
+ value = parse_value(options[:type], value)
124
133
  value = normalize_blanks(value)
125
134
 
126
- if call_scope && (value.present? || options[:allow_blank])
135
+ if value && options.key?(:using)
136
+ scope_value = value.values_at(*options[:using])
137
+ call_scope &&= scope_value.all?(&:present?) || options[:allow_blank]
138
+ else
139
+ scope_value = value
140
+ call_scope &&= value.present? || options[:allow_blank]
141
+ end
142
+
143
+ if call_scope
127
144
  current_scopes[key] = value
128
- target = call_scope_by_type(options[:type], scope, target, value, options)
145
+ target = call_scope_by_type(options[:type], scope, target, scope_value, options)
129
146
  end
130
147
  end
131
148
 
@@ -133,7 +150,7 @@ module HasScope
133
150
  end
134
151
 
135
152
  # Set the real value for the current scope if type check.
136
- def parse_value(type, key, value) #:nodoc:
153
+ def parse_value(type, value) #:nodoc:
137
154
  klasses, parser = ALLOWED_TYPES[type]
138
155
  if klasses.any? { |klass| value.is_a?(klass) }
139
156
  parser ? parser.call(value) : value
@@ -160,8 +177,7 @@ module HasScope
160
177
 
161
178
  if type == :boolean && !options[:allow_blank]
162
179
  block ? block.call(self, target) : target.send(scope)
163
- elsif value && options.key?(:using)
164
- value = value.values_at(*options[:using])
180
+ elsif options.key?(:using)
165
181
  block ? block.call(self, target, value) : target.send(scope, *value)
166
182
  else
167
183
  block ? block.call(self, target, value) : target.send(scope, value)
@@ -185,6 +201,11 @@ module HasScope
185
201
  def applicable?(string_proc_or_symbol, expected) #:nodoc:
186
202
  case string_proc_or_symbol
187
203
  when String
204
+ ActiveSupport::Deprecation.warn <<-DEPRECATION.squish
205
+ [HasScope] Passing a string to determine if the scope should be applied
206
+ is deprecated and it will be removed in a future version of HasScope.
207
+ DEPRECATION
208
+
188
209
  eval(string_proc_or_symbol) == expected
189
210
  when Proc
190
211
  string_proc_or_symbol.call(self) == expected
@@ -1,3 +1,3 @@
1
1
  module HasScope
2
- VERSION = "0.7.2"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -5,21 +5,30 @@ HasScope::ALLOWED_TYPES[:date] = [[String], -> v { Date.parse(v) rescue nil }]
5
5
  class Tree; end
6
6
 
7
7
  class TreesController < ApplicationController
8
- has_scope :color, :unless => :show_all_colors?
9
- has_scope :only_tall, :type => :boolean, :only => :index, :if => :restrict_to_only_tall_trees?
10
- has_scope :shadown_range, :default => 10, :except => [ :index, :show, :new ]
11
- has_scope :root_type, :as => :root, :allow_blank => true
12
- has_scope :planted_before, :default => proc { Date.today }
13
- has_scope :planted_after, :type => :date
14
- has_scope :calculate_height, :default => proc {|c| c.session[:height] || 20 }, :only => :new
15
- has_scope :paginate, :type => :hash
16
- has_scope :args_paginate, :type => :hash, :using => [:page, :per_page]
17
- has_scope :categories, :type => :array
18
- has_scope :title, :in => :q
19
- has_scope :content, :in => :q
20
- has_scope :conifer, type: :boolean, :allow_blank => true
21
-
22
- has_scope :only_short, :type => :boolean do |controller, scope|
8
+ has_scope :color, unless: :show_all_colors?
9
+ has_scope :only_tall, type: :boolean, only: :index, if: :restrict_to_only_tall_trees?
10
+ has_scope :shadown_range, default: 10, except: [ :index, :show, :new ]
11
+ has_scope :root_type, as: :root, allow_blank: true
12
+ has_scope :planted_before, default: proc { Date.today }
13
+ has_scope :planted_after, type: :date
14
+ has_scope :calculate_height, default: proc { |c| c.session[:height] || 20 }, only: :new
15
+ has_scope :paginate, type: :hash
16
+ has_scope :paginate_blank, type: :hash, allow_blank: true
17
+ has_scope :paginate_default, type: :hash, default: { page: 1, per_page: 10 }, only: :edit
18
+ has_scope :args_paginate, type: :hash, using: [:page, :per_page]
19
+ has_scope :args_paginate_blank, using: [:page, :per_page], allow_blank: true
20
+ has_scope :args_paginate_default, using: [:page, :per_page], default: { page: 1, per_page: 10 }, only: :edit
21
+ has_scope :categories, type: :array
22
+ has_scope :title, in: :q
23
+ has_scope :content, in: :q
24
+ has_scope :metadata, in: :q
25
+ has_scope :metadata_blank, in: :q, allow_blank: true
26
+ has_scope :metadata_default, in: :q, default: "default", only: :edit
27
+ has_scope :conifer, type: :boolean, allow_blank: true
28
+ has_scope :eval_plant, if: "params[:eval_plant].present?", unless: "params[:skip_eval_plant].present?"
29
+ has_scope :proc_plant, if: -> c { c.params[:proc_plant].present? }, unless: -> c { c.params[:skip_proc_plant].present? }
30
+
31
+ has_scope :only_short, type: :boolean do |controller, scope|
23
32
  scope.only_really_short!(controller.object_id)
24
33
  end
25
34
 
@@ -42,6 +51,16 @@ class TreesController < ApplicationController
42
51
  alias :edit :show
43
52
 
44
53
  protected
54
+ # Silence deprecations in the test suite, except for the actual deprecated String if/unless options.
55
+ # TODO: remove with the deprecation.
56
+ def apply_scopes(*)
57
+ if params[:eval_plant]
58
+ super
59
+ else
60
+ ActiveSupport::Deprecation.silence { super }
61
+ end
62
+ end
63
+
45
64
  def restrict_to_only_tall_trees?
46
65
  true
47
66
  end
@@ -50,20 +69,13 @@ class TreesController < ApplicationController
50
69
  false
51
70
  end
52
71
 
53
- if ActionPack::VERSION::MAJOR == 5
54
- def default_render
55
- render body: action_name
56
- end
57
- else
58
- # TODO: Remove this when we only support Rails 5.
59
- def default_render
60
- render text: action_name
61
- end
72
+ def default_render
73
+ render body: action_name
62
74
  end
63
75
  end
64
76
 
65
77
  class BonsaisController < TreesController
66
- has_scope :categories, :if => :categories?
78
+ has_scope :categories, if: :categories?
67
79
 
68
80
  protected
69
81
  def categories?
@@ -77,15 +89,19 @@ class HasScopeTest < ActionController::TestCase
77
89
  def test_boolean_scope_is_called_when_boolean_param_is_true
78
90
  Tree.expects(:only_tall).with().returns(Tree).in_sequence
79
91
  Tree.expects(:all).returns([mock_tree]).in_sequence
80
- get :index, :only_tall => 'true'
92
+
93
+ get :index, params: { only_tall: 'true' }
94
+
81
95
  assert_equal([mock_tree], assigns(:@trees))
82
- assert_equal({ :only_tall => true }, current_scopes)
96
+ assert_equal({ only_tall: true }, current_scopes)
83
97
  end
84
98
 
85
99
  def test_boolean_scope_is_not_called_when_boolean_param_is_false
86
100
  Tree.expects(:only_tall).never
87
101
  Tree.expects(:all).returns([mock_tree])
88
- get :index, :only_tall => 'false'
102
+
103
+ get :index, params: { only_tall: 'false' }
104
+
89
105
  assert_equal([mock_tree], assigns(:@trees))
90
106
  assert_equal({ }, current_scopes)
91
107
  end
@@ -93,23 +109,29 @@ class HasScopeTest < ActionController::TestCase
93
109
  def test_boolean_scope_with_allow_blank_is_called_when_boolean_param_is_true
94
110
  Tree.expects(:conifer).with(true).returns(Tree).in_sequence
95
111
  Tree.expects(:all).returns([mock_tree]).in_sequence
96
- get :index, :conifer => 'true'
112
+
113
+ get :index, params: { conifer: 'true' }
114
+
97
115
  assert_equal([mock_tree], assigns(:@trees))
98
- assert_equal({ :conifer => true }, current_scopes)
116
+ assert_equal({ conifer: true }, current_scopes)
99
117
  end
100
118
 
101
119
  def test_boolean_scope_with_allow_blank_is_called_when_boolean_param_is_false
102
120
  Tree.expects(:conifer).with(false).returns(Tree).in_sequence
103
121
  Tree.expects(:all).returns([mock_tree]).in_sequence
104
- get :index, :conifer => 'not_true'
122
+
123
+ get :index, params: { conifer: 'not_true' }
124
+
105
125
  assert_equal([mock_tree], assigns(:@trees))
106
- assert_equal({ :conifer => false }, current_scopes)
126
+ assert_equal({ conifer: false }, current_scopes)
107
127
  end
108
128
 
109
129
  def test_boolean_scope_with_allow_blank_is_not_called_when_boolean_param_is_not_present
110
130
  Tree.expects(:conifer).never
111
131
  Tree.expects(:all).returns([mock_tree])
132
+
112
133
  get :index
134
+
113
135
  assert_equal([mock_tree], assigns(:@trees))
114
136
  assert_equal({ }, current_scopes)
115
137
  end
@@ -117,7 +139,9 @@ class HasScopeTest < ActionController::TestCase
117
139
  def test_scope_is_called_only_on_index
118
140
  Tree.expects(:only_tall).never
119
141
  Tree.expects(:find).with('42').returns(mock_tree)
120
- get :show, :only_tall => 'true', :id => '42'
142
+
143
+ get :show, params: { only_tall: 'true', id: '42' }
144
+
121
145
  assert_equal(mock_tree, assigns(:@tree))
122
146
  assert_equal({ }, current_scopes)
123
147
  end
@@ -126,7 +150,9 @@ class HasScopeTest < ActionController::TestCase
126
150
  @controller.stubs(:restrict_to_only_tall_trees?).returns(false)
127
151
  Tree.expects(:only_tall).never
128
152
  Tree.expects(:all).returns([mock_tree])
129
- get :index, :only_tall => 'true'
153
+
154
+ get :index, params: { only_tall: 'true' }
155
+
130
156
  assert_equal([mock_tree], assigns(:@trees))
131
157
  assert_equal({ }, current_scopes)
132
158
  end
@@ -135,15 +161,41 @@ class HasScopeTest < ActionController::TestCase
135
161
  @controller.stubs(:show_all_colors?).returns(true)
136
162
  Tree.expects(:color).never
137
163
  Tree.expects(:all).returns([mock_tree])
138
- get :index, :color => 'blue'
164
+
165
+ get :index, params: { color: 'blue' }
166
+
139
167
  assert_equal([mock_tree], assigns(:@trees))
140
168
  assert_equal({ }, current_scopes)
141
169
  end
142
170
 
171
+ def test_scope_with_eval_string_if_and_unless_options_is_deprecated
172
+ Tree.expects(:eval_plant).with('value').returns(Tree)
173
+ Tree.expects(:all).returns([mock_tree])
174
+
175
+ assert_deprecated(/Passing a string to determine if the scope should be applied is deprecated/) do
176
+ get :index, params: { eval_plant: 'value', skip_eval_plant: nil }
177
+ end
178
+
179
+ assert_equal([mock_tree], assigns(:@trees))
180
+ assert_equal({ eval_plant: 'value' }, current_scopes)
181
+ end
182
+
183
+ def test_scope_with_proc_if_and_unless_options
184
+ Tree.expects(:proc_plant).with('value').returns(Tree)
185
+ Tree.expects(:all).returns([mock_tree])
186
+
187
+ get :index, params: { proc_plant: 'value', skip_proc_plant: nil }
188
+
189
+ assert_equal([mock_tree], assigns(:@trees))
190
+ assert_equal({ proc_plant: 'value' }, current_scopes)
191
+ end
192
+
143
193
  def test_scope_is_called_except_on_index
144
194
  Tree.expects(:shadown_range).never
145
195
  Tree.expects(:all).returns([mock_tree])
146
- get :index, :shadown_range => 20
196
+
197
+ get :index, params: { shadown_range: 20 }
198
+
147
199
  assert_equal([mock_tree], assigns(:@trees))
148
200
  assert_equal({ }, current_scopes)
149
201
  end
@@ -151,15 +203,19 @@ class HasScopeTest < ActionController::TestCase
151
203
  def test_scope_is_called_with_arguments
152
204
  Tree.expects(:color).with('blue').returns(Tree).in_sequence
153
205
  Tree.expects(:all).returns([mock_tree]).in_sequence
154
- get :index, :color => 'blue'
206
+
207
+ get :index, params: { color: 'blue' }
208
+
155
209
  assert_equal([mock_tree], assigns(:@trees))
156
- assert_equal({ :color => 'blue' }, current_scopes)
210
+ assert_equal({ color: 'blue' }, current_scopes)
157
211
  end
158
212
 
159
213
  def test_scope_is_not_called_if_blank
160
214
  Tree.expects(:color).never
161
215
  Tree.expects(:all).returns([mock_tree]).in_sequence
162
- get :index, :color => ''
216
+
217
+ get :index, params: { color: '' }
218
+
163
219
  assert_equal([mock_tree], assigns(:@trees))
164
220
  assert_equal({ }, current_scopes)
165
221
  end
@@ -167,25 +223,31 @@ class HasScopeTest < ActionController::TestCase
167
223
  def test_scope_is_called_when_blank_if_allow_blank_is_given
168
224
  Tree.expects(:root_type).with('').returns(Tree)
169
225
  Tree.expects(:all).returns([mock_tree]).in_sequence
170
- get :index, :root => ''
226
+
227
+ get :index, params: { root: '' }
228
+
171
229
  assert_equal([mock_tree], assigns(:@trees))
172
- assert_equal({ :root => '' }, current_scopes)
230
+ assert_equal({ root: '' }, current_scopes)
173
231
  end
174
232
 
175
233
  def test_multiple_scopes_are_called
176
234
  Tree.expects(:only_tall).with().returns(Tree)
177
235
  Tree.expects(:color).with('blue').returns(Tree)
178
236
  Tree.expects(:all).returns([mock_tree])
179
- get :index, :color => 'blue', :only_tall => 'true'
237
+
238
+ get :index, params: { color: 'blue', only_tall: 'true' }
239
+
180
240
  assert_equal([mock_tree], assigns(:@trees))
181
- assert_equal({ :color => 'blue', :only_tall => true }, current_scopes)
241
+ assert_equal({ color: 'blue', only_tall: true }, current_scopes)
182
242
  end
183
243
 
184
244
  def test_scope_of_type_hash
185
245
  hash = { "page" => "1", "per_page" => "10" }
186
246
  Tree.expects(:paginate).with(hash).returns(Tree)
187
247
  Tree.expects(:all).returns([mock_tree])
188
- get :index, :paginate => hash
248
+
249
+ get :index, params: { paginate: hash }
250
+
189
251
  assert_equal([mock_tree], assigns(:@trees))
190
252
  assert_equal({ paginate: hash }, current_scopes)
191
253
  end
@@ -194,25 +256,53 @@ class HasScopeTest < ActionController::TestCase
194
256
  hash = { "page" => "1", "per_page" => "10" }
195
257
  Tree.expects(:args_paginate).with("1", "10").returns(Tree)
196
258
  Tree.expects(:all).returns([mock_tree])
197
- get :index, :args_paginate => hash
259
+
260
+ get :index, params: { args_paginate: hash }
261
+
198
262
  assert_equal([mock_tree], assigns(:@trees))
199
- assert_equal({ :args_paginate => hash }, current_scopes)
263
+ assert_equal({ args_paginate: hash }, current_scopes)
200
264
  end
201
265
 
202
266
  def test_hash_with_blank_values_is_ignored
203
267
  hash = { "page" => "", "per_page" => "" }
204
268
  Tree.expects(:paginate).never
205
269
  Tree.expects(:all).returns([mock_tree])
206
- get :index, :paginate => hash
270
+
271
+ get :index, params: { paginate: hash }
272
+
207
273
  assert_equal([mock_tree], assigns(:@trees))
208
274
  assert_equal({ }, current_scopes)
209
275
  end
210
276
 
277
+ def test_hash_with_blank_values_and_allow_blank_is_called
278
+ hash = { "page" => "", "per_page" => "" }
279
+ Tree.expects(:paginate_blank).with({}).returns(Tree)
280
+ Tree.expects(:all).returns([mock_tree])
281
+
282
+ get :index, params: { paginate_blank: hash }
283
+
284
+ assert_equal([mock_tree], assigns(:@trees))
285
+ assert_equal({ paginate_blank: {} }, current_scopes)
286
+ end
287
+
288
+ def test_hash_with_using_and_blank_values_and_allow_blank_is_called
289
+ hash = { "page" => "", "per_page" => "" }
290
+ Tree.expects(:args_paginate_blank).with(nil, nil).returns(Tree)
291
+ Tree.expects(:all).returns([mock_tree])
292
+
293
+ get :index, params: { args_paginate_blank: hash }
294
+
295
+ assert_equal([mock_tree], assigns(:@trees))
296
+ assert_equal({ args_paginate_blank: {} }, current_scopes)
297
+ end
298
+
211
299
  def test_nested_hash_with_blank_values_is_ignored
212
- hash = { "parent" => {"children" => ""} }
300
+ hash = { "parent" => { "children" => "" } }
213
301
  Tree.expects(:paginate).never
214
302
  Tree.expects(:all).returns([mock_tree])
215
- get :index, :paginate => hash
303
+
304
+ get :index, params: { paginate: hash }
305
+
216
306
  assert_equal([mock_tree], assigns(:@trees))
217
307
  assert_equal({ }, current_scopes)
218
308
  end
@@ -221,7 +311,9 @@ class HasScopeTest < ActionController::TestCase
221
311
  hash = { "parent" => [""] }
222
312
  Tree.expects(:paginate).never
223
313
  Tree.expects(:all).returns([mock_tree])
224
- get :index, :paginate => hash
314
+
315
+ get :index, params: { paginate: hash }
316
+
225
317
  assert_equal([mock_tree], assigns(:@trees))
226
318
  assert_equal({ }, current_scopes)
227
319
  end
@@ -230,99 +322,148 @@ class HasScopeTest < ActionController::TestCase
230
322
  array = %w(book kitchen sport)
231
323
  Tree.expects(:categories).with(array).returns(Tree)
232
324
  Tree.expects(:all).returns([mock_tree])
233
- get :index, :categories => array
325
+
326
+ get :index, params: { categories: array }
327
+
234
328
  assert_equal([mock_tree], assigns(:@trees))
235
- assert_equal({ :categories => array }, current_scopes)
329
+ assert_equal({ categories: array }, current_scopes)
236
330
  end
237
331
 
238
332
  def test_array_of_blank_values_is_ignored
239
333
  Tree.expects(:categories).never
240
334
  Tree.expects(:all).returns([mock_tree])
241
- get :index, :categories => [""]
335
+
336
+ get :index, params: { categories: [""] }
337
+
242
338
  assert_equal([mock_tree], assigns(:@trees))
243
339
  assert_equal({ }, current_scopes)
244
340
  end
245
341
 
246
342
  def test_scope_of_invalid_type_silently_fails
247
343
  Tree.expects(:all).returns([mock_tree])
248
- get :index, :paginate => "1"
344
+
345
+ get :index, params: { paginate: "1" }
346
+
249
347
  assert_equal([mock_tree], assigns(:@trees))
250
348
  assert_equal({ }, current_scopes)
251
349
  end
252
350
 
253
351
  def test_scope_is_called_with_default_value
254
352
  Tree.expects(:shadown_range).with(10).returns(Tree).in_sequence
353
+ Tree.expects(:paginate_default).with('page' => 1, 'per_page' => 10).returns(Tree).in_sequence
354
+ Tree.expects(:args_paginate_default).with(1, 10).returns(Tree).in_sequence
355
+ Tree.expects(:metadata_default).with('default').returns(Tree).in_sequence
255
356
  Tree.expects(:find).with('42').returns(mock_tree).in_sequence
256
- get :edit, :id => '42'
357
+
358
+ get :edit, params: { id: '42' }
359
+
257
360
  assert_equal(mock_tree, assigns(:@tree))
258
- assert_equal({ :shadown_range => 10 }, current_scopes)
361
+ assert_equal({
362
+ shadown_range: 10,
363
+ paginate_default: { 'page' => 1, 'per_page' => 10 },
364
+ args_paginate_default: { 'page' => 1, 'per_page' => 10 },
365
+ q: { 'metadata_default' => 'default' }
366
+ }, current_scopes)
259
367
  end
260
368
 
261
369
  def test_default_scope_value_can_be_overwritten
262
370
  Tree.expects(:shadown_range).with('20').returns(Tree).in_sequence
371
+ Tree.expects(:paginate_default).with('page' => '2', 'per_page' => '20').returns(Tree).in_sequence
372
+ Tree.expects(:args_paginate_default).with('3', '15').returns(Tree).in_sequence
373
+ Tree.expects(:metadata_blank).with(nil).returns(Tree).in_sequence
374
+ Tree.expects(:metadata_default).with('other').returns(Tree).in_sequence
263
375
  Tree.expects(:find).with('42').returns(mock_tree).in_sequence
264
- get :edit, :id => '42', :shadown_range => '20'
376
+
377
+ get :edit, params: {
378
+ id: '42',
379
+ shadown_range: '20',
380
+ paginate_default: { page: 2, per_page: 20 },
381
+ args_paginate_default: { page: 3, per_page: 15},
382
+ q: { metadata_default: 'other' }
383
+ }
384
+
265
385
  assert_equal(mock_tree, assigns(:@tree))
266
- assert_equal({ :shadown_range => '20' }, current_scopes)
386
+ assert_equal({
387
+ shadown_range: '20',
388
+ paginate_default: { 'page' => '2', 'per_page' => '20' },
389
+ args_paginate_default: { 'page' => '3', 'per_page' => '15' },
390
+ q: { 'metadata_default' => 'other' }
391
+ }, current_scopes)
267
392
  end
268
393
 
269
394
  def test_scope_with_different_key
270
395
  Tree.expects(:root_type).with('outside').returns(Tree).in_sequence
271
396
  Tree.expects(:find).with('42').returns(mock_tree).in_sequence
272
- get :show, :id => '42', :root => 'outside'
397
+
398
+ get :show, params: { id: '42', root: 'outside' }
399
+
273
400
  assert_equal(mock_tree, assigns(:@tree))
274
- assert_equal({ :root => 'outside' }, current_scopes)
401
+ assert_equal({ root: 'outside' }, current_scopes)
275
402
  end
276
403
 
277
404
  def test_scope_with_default_value_as_a_proc_without_argument
278
405
  Date.expects(:today).returns("today")
279
406
  Tree.expects(:planted_before).with("today").returns(Tree)
280
407
  Tree.expects(:all).returns([mock_tree])
408
+
281
409
  get :index
410
+
282
411
  assert_equal([mock_tree], assigns(:@trees))
283
- assert_equal({ :planted_before => "today" }, current_scopes)
412
+ assert_equal({ planted_before: "today" }, current_scopes)
284
413
  end
285
414
 
286
415
  def test_scope_with_default_value_as_proc_with_argument
287
416
  session[:height] = 100
288
417
  Tree.expects(:calculate_height).with(100).returns(Tree).in_sequence
289
418
  Tree.expects(:new).returns(mock_tree).in_sequence
419
+
290
420
  get :new
421
+
291
422
  assert_equal(mock_tree, assigns(:@tree))
292
- assert_equal({ :calculate_height => 100 }, current_scopes)
423
+ assert_equal({ calculate_height: 100 }, current_scopes)
293
424
  end
294
425
 
295
426
  def test_scope_with_custom_type
296
427
  parsed = Date.civil(2014,11,11)
297
428
  Tree.expects(:planted_after).with(parsed).returns(Tree)
298
429
  Tree.expects(:all).returns([mock_tree])
299
- get :index, :planted_after => "2014-11-11"
430
+
431
+ get :index, params: { planted_after: "2014-11-11" }
432
+
300
433
  assert_equal([mock_tree], assigns(:@trees))
301
- assert_equal({ :planted_after => parsed }, current_scopes)
434
+ assert_equal({ planted_after: parsed }, current_scopes)
302
435
  end
303
436
 
304
437
  def test_scope_with_boolean_block
305
438
  Tree.expects(:only_really_short!).with(@controller.object_id).returns(Tree)
306
439
  Tree.expects(:all).returns([mock_tree])
307
- get :index, :only_short => 'true'
440
+
441
+ get :index, params: { only_short: 'true' }
442
+
308
443
  assert_equal([mock_tree], assigns(:@trees))
309
- assert_equal({ :only_short => true }, current_scopes)
444
+ assert_equal({ only_short: true }, current_scopes)
310
445
  end
311
446
 
312
447
  def test_scope_with_other_block_types
313
448
  Tree.expects(:by_given_category).with(@controller.object_id, 'for_id').returns(Tree)
314
449
  Tree.expects(:all).returns([mock_tree])
315
- get :index, :by_category => 'for'
450
+
451
+ get :index, params: { by_category: 'for' }
452
+
316
453
  assert_equal([mock_tree], assigns(:@trees))
317
- assert_equal({ :by_category => 'for' }, current_scopes)
454
+ assert_equal({ by_category: 'for' }, current_scopes)
318
455
  end
319
456
 
320
457
  def test_scope_with_nested_hash_and_in_option
321
458
  hash = { 'title' => 'the-title', 'content' => 'the-content' }
322
459
  Tree.expects(:title).with('the-title').returns(Tree)
323
460
  Tree.expects(:content).with('the-content').returns(Tree)
461
+ Tree.expects(:metadata).never
462
+ Tree.expects(:metadata_blank).with(nil).returns(Tree)
324
463
  Tree.expects(:all).returns([mock_tree])
325
- get :index, q: hash
464
+
465
+ get :index, params: { q: hash }
466
+
326
467
  assert_equal([mock_tree], assigns(:@trees))
327
468
  assert_equal({ q: hash }, current_scopes)
328
469
  end
@@ -334,14 +475,7 @@ class HasScopeTest < ActionController::TestCase
334
475
 
335
476
  protected
336
477
 
337
- if ActionPack::VERSION::MAJOR == 5
338
- # TODO: Remove this when we only support Rails 5.
339
- def get(action, params = {})
340
- super action, params: params
341
- end
342
- end
343
-
344
- def mock_tree(stubs={})
478
+ def mock_tree(stubs = {})
345
479
  @mock_tree ||= mock(stubs)
346
480
  end
347
481
 
@@ -360,16 +494,14 @@ class TreeHugger
360
494
  has_scope :color
361
495
 
362
496
  def by_color
363
- apply_scopes(Tree, :color => 'blue')
497
+ apply_scopes(Tree, color: 'blue')
364
498
  end
365
-
366
499
  end
367
500
 
368
501
  class HasScopeOutsideControllerTest < ActiveSupport::TestCase
369
-
370
502
  def test_has_scope_usable_outside_controller
371
503
  Tree.expects(:color).with('blue')
504
+
372
505
  TreeHugger.new.by_color
373
506
  end
374
-
375
507
  end
data/test/test_helper.rb CHANGED
@@ -7,17 +7,12 @@ require 'mocha/mini_test'
7
7
  # Configure Rails
8
8
  ENV['RAILS_ENV'] = 'test'
9
9
 
10
- require 'active_support'
11
- require 'active_support/core_ext/string/strip'
12
- require 'action_controller'
13
- require 'action_dispatch/middleware/flash'
14
-
15
10
  $:.unshift File.expand_path('../../lib', __FILE__)
16
11
  require 'has_scope'
17
12
 
18
13
  HasScope::Routes = ActionDispatch::Routing::RouteSet.new
19
14
  HasScope::Routes.draw do
20
- get '/:controller(/:action(/:id))'
15
+ resources :trees, only: %i[index new edit show]
21
16
  end
22
17
 
23
18
  class ApplicationController < ActionController::Base
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_scope
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - José Valim
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-10 00:00:00.000000000 Z
11
+ date: 2021-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.1'
19
+ version: '5.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4.1'
26
+ version: '5.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '4.1'
33
+ version: '5.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '4.1'
40
+ version: '5.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +83,7 @@ homepage: http://github.com/plataformatec/has_scope
83
83
  licenses:
84
84
  - MIT
85
85
  metadata: {}
86
- post_install_message:
86
+ post_install_message:
87
87
  rdoc_options:
88
88
  - "--charset=UTF-8"
89
89
  require_paths:
@@ -92,16 +92,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - ">="
94
94
  - !ruby/object:Gem::Version
95
- version: 2.1.7
95
+ version: 2.5.0
96
96
  required_rubygems_version: !ruby/object:Gem::Requirement
97
97
  requirements:
98
98
  - - ">="
99
99
  - !ruby/object:Gem::Version
100
100
  version: '0'
101
101
  requirements: []
102
- rubyforge_project:
103
- rubygems_version: 2.7.6
104
- signing_key:
102
+ rubygems_version: 3.2.6
103
+ signing_key:
105
104
  specification_version: 4
106
105
  summary: Maps controller filters to your resource scopes.
107
106
  test_files: