adequate_exposure 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -15
- data/lib/adequate_exposure/controller.rb +17 -6
- data/lib/adequate_exposure/exposure.rb +48 -12
- data/lib/adequate_exposure/version.rb +1 -1
- data/lib/adequate_exposure.rb +1 -1
- data/spec/controller_spec.rb +41 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15f771dd9996bd2a1920e2f00dbc487e568d84ce
|
4
|
+
data.tar.gz: 9db2690bceba1225904077e793d780813f968774
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5cbf18ca89f1b543a5ef99f19059beb805991238219835d827d2090b387bfb5c8c832b10a911f287f88f4bb274ca041e3353b13d91b17e71eb544e6b12c5ee6
|
7
|
+
data.tar.gz: e97dc7d95fe518d7b19a9e93ffd978240eb11de1a1ab6499777c15e6e548c36b581107eaf510e1a959929b4e4f3228da79a3b2402f84c4cef8f577b9afcef477
|
data/README.md
CHANGED
@@ -17,7 +17,8 @@ that down we can start talking about the API.
|
|
17
17
|
|
18
18
|
## API
|
19
19
|
|
20
|
-
The whole API consists of
|
20
|
+
The whole API consists of three methods so far: `expose`, `expose!`, and
|
21
|
+
`exposure_config`.
|
21
22
|
|
22
23
|
In the simplest scenario you'll just use it to expose a model in the
|
23
24
|
controller:
|
@@ -33,7 +34,7 @@ ID and try to perform `Thing.find(id)`. If the ID isn't found, it'll call
|
|
33
34
|
`Thing.new(things_params)`. The result will be memoized in an `@exposed_thing`
|
34
35
|
instance variable.
|
35
36
|
|
36
|
-
The default resolving workflow
|
37
|
+
The default resolving workflow is pretty powerful and customizable. It could be
|
37
38
|
expressed with the following pseudocode:
|
38
39
|
|
39
40
|
```ruby
|
@@ -108,7 +109,7 @@ Or if you (like me) absolutely hate parens in side-effect methods:
|
|
108
109
|
expose :thing, ->{ get_thing_some_way_or_another }
|
109
110
|
```
|
110
111
|
|
111
|
-
There is another shortcut that allows you to redefine entire fetch block with
|
112
|
+
There is another shortcut that allows you to redefine the entire fetch block with
|
112
113
|
less code:
|
113
114
|
|
114
115
|
```ruby
|
@@ -120,7 +121,7 @@ expose :comments, ->{ post.comments }
|
|
120
121
|
### `id`
|
121
122
|
|
122
123
|
The default fetch logic relies on the presence of an ID. And of course Adequate
|
123
|
-
Exposure allows
|
124
|
+
Exposure allows you to specify how exactly you want the ID to be extracted.
|
124
125
|
|
125
126
|
Default behavior could be expressed using following code:
|
126
127
|
|
@@ -136,15 +137,17 @@ But nothing is stopping you from throwing in any arbitrary code:
|
|
136
137
|
expose :thing, id: ->{ 42 }
|
137
138
|
```
|
138
139
|
|
139
|
-
Passing lambdas might not always be fun, so here are couple shortcuts that could
|
140
|
-
help
|
140
|
+
Passing lambdas might not always be fun, so here are a couple of shortcuts that could
|
141
|
+
help make life easier.
|
141
142
|
|
142
143
|
```ruby
|
143
|
-
# equivalent to id: ->{ params[:custom_thing_id] }
|
144
144
|
expose :thing, id: :custom_thing_id
|
145
|
+
# equivalent to
|
146
|
+
expose :thing, id: ->{ params[:custom_thing_id] }
|
145
147
|
|
146
|
-
# equivalent to id: ->{ params[:try_this_id] || params[:or_maybe_that_id] }
|
147
148
|
expose :thing, id: [:try_this_id, :or_maybe_that_id]
|
149
|
+
# equivalent to
|
150
|
+
expose :thing, id: ->{ params[:try_this_id] || params[:or_maybe_that_id] }
|
148
151
|
```
|
149
152
|
|
150
153
|
### `find`
|
@@ -160,7 +163,7 @@ Where `scope` is a model scope, like `Thing` or `User.active` or
|
|
160
163
|
`Post.published`.
|
161
164
|
|
162
165
|
Now, if you're using FriendlyId or Stringex or something similar, you'd have to
|
163
|
-
customize your finding logic.
|
166
|
+
customize your finding logic. Your code might look somewhat like this:
|
164
167
|
|
165
168
|
```ruby
|
166
169
|
expose :thing, find: ->(id, scope){ scope.find_by!(slug: id) }
|
@@ -184,10 +187,10 @@ expose :thing, build: ->(thing_params, scope){ scope.new(thing_params) }
|
|
184
187
|
|
185
188
|
### `build_params`
|
186
189
|
|
187
|
-
|
190
|
+
These options are responsible for calulating params before passing them to the
|
188
191
|
build step. The default behavior was modeled with Strong Parameters in mind and
|
189
|
-
is somewhat smart: it calls `thing_params` controller method if it's available
|
190
|
-
and request method it not `GET`. In all other cases it produces an empty hash.
|
192
|
+
is somewhat smart: it calls the `thing_params` controller method if it's available
|
193
|
+
and the request method it not `GET`. In all other cases it produces an empty hash.
|
191
194
|
|
192
195
|
You can easily specify which controller method you want it to call instead of
|
193
196
|
`thing_params`, or just provide your own logic:
|
@@ -217,7 +220,7 @@ Like before, shortcuts are there to make you happier:
|
|
217
220
|
|
218
221
|
```ruby
|
219
222
|
expose :post, scope: :published
|
220
|
-
#
|
223
|
+
# equivalent to
|
221
224
|
expose :post, scope: ->{ Post.published }
|
222
225
|
```
|
223
226
|
|
@@ -225,13 +228,13 @@ and
|
|
225
228
|
|
226
229
|
```ruby
|
227
230
|
expose :thing, parent: :current_user
|
228
|
-
#
|
231
|
+
# equivalent to:
|
229
232
|
expose :thing, scope: ->{ current_user.things }
|
230
233
|
```
|
231
234
|
|
232
235
|
### `model`
|
233
236
|
|
234
|
-
Allows to specify the model class to use. Pretty straightforward.
|
237
|
+
Allows you to specify the model class to use. Pretty straightforward.
|
235
238
|
|
236
239
|
```ruby
|
237
240
|
expose :thing, model: ->{ AnotherThing }
|
@@ -250,6 +253,20 @@ that:
|
|
250
253
|
expose :thing, decorate: ->(thing){ ThingDecorator.new(thing) }
|
251
254
|
```
|
252
255
|
|
256
|
+
## `exposure_config`
|
257
|
+
|
258
|
+
You can pre-save some configuration using `exposure_config` method reuse it
|
259
|
+
later.
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
exposure_config :cool_find, find: ->{ very_cool_find_code }
|
263
|
+
exposure_config :cool_build, build: ->{ very_cool_build_code }
|
264
|
+
|
265
|
+
expose :thing, with: [:cool_find, :cool_build]
|
266
|
+
expose :another_thing, with: :cool_build
|
267
|
+
```
|
268
|
+
|
269
|
+
|
253
270
|
## Contributing
|
254
271
|
|
255
272
|
1. Fork it (https://github.com/rwz/adequate_exposure/fork)
|
@@ -1,12 +1,23 @@
|
|
1
1
|
module AdequateExposure
|
2
2
|
module Controller
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included{ class_attribute :exposure_configuration }
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def expose(*args, &block)
|
9
|
+
Exposure.expose! self, *args, &block
|
10
|
+
end
|
11
|
+
|
12
|
+
def expose!(name, *args, &block)
|
13
|
+
expose name, *args, &block
|
14
|
+
before_action name
|
15
|
+
end
|
6
16
|
|
7
|
-
|
8
|
-
|
9
|
-
|
17
|
+
def exposure_config(name, options)
|
18
|
+
store = self.exposure_configuration ||= {}
|
19
|
+
self.exposure_configuration = store.merge(name => options)
|
20
|
+
end
|
10
21
|
end
|
11
22
|
end
|
12
23
|
end
|
@@ -41,12 +41,51 @@ module AdequateExposure
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def normalize_options
|
44
|
+
normalize_with_option
|
45
|
+
normalize_id_option
|
46
|
+
normalize_model_option
|
47
|
+
normalize_build_params_option
|
48
|
+
normalize_scope_options
|
49
|
+
normalize_parent_option
|
50
|
+
normalize_from_option
|
51
|
+
normalize_find_by_option
|
52
|
+
end
|
53
|
+
|
54
|
+
def normalize_find_by_option
|
55
|
+
if find_by = options.delete(:find_by)
|
56
|
+
merge_lambda_option :find, ->(id, scope){ scope.find_by!(find_by => id) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def normalize_parent_option
|
61
|
+
exposure_name = options.fetch(:name)
|
62
|
+
|
63
|
+
if parent = options.delete(:parent)
|
64
|
+
merge_lambda_option :scope, ->{ send(parent).send(exposure_name.to_s.pluralize) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def normalize_from_option
|
44
69
|
exposure_name = options.fetch(:name)
|
45
70
|
|
71
|
+
if from = options.delete(:from)
|
72
|
+
merge_lambda_option :fetch, ->{ send(from).send(exposure_name) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def normalize_with_option
|
77
|
+
if configs = options.delete(:with)
|
78
|
+
Array.wrap(configs).each{ |config| reverse_merge_config! config }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def normalize_id_option
|
46
83
|
normalize_non_proc_option :id do |ids|
|
47
84
|
->{ Array.wrap(ids).map{ |id| params[id] }.find(&:present?) }
|
48
85
|
end
|
86
|
+
end
|
49
87
|
|
88
|
+
def normalize_model_option
|
50
89
|
normalize_non_proc_option :model do |value|
|
51
90
|
model = if [String, Symbol].include?(value.class)
|
52
91
|
value.to_s.classify.constantize
|
@@ -56,27 +95,19 @@ module AdequateExposure
|
|
56
95
|
|
57
96
|
->{ model }
|
58
97
|
end
|
98
|
+
end
|
59
99
|
|
100
|
+
def normalize_build_params_option
|
60
101
|
normalize_non_proc_option :build_params do |value|
|
61
102
|
options[:build_params_method] = value
|
62
103
|
nil
|
63
104
|
end
|
105
|
+
end
|
64
106
|
|
107
|
+
def normalize_scope_options
|
65
108
|
normalize_non_proc_option :scope do |custom_scope|
|
66
109
|
->(model){ model.send(custom_scope) }
|
67
110
|
end
|
68
|
-
|
69
|
-
if parent = options.delete(:parent)
|
70
|
-
merge_lambda_option :scope, ->{ send(parent).send(exposure_name.to_s.pluralize) }
|
71
|
-
end
|
72
|
-
|
73
|
-
if from = options.delete(:from)
|
74
|
-
merge_lambda_option :fetch, ->{ send(from).send(exposure_name) }
|
75
|
-
end
|
76
|
-
|
77
|
-
if find_by = options.delete(:find_by)
|
78
|
-
merge_lambda_option :find, ->(id, scope){ scope.find_by!(find_by => id) }
|
79
|
-
end
|
80
111
|
end
|
81
112
|
|
82
113
|
def normalize_non_proc_option(name)
|
@@ -127,5 +158,10 @@ module AdequateExposure
|
|
127
158
|
fail ArgumentError, "Using #{name.inspect} option with other options doesn't make sense"
|
128
159
|
end
|
129
160
|
end
|
161
|
+
|
162
|
+
def reverse_merge_config!(name)
|
163
|
+
config = controller.exposure_configuration.fetch(name)
|
164
|
+
options.reverse_merge! config
|
165
|
+
end
|
130
166
|
end
|
131
167
|
end
|
data/lib/adequate_exposure.rb
CHANGED
data/spec/controller_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe AdequateExposure::Controller do
|
|
14
14
|
|
15
15
|
let(:controller_klass) do
|
16
16
|
Class.new(BaseController) do
|
17
|
-
|
17
|
+
include AdequateExposure::Controller
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -22,7 +22,7 @@ describe AdequateExposure::Controller do
|
|
22
22
|
let(:controller){ controller_klass.new }
|
23
23
|
before{ allow(controller).to receive(:request){ request } }
|
24
24
|
|
25
|
-
%w[expose expose!].each do |method_name|
|
25
|
+
%w[expose expose! exposure_config].each do |method_name|
|
26
26
|
define_method method_name do |*args, &block|
|
27
27
|
controller_klass.send method_name, *args, &block
|
28
28
|
end
|
@@ -54,6 +54,45 @@ describe AdequateExposure::Controller do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
context ".exposure_config" do
|
58
|
+
it "subclass configration doesn't propagate to superclass" do
|
59
|
+
controller_subklass = Class.new(controller_klass)
|
60
|
+
controller_klass.exposure_config :foo, :bar
|
61
|
+
controller_subklass.exposure_config :foo, :lol
|
62
|
+
controller_subklass.exposure_config :fizz, :buzz
|
63
|
+
expect(controller_subklass.exposure_configuration).to eq(foo: :lol, fizz: :buzz)
|
64
|
+
expect(controller_klass.exposure_configuration).to eq(foo: :bar)
|
65
|
+
end
|
66
|
+
|
67
|
+
context "applying" do
|
68
|
+
let(:thing){ double("Thing") }
|
69
|
+
|
70
|
+
before do
|
71
|
+
exposure_config :sluggable, find_by: :slug
|
72
|
+
exposure_config :weird_id_name, id: :check_this_out
|
73
|
+
exposure_config :another_id_name, id: :whee
|
74
|
+
controller.params.merge! check_this_out: "foo", whee: "wut"
|
75
|
+
end
|
76
|
+
|
77
|
+
after{ expect(controller.thing).to eq(thing) }
|
78
|
+
|
79
|
+
it "can be reused later" do
|
80
|
+
expose :thing, with: :weird_id_name
|
81
|
+
expect(Thing).to receive(:find).with("foo").and_return(thing)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "can apply multple configs at once" do
|
85
|
+
expose :thing, with: [:weird_id_name, :sluggable]
|
86
|
+
expect(Thing).to receive(:find_by!).with(slug: "foo").and_return(thing)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "applies multiple configs in a correct order" do
|
90
|
+
expose :thing, with: [:another_id_name, :weird_id_name]
|
91
|
+
expect(Thing).to receive(:find).with("wut").and_return(thing)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
57
96
|
context "with block" do
|
58
97
|
before{ expose(:thing){ compute_thing } }
|
59
98
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adequate_exposure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Pravosud
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|