adequate_exposure 0.0.5 → 0.0.6
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 +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
|