arcane 0.1.1 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +15 -2
- data/README.md +92 -32
- data/lib/arcane.rb +18 -26
- data/lib/arcane/finder.rb +3 -3
- data/lib/arcane/parameters.rb +77 -0
- data/lib/arcane/version.rb +1 -1
- data/spec/arcane/finder_spec.rb +12 -12
- data/spec/arcane/parameters_spec.rb +84 -0
- data/spec/arcane_spec.rb +13 -90
- data/spec/spec_helper.rb +39 -0
- metadata +21 -41
- data/lib/arcane/chain.rb +0 -43
- data/spec/arcane/chain_spec.rb +0 -66
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c157016d7b457a09a15c6222079d7d96725d8381
|
4
|
+
data.tar.gz: 90e1df401507d8c4281cf709580b23aebc72f958
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 75a7e859ce0552b16632bc9bc777cb3fcc621a7ef10403b6f9ceb24f91a39c96b7313c158908a28d8d8539c1556986c228f7b9c0dc817b26cd2a0c95a5559c91
|
7
|
+
data.tar.gz: d241c9243a4b3a194e92add373e31b56dd9a162f0631ad155ac287930a866e5abd7f1b8b63e8b8f5bb2c9203f5f21e31efbfceb8904d8566f6fd3845377e3abe
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,22 @@
|
|
1
|
-
### Arcane **0.
|
1
|
+
### Arcane **1.0.0.pre** [head] - 2013-07-12
|
2
|
+
* **[deprecation]** The `refine` helper no longer
|
3
|
+
exist, as it's a proposed keyword for ruby 2.0 look
|
4
|
+
to the new features for how to access arcane.
|
5
|
+
|
6
|
+
* **[feature]** Introducing chained methods on `params`
|
7
|
+
to specify for what, who and how you want arcane to
|
8
|
+
refine your parameters. Look in `README.md` for
|
9
|
+
detailed information.
|
10
|
+
|
11
|
+
* **[bugfix]** You can now properly specify
|
12
|
+
`refinery_class` in your model.
|
13
|
+
|
14
|
+
### Arcane **0.1.1** [current] – 2013-07-11
|
2
15
|
* **[feature]** The `refine` helper no longer needs a
|
3
16
|
refinery method, it will try and detect which one to
|
4
17
|
use based on parameters.
|
5
18
|
|
6
|
-
### Arcane **0.1.0** [
|
19
|
+
### Arcane **0.1.0** [old] – 2013-07-11
|
7
20
|
* **[bugfix]** Arcane should no longer error when there is
|
8
21
|
no current_user present.
|
9
22
|
* **[feature]** Added new query syntax for the `refine`
|
data/README.md
CHANGED
@@ -13,16 +13,28 @@ Inspired by [Pundit](https://github.com/elabs/pundit)
|
|
13
13
|
|
14
14
|
## Usage
|
15
15
|
|
16
|
-
This is how easy it
|
16
|
+
This is how easy it is to use:
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
|
19
|
+
def create
|
20
|
+
@article = Article.new params.for(Article).refine
|
21
|
+
end
|
22
|
+
|
23
|
+
def update
|
24
|
+
@article.find(params[:id])
|
25
|
+
@article.update_attributes params.for(@article).as(current_user).refine
|
26
|
+
end
|
27
|
+
|
28
|
+
def destroy
|
29
|
+
@article.find(params[:id])
|
30
|
+
@article.update_attributes params.for(@article).on(:destroy).refine
|
31
|
+
end
|
20
32
|
```
|
21
33
|
|
22
|
-
### Include the
|
34
|
+
### Include the Arcane Module
|
23
35
|
|
24
36
|
Though, we need to do a couple of things before we can get started. First of all include `Arcane` in your
|
25
|
-
controller. This will
|
37
|
+
controller. This will extend strong parameters with all the arcane methods you saw above in the example.
|
26
38
|
|
27
39
|
```ruby
|
28
40
|
# app/controllers/application_controller.rb
|
@@ -33,7 +45,7 @@ end
|
|
33
45
|
|
34
46
|
### Create your first Refinery
|
35
47
|
|
36
|
-
Before you can use the
|
48
|
+
Before you can use the parameter methods, you need a Refinery for the model you want to pass parameters to.
|
37
49
|
Simply create the directory `/app/refineries` in your Rails project. Create a Refinery your model, in this
|
38
50
|
case Article. `/app/refineries/article_refinery.rb`. Create a class in that file called `ArticleRefinery`.
|
39
51
|
|
@@ -41,9 +53,8 @@ Methods defined in the refinery should reflect the controller method for clarity
|
|
41
53
|
want it to be. These methods must return an array containing the same parameters you would otherwise send
|
42
54
|
to strong parameters.
|
43
55
|
|
44
|
-
It can be initiated using a `Struct` which accepts an `object` and a `user`.
|
45
|
-
|
46
|
-
the parameters on.
|
56
|
+
It can be initiated using a `Struct` which accepts an `object` and a `user`. Arcane will automatically send
|
57
|
+
`current_user`, if present to the refinery as well as the object you want to apply the parameters on.
|
47
58
|
|
48
59
|
```ruby
|
49
60
|
# app/refineries/article_refinery.rb
|
@@ -66,60 +77,82 @@ class CommentRefinery < Arcane::Refinery; end
|
|
66
77
|
|
67
78
|
### Using Arcane in your controller
|
68
79
|
|
69
|
-
Next up, using the
|
70
|
-
|
71
|
-
|
80
|
+
Next up, using the Arcane methods. There first three are; `for`, `as`, `on` and can all be called on
|
81
|
+
an instance of rails params, chained, and in any order you want. The fourth one, `refine` you call to
|
82
|
+
pull your parameters through a refinery.
|
83
|
+
|
84
|
+
* `for` - The model or object you want to filter parameters
|
85
|
+
* `as` - The user performing the action, by default `current_user`
|
86
|
+
* `on` - The action or rather, refinery method that is called
|
87
|
+
|
88
|
+
* `refine` - Wraps everything up and finds your desired filter.
|
72
89
|
|
73
90
|
```ruby
|
74
|
-
refined_params =
|
91
|
+
refined_params = params.for(@article).as(current_user).on(:update).refine
|
75
92
|
```
|
76
93
|
|
77
|
-
|
94
|
+
Here's an example of how a controller can look with Arcane paramters.
|
78
95
|
|
79
96
|
```ruby
|
80
|
-
class
|
81
|
-
|
97
|
+
class GameController < ApplicationController
|
82
98
|
def create
|
83
|
-
@
|
84
|
-
@article.save
|
99
|
+
@game = Game.create(params.for(Game).as(user_from_location).refine)
|
85
100
|
end
|
86
101
|
|
87
102
|
def update
|
88
|
-
@article
|
89
|
-
@article.update_attributes(
|
103
|
+
@article.find(params[:id])
|
104
|
+
@article.update_attributes params.for(@article).as(current_user).refine
|
90
105
|
end
|
91
106
|
|
92
|
-
|
107
|
+
def update_many
|
108
|
+
@games = Game.find(params[:ids])
|
109
|
+
@games.each do |game|
|
110
|
+
game.update_attributes(params.for(@game).on(:update).refine)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
93
115
|
|
116
|
+
def user_from_location
|
117
|
+
# ...
|
118
|
+
end
|
119
|
+
end
|
94
120
|
```
|
95
121
|
|
96
122
|
## Features
|
97
123
|
|
98
|
-
###
|
99
|
-
|
100
|
-
|
124
|
+
### Invokable anywhere.
|
125
|
+
As arcane extends ActionController::Parameters you can invoke in anywhere and start toying around with
|
126
|
+
the arcane methods. This is good if you have some other way of getting data in to your application outside
|
127
|
+
the context of a controller.
|
101
128
|
|
102
129
|
```ruby
|
103
|
-
|
104
|
-
|
105
|
-
|
130
|
+
@user, @post = User.find(1), Post.find(24)
|
131
|
+
|
132
|
+
my_params = ActionController::Parameters.new({ post: { content: "Hello" } })
|
133
|
+
my_params.for(@post).as(@user).on(:create)
|
106
134
|
```
|
107
135
|
|
108
136
|
### Automatic Method Detection
|
109
|
-
If you have specified no refinery
|
110
|
-
what method to use.
|
111
|
-
on the parameters and use your refinery. *If you want to know how to handle fallbacks, see next feature.*
|
137
|
+
If you have specified no refinery action in your chain to params, Arcane tries to find out for itself
|
138
|
+
what method to use. Arcane uses the action key in the rails parameters to determine the refinery method.
|
112
139
|
|
113
140
|
```ruby
|
114
141
|
class CommentsController < ApplicationController
|
115
142
|
def update
|
116
143
|
@comment = Comment.find(params[:id])
|
117
|
-
@comment.update_attributes
|
144
|
+
@comment.update_attributes params.for(@comment)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class CommentRefinery < Arcane::Refinery
|
149
|
+
def update
|
150
|
+
[:email,:name,:text]
|
118
151
|
end
|
119
152
|
end
|
120
153
|
```
|
121
154
|
|
122
|
-
### Default
|
155
|
+
### Default parameters
|
123
156
|
You are able to specify a `default` method in your refinery which will be prioritized if no the method
|
124
157
|
you call does not exist. If default is not specified it will be as the refinery returned an empty array.
|
125
158
|
|
@@ -131,7 +164,7 @@ class AmbiguityRefinery < Arcane::Refinery
|
|
131
164
|
end
|
132
165
|
```
|
133
166
|
|
134
|
-
###
|
167
|
+
### Custom root requrement
|
135
168
|
You are able to disable or change the root requirement. Let's say you have a sessions endpoint where
|
136
169
|
you don't have your username and password parameters wrapped in a root. Now you can use the root class
|
137
170
|
method and set it to nil or false and it will automatically not require it.
|
@@ -156,6 +189,33 @@ class MeRefinery < UserRefinery
|
|
156
189
|
end
|
157
190
|
```
|
158
191
|
|
192
|
+
### Refinery Inheritence
|
193
|
+
Say you have quite similar needs between two different models, one of them might even have inherited
|
194
|
+
from the other. As arcane's refineries are just regular ruby models you can easily inherit from one
|
195
|
+
to another and it will just work.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
class Square
|
199
|
+
attr :height, :width
|
200
|
+
end
|
201
|
+
|
202
|
+
class Cube < Square
|
203
|
+
attr :depth
|
204
|
+
end
|
205
|
+
|
206
|
+
class SquareRefinery
|
207
|
+
def create
|
208
|
+
[:height,:width]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
class CubeRefinery
|
213
|
+
def create
|
214
|
+
[:depth] + super
|
215
|
+
end
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
159
219
|
## Requirements
|
160
220
|
|
161
221
|
Currently this gem is only supported for Rails and with any of these ruby versions:
|
data/lib/arcane.rb
CHANGED
@@ -1,49 +1,41 @@
|
|
1
|
-
require "arcane/version"
|
2
|
-
require "arcane/finder"
|
3
|
-
require "arcane/chain"
|
4
|
-
require "arcane/refinery"
|
5
|
-
|
6
1
|
require 'active_support/concern'
|
7
2
|
require 'active_support/core_ext/string/inflections'
|
8
3
|
require 'active_support/core_ext/object/blank'
|
9
4
|
require 'strong_parameters'
|
10
5
|
|
6
|
+
require "arcane/version"
|
7
|
+
require "arcane/finder"
|
8
|
+
require "arcane/refinery"
|
9
|
+
require "arcane/parameters"
|
10
|
+
|
11
11
|
module Arcane
|
12
12
|
|
13
13
|
extend ActiveSupport::Concern
|
14
14
|
|
15
15
|
included do
|
16
|
+
|
16
17
|
if respond_to?(:helper_method)
|
17
18
|
helper_method :refine
|
19
|
+
helper_method :current_params_user
|
18
20
|
end
|
21
|
+
|
19
22
|
if respond_to?(:hide_action)
|
20
23
|
hide_action :refine
|
24
|
+
hide_action :current_params_user
|
21
25
|
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def refine(object,*args)
|
25
|
-
|
26
|
-
current_user = nil unless respond_to?(:current_user)
|
27
26
|
|
28
|
-
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
elsif [Hash,HashWithIndifferentAccess,ActionController::Parameters].any? { |c| arg.kind_of?(c) }
|
34
|
-
opts[:params] ||= arg
|
35
|
-
elsif current_user.nil?
|
36
|
-
opts[:user] ||= arg
|
37
|
-
end
|
38
|
-
end
|
29
|
+
def current_params_user
|
30
|
+
respond_to?(:current_user) ? current_user : nil
|
31
|
+
end
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
opts[:object] ||= object.respond_to?(:new) ? object.new : object
|
33
|
+
def params
|
34
|
+
@_params ||= ActionController::Parameters.new(request.parameters).as(current_params_user)
|
35
|
+
end
|
44
36
|
|
45
|
-
|
46
|
-
|
37
|
+
def params=(val)
|
38
|
+
@_params = val.kind_of?(Hash) ? ActionController::Parameters.new(val).as(current_params_user) : val.as(current_params_user)
|
47
39
|
end
|
48
40
|
|
49
41
|
end
|
data/lib/arcane/finder.rb
CHANGED
@@ -8,7 +8,7 @@ module Arcane
|
|
8
8
|
@object = object
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def refinery
|
12
12
|
klass = find
|
13
13
|
klass = klass.constantize if klass.is_a?(String)
|
14
14
|
klass
|
@@ -33,9 +33,9 @@ module Arcane
|
|
33
33
|
|
34
34
|
def find
|
35
35
|
if object.respond_to?(:arcane_class)
|
36
|
-
object.
|
36
|
+
object.refinery_class
|
37
37
|
elsif object.class.respond_to?(:arcane_class)
|
38
|
-
object.class.
|
38
|
+
object.class.refinery_class
|
39
39
|
else
|
40
40
|
klass = self.class.object_name(object)
|
41
41
|
"#{klass}Refinery"
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Arcane
|
2
|
+
|
3
|
+
module Parameters
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
|
9
|
+
attr_accessor :user, :object, :action
|
10
|
+
|
11
|
+
def dup
|
12
|
+
self.class.new(self).tap do |duplicate|
|
13
|
+
duplicate.user = user
|
14
|
+
duplicate.object = object
|
15
|
+
duplicate.action = action
|
16
|
+
duplicate.default = default
|
17
|
+
duplicate.instance_variable_set :@permitted, @permitted
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def for(object)
|
24
|
+
params = self.dup
|
25
|
+
params.object = object
|
26
|
+
return params
|
27
|
+
end
|
28
|
+
|
29
|
+
def as(user)
|
30
|
+
params = self.dup
|
31
|
+
params.user = user
|
32
|
+
return params
|
33
|
+
end
|
34
|
+
|
35
|
+
def on(action)
|
36
|
+
params = self.dup
|
37
|
+
params.action = action
|
38
|
+
return params
|
39
|
+
end
|
40
|
+
|
41
|
+
def refine(opts={})
|
42
|
+
params = self.dup
|
43
|
+
|
44
|
+
params.action = opts[:action] || action || params[:action]
|
45
|
+
params.user = opts[:user] || user
|
46
|
+
params.object = opts[:object] || object
|
47
|
+
|
48
|
+
refinery = Arcane::Finder.new(params.object).refinery.new(params.object, params.user)
|
49
|
+
|
50
|
+
args = if params.action.nil?
|
51
|
+
[]
|
52
|
+
elsif refinery.respond_to?(params.action)
|
53
|
+
refinery.public_send(params.action)
|
54
|
+
elsif refinery.respond_to?(:default)
|
55
|
+
refinery.default
|
56
|
+
else
|
57
|
+
[]
|
58
|
+
end
|
59
|
+
|
60
|
+
root = if refinery.respond_to?(:root)
|
61
|
+
refinery.root
|
62
|
+
elsif refinery.class.respond_to?(:root)
|
63
|
+
refinery.class.root
|
64
|
+
else
|
65
|
+
Arcane::Finder.object_name(params.object)
|
66
|
+
end
|
67
|
+
|
68
|
+
return root.present? ? params.require(root.underscore).permit(*args) : params.permit(*args)
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
ActionController::Parameters.send :include, Arcane::Parameters
|
data/lib/arcane/version.rb
CHANGED
data/spec/arcane/finder_spec.rb
CHANGED
@@ -2,34 +2,34 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Arcane::Finder do
|
4
4
|
|
5
|
-
let(:
|
6
|
-
let(:
|
5
|
+
let(:object_with_refinery) { Task.new }
|
6
|
+
let(:object_without_refinery) { Shape.new }
|
7
7
|
|
8
|
-
before(:each) { @
|
8
|
+
before(:each) { @refinery = Arcane::Finder.new(object_with_refinery) }
|
9
9
|
|
10
10
|
describe '.new' do
|
11
11
|
it 'sets the object' do
|
12
|
-
@
|
12
|
+
@refinery.object.should eq(object_with_refinery)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
describe '#find' do
|
17
17
|
|
18
|
-
it 'finds existing
|
19
|
-
@
|
18
|
+
it 'finds existing refinery' do
|
19
|
+
@refinery.send(:find).should eq "TaskRefinery"
|
20
20
|
end
|
21
21
|
|
22
22
|
end
|
23
23
|
|
24
|
-
describe '#
|
24
|
+
describe '#refinery' do
|
25
25
|
|
26
|
-
it 'returns
|
27
|
-
@
|
26
|
+
it 'returns refinery' do
|
27
|
+
@refinery.refinery.should eq TaskRefinery
|
28
28
|
end
|
29
29
|
|
30
|
-
it 'returns base
|
31
|
-
@
|
32
|
-
@
|
30
|
+
it 'returns base refinery class when no refinery exists' do
|
31
|
+
@refinery = Arcane::Finder.new(object_without_refinery)
|
32
|
+
@refinery.refinery.should eq Arcane::Refinery
|
33
33
|
end
|
34
34
|
|
35
35
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Arcane::Parameters do
|
4
|
+
|
5
|
+
let(:user) { double }
|
6
|
+
let(:object) { NilModel.new }
|
7
|
+
let(:action) { :unknown }
|
8
|
+
let(:params) { nil_model_params }
|
9
|
+
let(:refinery) { NilModelRefinery }
|
10
|
+
|
11
|
+
let(:subject) { subject_class.new(params).for(object).on(action).as(user) }
|
12
|
+
let(:subject_class) { ActionController::Parameters }
|
13
|
+
|
14
|
+
describe '#for' do
|
15
|
+
it { subject.for(object).should be_a ActionController::Parameters }
|
16
|
+
it { subject.for(object).object.should eq object }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#as' do
|
20
|
+
it { subject.as(user).should be_a ActionController::Parameters }
|
21
|
+
it { subject.as(user).user.should eq user }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#on' do
|
25
|
+
it { subject.on(action).should be_a ActionController::Parameters }
|
26
|
+
it { subject.on(action).action.should eq action }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#refine' do
|
30
|
+
|
31
|
+
it { subject.refine.should be_a ActionController::Parameters }
|
32
|
+
|
33
|
+
context 'with exstensive parameters' do
|
34
|
+
|
35
|
+
let(:user) { double }
|
36
|
+
let(:object) { Article.new }
|
37
|
+
let(:params) { article_params }
|
38
|
+
|
39
|
+
it 'filters correctly' do
|
40
|
+
subject.on(:update).refine.should eq expected_params(:article,:title,:content)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'filters nested object parameters correctly' do
|
44
|
+
subject.on(:create).refine.should eq expected_params(:article,:title,:content,:links)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'filters nested scalar parameters correctly' do
|
48
|
+
subject.on(:publish).refine.should eq expected_params(:article,:title,:content,:tags)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'action is not set' do
|
54
|
+
|
55
|
+
let(:params) { nil_model_params action: 'create' }
|
56
|
+
let(:subject) { subject_class.new(params).for(object).as(user) }
|
57
|
+
|
58
|
+
it 'uses the params to determine refinery action' do
|
59
|
+
NilModelRefinery.any_instance.should_receive :create
|
60
|
+
subject.refine
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'uses the options to determine refinery action' do
|
64
|
+
NilModelRefinery.any_instance.should_receive :create
|
65
|
+
subject.refine action: :create
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'user is not set' do
|
71
|
+
|
72
|
+
let(:user) { double(name: :test) }
|
73
|
+
let(:subject) { subject_class.new(params).for(object).on(action) }
|
74
|
+
|
75
|
+
it 'uses user from options' do
|
76
|
+
expect(subject).to receive(:user).once
|
77
|
+
subject.refine(user: user)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/spec/arcane_spec.rb
CHANGED
@@ -2,99 +2,22 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Arcane do
|
4
4
|
|
5
|
-
let(:user)
|
6
|
-
let(:
|
7
|
-
let(:
|
8
|
-
let(:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
content: "world",
|
14
|
-
links: [
|
15
|
-
{ blog: "http://blog.example.com" },
|
16
|
-
{ site: "http://www.example.com" },
|
17
|
-
],
|
18
|
-
tags: ["test","greeting"]
|
19
|
-
}
|
20
|
-
})
|
21
|
-
end
|
22
|
-
let(:custom_params) do
|
23
|
-
HashWithIndifferentAccess.new({
|
24
|
-
article: {
|
25
|
-
tags: ["test","greeting"]
|
26
|
-
}
|
27
|
-
})
|
28
|
-
end
|
29
|
-
|
30
|
-
describe '#refine' do
|
31
|
-
|
32
|
-
it { controller.refine(article).should be_a Arcane::Chain }
|
33
|
-
it { controller.refine(article,:update).should be_a ActionController::Parameters }
|
34
|
-
it { controller.refine(article).update.should be_a ActionController::Parameters }
|
35
|
-
it { controller.refine(Article)._object.should be_a Article }
|
36
|
-
|
37
|
-
context 'without supplying a refinery method' do
|
38
|
-
|
39
|
-
let(:params) do
|
40
|
-
HashWithIndifferentAccess.new({
|
41
|
-
action: 'create',
|
42
|
-
comment: {
|
43
|
-
content: "Awesome!",
|
44
|
-
score: 5
|
45
|
-
}
|
46
|
-
})
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'still returns a parameters hash' do
|
50
|
-
controller.refine(comment).should be_a ActionController::Parameters
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'finds the right method' do
|
54
|
-
controller.refine(comment).should eq expected_params(:comment,:score,:content)
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'using a missing refinery method' do
|
58
|
-
|
59
|
-
let(:params) do
|
60
|
-
HashWithIndifferentAccess.new({
|
61
|
-
action: 'update',
|
62
|
-
comment: {
|
63
|
-
content: "Awesome!",
|
64
|
-
score: 5
|
65
|
-
}
|
66
|
-
})
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'falls back on default' do
|
70
|
-
controller.refine(comment).should eq expected_params(:comment,:score)
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'filters parameters correctly' do
|
78
|
-
controller.refine(article).update.should eq expected_params(:article,:title,:content)
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'filters nested object parameters correctly' do
|
82
|
-
controller.refine(article).create.should eq expected_params(:article,:title,:content,:links)
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'filters nested scalar parameters correctly' do
|
86
|
-
controller.refine(article).publish.should eq expected_params(:article,:title,:content,:tags)
|
5
|
+
let(:user) { double(name: :user) }
|
6
|
+
let(:parameters) { nil_model_params }
|
7
|
+
let(:controller) { double(request: request, current_user: user).tap { |c| c.extend(Arcane) } }
|
8
|
+
let(:request) { double(parameters: parameters) }
|
9
|
+
|
10
|
+
describe '#params' do
|
11
|
+
it 'sets the user for parameters' do
|
12
|
+
controller.params.user.should eq user
|
87
13
|
end
|
14
|
+
end
|
88
15
|
|
89
|
-
|
90
|
-
|
91
|
-
controller.
|
16
|
+
describe '#params=' do
|
17
|
+
it 'sets the user for parameters' do
|
18
|
+
controller.params = { foo: :bar }
|
19
|
+
controller.instance_variable_get(:@_params).user.should eq user
|
92
20
|
end
|
93
|
-
|
94
21
|
end
|
95
22
|
|
96
|
-
end
|
97
|
-
|
98
|
-
def expected_params(object_name,*includes)
|
99
|
-
params[object_name].reject { |k,_| !includes.include? k.to_sym }
|
100
23
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,19 @@ require "pry"
|
|
3
3
|
require "active_support/core_ext"
|
4
4
|
require "active_model/naming"
|
5
5
|
|
6
|
+
class NilModel; end
|
7
|
+
class NilModelRefinery < Struct.new(:object,:user)
|
8
|
+
|
9
|
+
def create
|
10
|
+
[:attribute]
|
11
|
+
end
|
12
|
+
|
13
|
+
def default
|
14
|
+
create
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
6
19
|
class Article; end
|
7
20
|
class ArticleRefinery < Arcane::Refinery
|
8
21
|
|
@@ -46,4 +59,30 @@ class CommentRefinery < Arcane::Refinery
|
|
46
59
|
[:score]
|
47
60
|
end
|
48
61
|
|
62
|
+
end
|
63
|
+
|
64
|
+
def article_params
|
65
|
+
ActionController::Parameters.new({
|
66
|
+
action: 'create',
|
67
|
+
article: {
|
68
|
+
title: "hello",
|
69
|
+
content: "world",
|
70
|
+
links: [
|
71
|
+
{ blog: "http://blog.example.com" },
|
72
|
+
{ site: "http://www.example.com" },
|
73
|
+
],
|
74
|
+
tags: ["test","greeting"]
|
75
|
+
}
|
76
|
+
})
|
77
|
+
end
|
78
|
+
|
79
|
+
def nil_model_params(opts={})
|
80
|
+
ActionController::Parameters.new({
|
81
|
+
action: 'unknown',
|
82
|
+
nil_model: { attribute: :value }
|
83
|
+
}).merge(opts)
|
84
|
+
end
|
85
|
+
|
86
|
+
def expected_params(object_name,*includes)
|
87
|
+
params[object_name].reject { |k,_| !includes.include? k.to_sym }
|
49
88
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arcane
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0.pre
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Philip Vieira
|
@@ -10,60 +9,53 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-12 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: activesupport
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: 3.0.0
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - '>='
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: 3.0.0
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: strong_parameters
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - '>='
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: 0.2.0
|
39
35
|
type: :runtime
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '>='
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: 0.2.0
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: activerecord
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - '>='
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: 3.0.0
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - '>='
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: 3.0.0
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: rspec
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
60
|
- - ~>
|
69
61
|
- !ruby/object:Gem::Version
|
@@ -71,7 +63,6 @@ dependencies:
|
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
67
|
- - ~>
|
77
68
|
- !ruby/object:Gem::Version
|
@@ -79,33 +70,29 @@ dependencies:
|
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: pry
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
|
-
- -
|
74
|
+
- - '>='
|
85
75
|
- !ruby/object:Gem::Version
|
86
76
|
version: '0'
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
|
-
- -
|
81
|
+
- - '>='
|
93
82
|
- !ruby/object:Gem::Version
|
94
83
|
version: '0'
|
95
84
|
- !ruby/object:Gem::Dependency
|
96
85
|
name: rake
|
97
86
|
requirement: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
87
|
requirements:
|
100
|
-
- -
|
88
|
+
- - '>='
|
101
89
|
- !ruby/object:Gem::Version
|
102
90
|
version: '0'
|
103
91
|
type: :development
|
104
92
|
prerelease: false
|
105
93
|
version_requirements: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
94
|
requirements:
|
108
|
-
- -
|
95
|
+
- - '>='
|
109
96
|
- !ruby/object:Gem::Version
|
110
97
|
version: '0'
|
111
98
|
description: Parameter filter done OO, extending strong parameters.
|
@@ -125,49 +112,42 @@ files:
|
|
125
112
|
- Rakefile
|
126
113
|
- arcane.gemspec
|
127
114
|
- lib/arcane.rb
|
128
|
-
- lib/arcane/chain.rb
|
129
115
|
- lib/arcane/finder.rb
|
116
|
+
- lib/arcane/parameters.rb
|
130
117
|
- lib/arcane/refinery.rb
|
131
118
|
- lib/arcane/version.rb
|
132
|
-
- spec/arcane/chain_spec.rb
|
133
119
|
- spec/arcane/finder_spec.rb
|
120
|
+
- spec/arcane/parameters_spec.rb
|
134
121
|
- spec/arcane/refinery_spec.rb
|
135
122
|
- spec/arcane_spec.rb
|
136
123
|
- spec/spec_helper.rb
|
137
124
|
homepage: https://github.com/cloudsdaleapp/arcane
|
138
125
|
licenses:
|
139
126
|
- MIT
|
127
|
+
metadata: {}
|
140
128
|
post_install_message:
|
141
129
|
rdoc_options: []
|
142
130
|
require_paths:
|
143
131
|
- lib
|
144
132
|
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
133
|
requirements:
|
147
|
-
- -
|
134
|
+
- - '>='
|
148
135
|
- !ruby/object:Gem::Version
|
149
136
|
version: '0'
|
150
|
-
segments:
|
151
|
-
- 0
|
152
|
-
hash: 1025235848978620495
|
153
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
-
none: false
|
155
138
|
requirements:
|
156
|
-
- -
|
139
|
+
- - '>'
|
157
140
|
- !ruby/object:Gem::Version
|
158
|
-
version:
|
159
|
-
segments:
|
160
|
-
- 0
|
161
|
-
hash: 1025235848978620495
|
141
|
+
version: 1.3.1
|
162
142
|
requirements: []
|
163
143
|
rubyforge_project:
|
164
|
-
rubygems_version:
|
144
|
+
rubygems_version: 2.0.3
|
165
145
|
signing_key:
|
166
|
-
specification_version:
|
146
|
+
specification_version: 4
|
167
147
|
summary: Extension for strong_parameters.
|
168
148
|
test_files:
|
169
|
-
- spec/arcane/chain_spec.rb
|
170
149
|
- spec/arcane/finder_spec.rb
|
150
|
+
- spec/arcane/parameters_spec.rb
|
171
151
|
- spec/arcane/refinery_spec.rb
|
172
152
|
- spec/arcane_spec.rb
|
173
153
|
- spec/spec_helper.rb
|
data/lib/arcane/chain.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
module Arcane
|
2
|
-
|
3
|
-
class Chain
|
4
|
-
|
5
|
-
attr_reader :_params, :_user, :_object, :_arcane, :_arcane_class
|
6
|
-
|
7
|
-
def initialize(_params,_object,_user)
|
8
|
-
@_user = _user
|
9
|
-
@_object = _object
|
10
|
-
@_params = ActionController::Parameters.new(_params)
|
11
|
-
@_arcane_class = Arcane::Finder.new(_object).arcane
|
12
|
-
@_arcane = @_arcane_class.new(_object,_user)
|
13
|
-
end
|
14
|
-
|
15
|
-
def method_missing(_arcane_method,*args)
|
16
|
-
|
17
|
-
if _arcane.respond_to?(_arcane_method)
|
18
|
-
_computed = _arcane.public_send(_arcane_method)
|
19
|
-
elsif _arcane.respond_to?(:default)
|
20
|
-
_computed = _arcane.default
|
21
|
-
else
|
22
|
-
_computed = []
|
23
|
-
end
|
24
|
-
|
25
|
-
if _arcane.respond_to?(:root)
|
26
|
-
_root = arcane.root
|
27
|
-
elsif _arcane_class.respond_to?(:root)
|
28
|
-
_root = _arcane_class.root
|
29
|
-
else
|
30
|
-
_root = Arcane::Finder.object_name(_object)
|
31
|
-
end
|
32
|
-
|
33
|
-
if _root.present?
|
34
|
-
_params.require(_root.parameterize).permit(*_computed)
|
35
|
-
else
|
36
|
-
_params.permit(*_computed)
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
data/spec/arcane/chain_spec.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Arcane::Chain do
|
4
|
-
|
5
|
-
let(:chain) { Arcane::Chain.new(params,object,user) }
|
6
|
-
|
7
|
-
let(:user) { double }
|
8
|
-
let(:object) { Article.new }
|
9
|
-
let(:arcane_class) { ArticleRefinery }
|
10
|
-
let(:params) { ActionController::Parameters.new(hash_params) }
|
11
|
-
let(:hash_params) do
|
12
|
-
{
|
13
|
-
article: {
|
14
|
-
title: "hello",
|
15
|
-
content: "world",
|
16
|
-
links: [
|
17
|
-
{ blog: "http://blog.example.com" },
|
18
|
-
{ site: "http://www.example.com" },
|
19
|
-
]
|
20
|
-
}
|
21
|
-
}
|
22
|
-
end
|
23
|
-
|
24
|
-
describe '.new' do
|
25
|
-
|
26
|
-
it 'sets attributes' do
|
27
|
-
chain._params.should eq(params)
|
28
|
-
chain._object.should eq(object)
|
29
|
-
chain._user.should eq(user)
|
30
|
-
chain._arcane.should be_a(arcane_class)
|
31
|
-
chain._arcane_class.should eq(arcane_class)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'converts the object to ActionController::Parameters' do
|
35
|
-
chain = Arcane::Chain.new(hash_params,object,user)
|
36
|
-
chain._params.should be_a ActionController::Parameters
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
describe '#method_missing' do
|
42
|
-
|
43
|
-
it 'returns the filtered parameters' do
|
44
|
-
chain.void_method.should be_a ActionController::Parameters
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'filters the same as the default constraint' do
|
48
|
-
chain.void_method.should eq chain.default
|
49
|
-
end
|
50
|
-
|
51
|
-
context 'without root in params' do
|
52
|
-
let(:chain) { Arcane::Chain.new(params[:article],object,user) }
|
53
|
-
it 'raises an error' do
|
54
|
-
expect { chain.void_method }.to raise_error ActionController::ParameterMissing
|
55
|
-
end
|
56
|
-
it 'successds with nil root in arcane' do
|
57
|
-
arcane_class.stub(:root) { false }
|
58
|
-
expect { chain.void_method }.to_not raise_error
|
59
|
-
arcane_class.stub(:root) { nil }
|
60
|
-
expect { chain.void_method }.to_not raise_error
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|