decent_exposure 3.0.0.beta2 → 3.0.4
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 +5 -5
- data/.travis.yml +1 -1
- data/CHANGELOG.md +19 -0
- data/Gemfile +1 -1
- data/README.md +40 -5
- data/decent_exposure.gemspec +14 -12
- data/gemfiles/{Gemfile.rails-5.0.0.rc1 → Gemfile.rails-5.0.0} +1 -1
- data/lib/decent_exposure.rb +11 -5
- data/lib/decent_exposure/attribute.rb +0 -1
- data/lib/decent_exposure/behavior.rb +1 -1
- data/lib/decent_exposure/context.rb +2 -2
- data/lib/decent_exposure/controller.rb +4 -4
- data/lib/decent_exposure/exposure.rb +24 -23
- data/lib/decent_exposure/flow.rb +2 -3
- data/lib/decent_exposure/mailer.rb +15 -0
- data/lib/decent_exposure/version.rb +1 -1
- data/lib/generators/decent_exposure/scaffold_templates_generator.rb +7 -7
- data/spec/{controller_spec.rb → decent_exposure/controller_spec.rb} +47 -41
- data/spec/features/api_birds_controller_spec.rb +70 -0
- data/spec/features/birds_controller_spec.rb +77 -0
- data/spec/features/birds_mailer_spec.rb +54 -0
- data/spec/generators/decent_exposure/scaffold_templates_generator_spec.rb +19 -20
- data/spec/support/rails_app.rb +39 -7
- metadata +48 -16
- data/hashrocket_logo.png +0 -0
- data/spec/integration_spec.rb +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7f14b1fe6ed0c7cfea5f043262895e4f17bbd9cdd8f019259d8d0a44fb1f9f98
|
|
4
|
+
data.tar.gz: b5e0989425e1f94847b6867c4a0e81bd87d07a9fcd2683c9d64412700f7fd0d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 705363f8c4b0fe230b6a25b3e171e74f936d1d1bc34af6a10b809d8283324c2b7a249e00d5455f5c2cec28944cf3aee94f0c2487b1c45f2b99a8ba0e60e732a8
|
|
7
|
+
data.tar.gz: d784e10c482a0a9e35c4aa21cf51632d6d0d28c0055f1f0b302259505c8b4f2d7feac9208af402a02a799ffca444c81d89f52ed278ef380096f1e6b45b30100c
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# DecentExposure History/Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
5
|
+
|
|
6
|
+
## 3.0.2
|
|
7
|
+
|
|
8
|
+
* Fix mailers when arguments are not a hash.
|
|
9
|
+
|
|
10
|
+
## 3.0.1
|
|
11
|
+
|
|
12
|
+
* Allow exposures with a question mark (?).
|
|
13
|
+
* Remove setter from view helper.
|
|
14
|
+
* Fix undefined `helper_method` error
|
|
15
|
+
|
|
16
|
+
## 3.0.0
|
|
17
|
+
|
|
18
|
+
* New codebase, see [api changes document](https://github.com/hashrocket/decent_exposure/wiki/Api-changes-in-version-3).
|
|
19
|
+
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Version `3.0` will support Rails 4 and 5.
|
|
|
18
18
|
Add this line to your application's Gemfile:
|
|
19
19
|
|
|
20
20
|
```ruby
|
|
21
|
-
gem 'decent_exposure', '3.0.0
|
|
21
|
+
gem 'decent_exposure', '3.0.0'
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
And then execute:
|
|
@@ -45,7 +45,7 @@ end
|
|
|
45
45
|
|
|
46
46
|
Now every time you call `thing` in your controller or view, it will look for an
|
|
47
47
|
ID and try to perform `Thing.find(id)`. If the ID isn't found, it will call
|
|
48
|
-
`Thing.new(
|
|
48
|
+
`Thing.new(thing_params)`. The result will be memoized in an `@exposed_thing`
|
|
49
49
|
instance variable.
|
|
50
50
|
|
|
51
51
|
#### Example Controller
|
|
@@ -309,6 +309,7 @@ decoration process. Initially, this does nothing, but you can obviously change
|
|
|
309
309
|
that:
|
|
310
310
|
|
|
311
311
|
```ruby
|
|
312
|
+
expose :things, ->{ Thing.all.map{ |thing| ThingDecorator.new(thing) } }
|
|
312
313
|
expose :thing, decorate: ->(thing){ ThingDecorator.new(thing) }
|
|
313
314
|
```
|
|
314
315
|
|
|
@@ -325,6 +326,29 @@ expose :thing, with: [:cool_find, :cool_build]
|
|
|
325
326
|
expose :another_thing, with: :cool_build
|
|
326
327
|
```
|
|
327
328
|
|
|
329
|
+
## Rails Mailers
|
|
330
|
+
|
|
331
|
+
Mailers and Controllers use the same decent_exposure dsl.
|
|
332
|
+
|
|
333
|
+
### Example Mailer
|
|
334
|
+
|
|
335
|
+
```ruby
|
|
336
|
+
class PostMailer < ApplicationMailer
|
|
337
|
+
expose(:posts, -> { Post.last(10) })
|
|
338
|
+
expose(:post)
|
|
339
|
+
|
|
340
|
+
def top_posts
|
|
341
|
+
@greeting = "Top Posts"
|
|
342
|
+
mail to: "to@example.org"
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def featured_post(id:)
|
|
346
|
+
@greeting = "Featured Post"
|
|
347
|
+
mail to: "to@example.org"
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
```
|
|
351
|
+
|
|
328
352
|
## Rails Scaffold Templates
|
|
329
353
|
|
|
330
354
|
If you want to generate rails scaffold templates prepared for `decent_exposure` run:
|
|
@@ -333,7 +357,18 @@ If you want to generate rails scaffold templates prepared for `decent_exposure`
|
|
|
333
357
|
rails generate decent_exposure:scaffold_templates [--template_engine erb|haml]
|
|
334
358
|
```
|
|
335
359
|
|
|
336
|
-
This will create the templates in your `lib/templates` folder.
|
|
360
|
+
This will create the templates in your `lib/templates` folder.
|
|
361
|
+
|
|
362
|
+
Make sure you have configured your templates engine for generators in `config/application.rb`:
|
|
363
|
+
|
|
364
|
+
```ruby
|
|
365
|
+
# config/application.rb
|
|
366
|
+
config.generators do |g|
|
|
367
|
+
g.template_engine :erb
|
|
368
|
+
end
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Now you can run scaffold like:
|
|
337
372
|
|
|
338
373
|
```bash
|
|
339
374
|
rails generate scaffold post title description:text
|
|
@@ -349,6 +384,6 @@ rails generate scaffold post title description:text
|
|
|
349
384
|
|
|
350
385
|
## About
|
|
351
386
|
|
|
352
|
-
[](https://hashrocket.com)
|
|
353
388
|
|
|
354
|
-
Decent Exposure is supported by the team at [Hashrocket](https://hashrocket.com), a multidisciplinary design & development consultancy. If you'd like to [work with us](https://hashrocket.com/contact
|
|
389
|
+
Decent Exposure is supported by the team at [Hashrocket](https://hashrocket.com), a multidisciplinary design & development consultancy. If you'd like to [work with us](https://hashrocket.com/contact) or [join our team](https://hashrocket.com/careers), don't hesitate to get in touch.
|
data/decent_exposure.gemspec
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
require File.expand_path("../lib/decent_exposure/version", __FILE__)
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
|
-
spec.name
|
|
5
|
-
spec.version
|
|
6
|
-
spec.authors
|
|
7
|
-
spec.email
|
|
8
|
-
spec.summary
|
|
9
|
-
spec.description =
|
|
4
|
+
spec.name = "decent_exposure"
|
|
5
|
+
spec.version = DecentExposure::VERSION
|
|
6
|
+
spec.authors = ["Pavel Pravosud", "Stephen Caudill"]
|
|
7
|
+
spec.email = ["info@hashrocket.com"]
|
|
8
|
+
spec.summary = "A helper for creating declarative interfaces in controllers"
|
|
9
|
+
spec.description = '
|
|
10
10
|
DecentExposure helps you program to an interface, rather than an
|
|
11
11
|
implementation in your Rails controllers. The fact of the matter is that
|
|
12
12
|
sharing state via instance variables in controllers promotes close coupling
|
|
13
13
|
with views. DecentExposure gives you a declarative manner of exposing an
|
|
14
14
|
interface to the state that controllers contain and thereby decreasing
|
|
15
15
|
coupling and improving your testability and overall design.
|
|
16
|
-
|
|
17
|
-
spec.homepage
|
|
18
|
-
spec.license
|
|
19
|
-
spec.files
|
|
20
|
-
spec.test_files
|
|
16
|
+
'
|
|
17
|
+
spec.homepage = "https://github.com/hashrocket/decent_exposure"
|
|
18
|
+
spec.license = "MIT"
|
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
20
|
+
spec.test_files = spec.files.grep(/\Aspec\//)
|
|
21
21
|
spec.require_path = "lib"
|
|
22
22
|
|
|
23
|
-
spec.required_ruby_version = "
|
|
23
|
+
spec.required_ruby_version = ">= 2.0"
|
|
24
24
|
|
|
25
25
|
spec.add_dependency "activesupport", ">= 4.0"
|
|
26
26
|
spec.add_development_dependency "railties", ">= 4.0"
|
|
27
|
+
spec.add_development_dependency "actionmailer"
|
|
27
28
|
spec.add_development_dependency "rspec-rails", "~> 3.0"
|
|
29
|
+
spec.add_development_dependency "standard"
|
|
28
30
|
end
|
data/lib/decent_exposure.rb
CHANGED
|
@@ -4,13 +4,19 @@ require "generators/decent_exposure/scaffold_templates_generator"
|
|
|
4
4
|
|
|
5
5
|
module DecentExposure
|
|
6
6
|
autoload :Controller, "decent_exposure/controller"
|
|
7
|
-
autoload :
|
|
8
|
-
autoload :
|
|
9
|
-
autoload :
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :
|
|
7
|
+
autoload :Mailer, "decent_exposure/mailer"
|
|
8
|
+
autoload :Exposure, "decent_exposure/exposure"
|
|
9
|
+
autoload :Attribute, "decent_exposure/attribute"
|
|
10
|
+
autoload :Context, "decent_exposure/context"
|
|
11
|
+
autoload :Behavior, "decent_exposure/behavior"
|
|
12
|
+
autoload :Flow, "decent_exposure/flow"
|
|
12
13
|
|
|
13
14
|
ActiveSupport.on_load :action_controller do
|
|
14
15
|
include Controller
|
|
15
16
|
end
|
|
17
|
+
|
|
18
|
+
ActiveSupport.on_load :action_mailer do
|
|
19
|
+
include Controller
|
|
20
|
+
include Mailer
|
|
21
|
+
end
|
|
16
22
|
end
|
|
@@ -20,7 +20,7 @@ module DecentExposure
|
|
|
20
20
|
#
|
|
21
21
|
# Returns the attribute's value.
|
|
22
22
|
def get
|
|
23
|
-
ivar_defined
|
|
23
|
+
ivar_defined? ? ivar_get : set(fetch_value)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
# Public: Write to an attribute on the context Class.
|
|
@@ -51,7 +51,7 @@ module DecentExposure
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def ivar_name
|
|
54
|
-
"@#{attribute.ivar_name}"
|
|
54
|
+
"@#{attribute.ivar_name.gsub("?", "_question_mark_")}"
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def fetch_value
|
|
@@ -17,8 +17,8 @@ module DecentExposure
|
|
|
17
17
|
#
|
|
18
18
|
# Returns the helper methods that are now defined on the class
|
|
19
19
|
# where this method is included.
|
|
20
|
-
def expose(*args, &block)
|
|
21
|
-
Exposure.expose! self, *args, &block
|
|
20
|
+
def expose(*args, **options, &block)
|
|
21
|
+
Exposure.expose! self, *args, **options, &block
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# Public: Exposes an attribute to a controller Class.
|
|
@@ -33,8 +33,8 @@ module DecentExposure
|
|
|
33
33
|
#
|
|
34
34
|
# Sets the exposed attribute to a before_action callback in the
|
|
35
35
|
# controller.
|
|
36
|
-
def expose!(name, *args, &block)
|
|
37
|
-
expose name, *args, &block
|
|
36
|
+
def expose!(name, *args, **options, &block)
|
|
37
|
+
expose name, *args, **options, &block
|
|
38
38
|
before_action name
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -13,8 +13,8 @@ module DecentExposure
|
|
|
13
13
|
# the Proc when called.
|
|
14
14
|
#
|
|
15
15
|
# Returns a collection of exposed helper methods.
|
|
16
|
-
def self.expose!(*args, &block)
|
|
17
|
-
new(*args, &block).expose!
|
|
16
|
+
def self.expose!(*args, **options, &block)
|
|
17
|
+
new(*args, **options, &block).expose!
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# Public: Initalize an Exposure with a hash of options.
|
|
@@ -34,7 +34,7 @@ module DecentExposure
|
|
|
34
34
|
# the Proc.
|
|
35
35
|
#
|
|
36
36
|
# Returns a normalized options Hash.
|
|
37
|
-
def initialize(controller, name, fetch_block=nil, **options, &block)
|
|
37
|
+
def initialize(controller, name, fetch_block = nil, **options, &block)
|
|
38
38
|
@controller = controller
|
|
39
39
|
@options = options.with_indifferent_access.merge(name: name)
|
|
40
40
|
|
|
@@ -67,8 +67,9 @@ module DecentExposure
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def expose_helper_methods!
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
return unless controller.respond_to?(:helper_method)
|
|
71
|
+
|
|
72
|
+
controller.helper_method attribute.getter_method_name
|
|
72
73
|
end
|
|
73
74
|
|
|
74
75
|
def normalize_options
|
|
@@ -85,43 +86,43 @@ module DecentExposure
|
|
|
85
86
|
|
|
86
87
|
def normalize_fetch_option
|
|
87
88
|
normalize_non_proc_option :fetch do |method_name|
|
|
88
|
-
->{ send(method_name) }
|
|
89
|
+
-> { send(method_name) }
|
|
89
90
|
end
|
|
90
91
|
end
|
|
91
92
|
|
|
92
93
|
def normalize_find_by_option
|
|
93
|
-
if find_by = options.delete(:find_by)
|
|
94
|
-
merge_lambda_option :find, ->(id, scope){ scope.find_by!(find_by => id) }
|
|
94
|
+
if (find_by = options.delete(:find_by))
|
|
95
|
+
merge_lambda_option :find, ->(id, scope) { scope.find_by!(find_by => id) }
|
|
95
96
|
end
|
|
96
97
|
end
|
|
97
98
|
|
|
98
99
|
def normalize_parent_option
|
|
99
100
|
exposure_name = options.fetch(:name)
|
|
100
101
|
|
|
101
|
-
if parent = options.delete(:parent)
|
|
102
|
-
merge_lambda_option :scope, ->{ send(parent).send(exposure_name.to_s.pluralize) }
|
|
102
|
+
if (parent = options.delete(:parent))
|
|
103
|
+
merge_lambda_option :scope, -> { send(parent).send(exposure_name.to_s.pluralize) }
|
|
103
104
|
end
|
|
104
105
|
end
|
|
105
106
|
|
|
106
107
|
def normalize_from_option
|
|
107
108
|
exposure_name = options.fetch(:name)
|
|
108
109
|
|
|
109
|
-
if from = options.delete(:from)
|
|
110
|
-
merge_lambda_option :build, ->{ send(from).send(exposure_name) }
|
|
111
|
-
merge_lambda_option :model, ->{ nil }
|
|
112
|
-
merge_lambda_option :id, ->{ nil }
|
|
110
|
+
if (from = options.delete(:from))
|
|
111
|
+
merge_lambda_option :build, -> { send(from).send(exposure_name) }
|
|
112
|
+
merge_lambda_option :model, -> { nil }
|
|
113
|
+
merge_lambda_option :id, -> { nil }
|
|
113
114
|
end
|
|
114
115
|
end
|
|
115
116
|
|
|
116
117
|
def normalize_with_option
|
|
117
|
-
if configs = options.delete(:with)
|
|
118
|
-
Array.wrap(configs).each{ |config| reverse_merge_config! config }
|
|
118
|
+
if (configs = options.delete(:with))
|
|
119
|
+
Array.wrap(configs).each { |config| reverse_merge_config! config }
|
|
119
120
|
end
|
|
120
121
|
end
|
|
121
122
|
|
|
122
123
|
def normalize_id_option
|
|
123
124
|
normalize_non_proc_option :id do |ids|
|
|
124
|
-
->{ Array.wrap(ids).map{ |id| params[id] }.find(&:present?) }
|
|
125
|
+
-> { Array.wrap(ids).map { |id| params[id] }.find(&:present?) }
|
|
125
126
|
end
|
|
126
127
|
end
|
|
127
128
|
|
|
@@ -133,7 +134,7 @@ module DecentExposure
|
|
|
133
134
|
value
|
|
134
135
|
end
|
|
135
136
|
|
|
136
|
-
->{ model }
|
|
137
|
+
-> { model }
|
|
137
138
|
end
|
|
138
139
|
end
|
|
139
140
|
|
|
@@ -146,7 +147,7 @@ module DecentExposure
|
|
|
146
147
|
|
|
147
148
|
def normalize_scope_options
|
|
148
149
|
normalize_non_proc_option :scope do |custom_scope|
|
|
149
|
-
->(model){ model.send(custom_scope) }
|
|
150
|
+
->(model) { model.send(custom_scope) }
|
|
150
151
|
end
|
|
151
152
|
end
|
|
152
153
|
|
|
@@ -164,7 +165,7 @@ module DecentExposure
|
|
|
164
165
|
end
|
|
165
166
|
|
|
166
167
|
def merge_lambda_option(name, body)
|
|
167
|
-
if previous_value = options[name]
|
|
168
|
+
if (previous_value = options[name]) && (Proc === previous_value)
|
|
168
169
|
fail ArgumentError, "#{name.to_s.titleize} block is already defined"
|
|
169
170
|
end
|
|
170
171
|
|
|
@@ -177,7 +178,7 @@ module DecentExposure
|
|
|
177
178
|
|
|
178
179
|
name = options.fetch(:name)
|
|
179
180
|
ivar_name = "exposed_#{name}"
|
|
180
|
-
fetch = ->{ Flow.new(self, local_options).fetch }
|
|
181
|
+
fetch = -> { Flow.new(self, local_options).fetch }
|
|
181
182
|
|
|
182
183
|
Attribute.new(
|
|
183
184
|
name: name,
|
|
@@ -188,13 +189,13 @@ module DecentExposure
|
|
|
188
189
|
end
|
|
189
190
|
|
|
190
191
|
def assert_incompatible_options_pair(key1, key2)
|
|
191
|
-
if options.key?(key1) && options.key?(key2)
|
|
192
|
+
if options.symbolize_keys.key?(key1) && options.symbolize_keys.key?(key2)
|
|
192
193
|
fail ArgumentError, "Using #{key1.inspect} option with #{key2.inspect} doesn't make sense"
|
|
193
194
|
end
|
|
194
195
|
end
|
|
195
196
|
|
|
196
197
|
def assert_singleton_option(name)
|
|
197
|
-
if options.except(name, :name, :decorate).any? && options.key?(name)
|
|
198
|
+
if options.symbolize_keys.except(name, :name, :decorate).any? && options.symbolize_keys.key?(name)
|
|
198
199
|
fail ArgumentError, "Using #{name.inspect} option with other options doesn't make sense"
|
|
199
200
|
end
|
|
200
201
|
end
|
data/lib/decent_exposure/flow.rb
CHANGED
|
@@ -42,11 +42,11 @@ module DecentExposure
|
|
|
42
42
|
delegate :params, to: :controller
|
|
43
43
|
|
|
44
44
|
def get_request?
|
|
45
|
-
controller.request.get?
|
|
45
|
+
controller.request.get? || controller.request.head?
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def params_method_name
|
|
49
|
-
options.fetch(:build_params_method){ "#{name}_params" }
|
|
49
|
+
options.fetch(:build_params_method) { "#{name}_params" }
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def handle_flow_method(name, *args, &block)
|
|
@@ -75,7 +75,6 @@ module DecentExposure
|
|
|
75
75
|
method.bind(self).call(*args, &block)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
|
|
79
78
|
def fetch_ivar(name)
|
|
80
79
|
ivar_name = "@#{name}"
|
|
81
80
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DecentExposure
|
|
2
|
+
module Mailer
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.class_eval do
|
|
5
|
+
attr_accessor :params
|
|
6
|
+
|
|
7
|
+
def process_action(*args)
|
|
8
|
+
arg = args.second
|
|
9
|
+
self.params = arg.stringify_keys if arg && Hash === arg
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "rails/generators"
|
|
2
2
|
|
|
3
3
|
module DecentExposure
|
|
4
4
|
module Generators
|
|
5
5
|
class ScaffoldTemplatesGenerator < Rails::Generators::Base
|
|
6
|
-
desc
|
|
7
|
-
source_root File.expand_path(
|
|
8
|
-
class_option :template_engine, desc:
|
|
6
|
+
desc "Generate DecentExposure scaffold template files"
|
|
7
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
8
|
+
class_option :template_engine, desc: "Template engine to be invoked (erb)."
|
|
9
9
|
|
|
10
|
-
VIEWS = %i
|
|
11
|
-
AVAILABLE_ENGINES = %w
|
|
10
|
+
VIEWS = %i[_form edit index new show]
|
|
11
|
+
AVAILABLE_ENGINES = %w[erb haml]
|
|
12
12
|
|
|
13
13
|
def generate
|
|
14
14
|
validate_template_engine
|
|
@@ -20,7 +20,7 @@ module DecentExposure
|
|
|
20
20
|
private
|
|
21
21
|
|
|
22
22
|
def generate_controller
|
|
23
|
-
copy_template(
|
|
23
|
+
copy_template("rails/scaffold_controller", "controller.rb")
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def generate_view(view)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
|
-
describe DecentExposure::Controller do
|
|
3
|
+
RSpec.describe DecentExposure::Controller do
|
|
4
4
|
class Thing; end
|
|
5
5
|
class DifferentThing; end
|
|
6
6
|
|
|
7
7
|
class BaseController
|
|
8
|
-
def self.helper_method(*)
|
|
8
|
+
def self.helper_method(*)
|
|
9
|
+
end
|
|
9
10
|
|
|
10
11
|
def params
|
|
11
12
|
@params ||= HashWithIndifferentAccess.new
|
|
@@ -18,18 +19,18 @@ describe DecentExposure::Controller do
|
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
let(:request){ double("Request") }
|
|
22
|
-
let(:controller){ controller_klass.new }
|
|
23
|
-
before{ allow(controller).to receive(:request){ request } }
|
|
22
|
+
let(:request) { double("Request") }
|
|
23
|
+
let(:controller) { controller_klass.new }
|
|
24
|
+
before { allow(controller).to receive(:request) { request } }
|
|
24
25
|
|
|
25
26
|
%w[expose expose! exposure_config].each do |method_name|
|
|
26
|
-
define_method method_name do |*args, &block|
|
|
27
|
-
controller_klass.send method_name, *args, &block
|
|
27
|
+
define_method method_name do |*args, **options, &block|
|
|
28
|
+
controller_klass.send method_name, *args, **options, &block
|
|
28
29
|
end
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
context "getter/setter methods" do
|
|
32
|
-
before{ expose :thing }
|
|
33
|
+
before { expose :thing }
|
|
33
34
|
|
|
34
35
|
it "defines getter method" do
|
|
35
36
|
expect(controller).to respond_to(:thing)
|
|
@@ -41,8 +42,13 @@ describe DecentExposure::Controller do
|
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
context "helper methods" do
|
|
44
|
-
it "exposes getter
|
|
45
|
-
expect(controller_klass).to receive(:helper_method).with(:thing
|
|
45
|
+
it "exposes getter as controller helper methods" do
|
|
46
|
+
expect(controller_klass).to receive(:helper_method).with(:thing)
|
|
47
|
+
expose :thing
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "does not expose setter as controller helper methods" do
|
|
51
|
+
expect(controller_klass).to_not receive(:helper_method).with(:thing=)
|
|
46
52
|
expose :thing
|
|
47
53
|
end
|
|
48
54
|
end
|
|
@@ -65,7 +71,7 @@ describe DecentExposure::Controller do
|
|
|
65
71
|
end
|
|
66
72
|
|
|
67
73
|
context "applying" do
|
|
68
|
-
let(:thing){ double("Thing") }
|
|
74
|
+
let(:thing) { double("Thing") }
|
|
69
75
|
|
|
70
76
|
before do
|
|
71
77
|
exposure_config :sluggable, find_by: :slug
|
|
@@ -75,7 +81,7 @@ describe DecentExposure::Controller do
|
|
|
75
81
|
controller.params.merge! check_this_out: "foo", whee: "wut"
|
|
76
82
|
end
|
|
77
83
|
|
|
78
|
-
after{ expect(controller.thing).to eq(thing) }
|
|
84
|
+
after { expect(controller.thing).to eq(thing) }
|
|
79
85
|
|
|
80
86
|
it "can be reused later" do
|
|
81
87
|
expose :thing, with: :weird_id_name
|
|
@@ -105,7 +111,7 @@ describe DecentExposure::Controller do
|
|
|
105
111
|
end
|
|
106
112
|
|
|
107
113
|
context "with block" do
|
|
108
|
-
before{ expose(:thing){ compute_thing } }
|
|
114
|
+
before { expose(:thing) { compute_thing } }
|
|
109
115
|
|
|
110
116
|
it "executes block to calculate the value" do
|
|
111
117
|
allow(controller).to receive(:compute_thing).and_return(42)
|
|
@@ -114,7 +120,7 @@ describe DecentExposure::Controller do
|
|
|
114
120
|
|
|
115
121
|
it "executes the block once and memoizes the result" do
|
|
116
122
|
expect(controller).to receive(:compute_thing).once.and_return(42)
|
|
117
|
-
10.times{ controller.thing }
|
|
123
|
+
10.times { controller.thing }
|
|
118
124
|
end
|
|
119
125
|
|
|
120
126
|
it "allows setting value directly" do
|
|
@@ -124,20 +130,20 @@ describe DecentExposure::Controller do
|
|
|
124
130
|
end
|
|
125
131
|
|
|
126
132
|
it "throws and error when providing options with block" do
|
|
127
|
-
action = ->{ expose(:thing, id: :some_id){ some_code } }
|
|
133
|
+
action = -> { expose(:thing, id: :some_id) { some_code } }
|
|
128
134
|
expect(&action).to raise_error(ArgumentError, "Using :fetch option with other options doesn't make sense")
|
|
129
135
|
end
|
|
130
136
|
end
|
|
131
137
|
|
|
132
138
|
context "passing fetch block as an argument instead of block" do
|
|
133
139
|
it "is equivalent to passing block" do
|
|
134
|
-
expose :thing, ->{ compute_thing }
|
|
140
|
+
expose :thing, -> { compute_thing }
|
|
135
141
|
expect(controller).to receive(:compute_thing).and_return(42)
|
|
136
142
|
expect(controller.thing).to eq(42)
|
|
137
143
|
end
|
|
138
144
|
|
|
139
145
|
it "throws an error when passing both block and block-argument" do
|
|
140
|
-
action = ->{ expose(:thing, ->{}){} }
|
|
146
|
+
action = -> { expose(:thing, -> {}) {} }
|
|
141
147
|
expect(&action).to raise_error(ArgumentError, "Fetch block is already defined")
|
|
142
148
|
end
|
|
143
149
|
end
|
|
@@ -152,7 +158,7 @@ describe DecentExposure::Controller do
|
|
|
152
158
|
|
|
153
159
|
context "redefine fetch" do
|
|
154
160
|
before do
|
|
155
|
-
expose :thing, fetch: ->{ compute_thing }
|
|
161
|
+
expose :thing, fetch: -> { compute_thing }
|
|
156
162
|
allow(controller).to receive(:compute_thing).and_return(42)
|
|
157
163
|
end
|
|
158
164
|
|
|
@@ -163,9 +169,9 @@ describe DecentExposure::Controller do
|
|
|
163
169
|
|
|
164
170
|
context "default behaviour" do
|
|
165
171
|
context "build" do
|
|
166
|
-
let(:thing){ double("Thing") }
|
|
172
|
+
let(:thing) { double("Thing") }
|
|
167
173
|
|
|
168
|
-
after{ expect(controller.thing).to eq(thing) }
|
|
174
|
+
after { expect(controller.thing).to eq(thing) }
|
|
169
175
|
|
|
170
176
|
context "params method is not available" do
|
|
171
177
|
it "builds a new instance with empty hash" do
|
|
@@ -184,20 +190,20 @@ describe DecentExposure::Controller do
|
|
|
184
190
|
|
|
185
191
|
it "uses params method on non-get request" do
|
|
186
192
|
expose :thing
|
|
187
|
-
expect(request).to
|
|
193
|
+
expect(request).to receive_messages(get?: false, head?: false)
|
|
188
194
|
expect(Thing).to receive(:new).with(foo: :bar).and_return(thing)
|
|
189
195
|
expect(controller).to receive(:thing_params).and_return(foo: :bar)
|
|
190
196
|
end
|
|
191
197
|
|
|
192
198
|
it "can use custom params method name" do
|
|
193
199
|
expose :thing, build_params: :custom_params_method_name
|
|
194
|
-
expect(request).to
|
|
200
|
+
expect(request).to receive_messages(get?: false, head?: false)
|
|
195
201
|
expect(Thing).to receive(:new).with(foo: :bar).and_return(thing)
|
|
196
202
|
expect(controller).to receive(:custom_params_method_name).and_return(foo: :bar)
|
|
197
203
|
end
|
|
198
204
|
|
|
199
205
|
it "can use custom build params" do
|
|
200
|
-
expose :thing, build_params: ->{ foobar }
|
|
206
|
+
expose :thing, build_params: -> { foobar }
|
|
201
207
|
expect(controller).to receive(:foobar).and_return(42)
|
|
202
208
|
expect(Thing).to receive(:new).with(42).and_return(thing)
|
|
203
209
|
end
|
|
@@ -210,7 +216,7 @@ describe DecentExposure::Controller do
|
|
|
210
216
|
expect(DifferentThing).to receive(:find).with(10)
|
|
211
217
|
end
|
|
212
218
|
|
|
213
|
-
after{ controller.thing }
|
|
219
|
+
after { controller.thing }
|
|
214
220
|
|
|
215
221
|
it "checks params[:different_thing_id] first" do
|
|
216
222
|
controller.params.merge! different_thing_id: 10, thing_id: 11, id: 12
|
|
@@ -227,14 +233,14 @@ describe DecentExposure::Controller do
|
|
|
227
233
|
|
|
228
234
|
context "find_by" do
|
|
229
235
|
it "throws and error when using with :find" do
|
|
230
|
-
action = ->{ expose :thing, find: :foo, find_by: :bar }
|
|
236
|
+
action = -> { expose :thing, find: :foo, find_by: :bar }
|
|
231
237
|
expect(&action).to raise_error(ArgumentError, "Using :find_by option with :find doesn't make sense")
|
|
232
238
|
end
|
|
233
239
|
|
|
234
240
|
it "allows to specify what attribute to use for find" do
|
|
235
241
|
expect(Thing).to receive(:find_by!).with(foo: 10).and_return(42)
|
|
236
242
|
expose :thing, find_by: :foo
|
|
237
|
-
controller.params
|
|
243
|
+
controller.params[:id] = 10
|
|
238
244
|
expect(controller.thing).to eq(42)
|
|
239
245
|
end
|
|
240
246
|
end
|
|
@@ -242,19 +248,19 @@ describe DecentExposure::Controller do
|
|
|
242
248
|
context "parent option" do
|
|
243
249
|
context "with scope/model options" do
|
|
244
250
|
it "throws an error when used with scope option" do
|
|
245
|
-
action = ->{ expose :thing, scope: :foo, parent: :something }
|
|
251
|
+
action = -> { expose :thing, scope: :foo, parent: :something }
|
|
246
252
|
expect(&action).to raise_error(ArgumentError, "Using :parent option with :scope doesn't make sense")
|
|
247
253
|
end
|
|
248
254
|
|
|
249
255
|
it "throws an error when used with model option" do
|
|
250
|
-
action = ->{ expose :thing, model: :foo, parent: :something }
|
|
256
|
+
action = -> { expose :thing, model: :foo, parent: :something }
|
|
251
257
|
expect(&action).to raise_error(ArgumentError, "Using :parent option with :model doesn't make sense")
|
|
252
258
|
end
|
|
253
259
|
end
|
|
254
260
|
|
|
255
261
|
context "build/find" do
|
|
256
|
-
let(:current_user){ double("User") }
|
|
257
|
-
let(:scope){ double("Scope") }
|
|
262
|
+
let(:current_user) { double("User") }
|
|
263
|
+
let(:scope) { double("Scope") }
|
|
258
264
|
|
|
259
265
|
before do
|
|
260
266
|
expect(controller).to receive(:current_user).and_return(current_user)
|
|
@@ -262,26 +268,26 @@ describe DecentExposure::Controller do
|
|
|
262
268
|
expose :thing, parent: :current_user
|
|
263
269
|
end
|
|
264
270
|
|
|
265
|
-
after{ expect(controller.thing).to eq(42) }
|
|
271
|
+
after { expect(controller.thing).to eq(42) }
|
|
266
272
|
|
|
267
273
|
it "sets the scope to belong to parent defined by controller method" do
|
|
268
274
|
expect(scope).to receive(:new).with({}).and_return(42)
|
|
269
275
|
end
|
|
270
276
|
|
|
271
277
|
it "scopes the find to proper scope" do
|
|
272
|
-
controller.params
|
|
278
|
+
controller.params[:thing_id] = 10
|
|
273
279
|
expect(scope).to receive(:find).with(10).and_return(42)
|
|
274
280
|
end
|
|
275
281
|
end
|
|
276
282
|
end
|
|
277
283
|
|
|
278
284
|
context "override model" do
|
|
279
|
-
let(:different_thing){ double("DifferentThing") }
|
|
280
|
-
before{ expect(DifferentThing).to receive(:new).with({}).and_return(different_thing) }
|
|
281
|
-
after{ expect(controller.thing).to eq(different_thing) }
|
|
285
|
+
let(:different_thing) { double("DifferentThing") }
|
|
286
|
+
before { expect(DifferentThing).to receive(:new).with({}).and_return(different_thing) }
|
|
287
|
+
after { expect(controller.thing).to eq(different_thing) }
|
|
282
288
|
|
|
283
289
|
it "allows overriding model class with proc" do
|
|
284
|
-
expose :thing, model: ->{ DifferentThing }
|
|
290
|
+
expose :thing, model: -> { DifferentThing }
|
|
285
291
|
end
|
|
286
292
|
|
|
287
293
|
it "allows overriding model with class" do
|
|
@@ -300,7 +306,7 @@ describe DecentExposure::Controller do
|
|
|
300
306
|
context "override scope" do
|
|
301
307
|
it "allows overriding scope with proc" do
|
|
302
308
|
scope = double("Scope")
|
|
303
|
-
expose :thing, scope: ->{ scope }
|
|
309
|
+
expose :thing, scope: -> { scope }
|
|
304
310
|
expect(scope).to receive(:new).and_return(42)
|
|
305
311
|
expect(controller.thing).to eq(42)
|
|
306
312
|
end
|
|
@@ -321,7 +327,7 @@ describe DecentExposure::Controller do
|
|
|
321
327
|
end
|
|
322
328
|
|
|
323
329
|
it "allows overriding id with proc" do
|
|
324
|
-
expose :thing, id: ->{ get_thing_id_somehow }
|
|
330
|
+
expose :thing, id: -> { get_thing_id_somehow }
|
|
325
331
|
expect(controller).to receive(:get_thing_id_somehow).and_return(42)
|
|
326
332
|
end
|
|
327
333
|
|
|
@@ -338,7 +344,7 @@ describe DecentExposure::Controller do
|
|
|
338
344
|
|
|
339
345
|
context "override decorator" do
|
|
340
346
|
it "allows specify decorator" do
|
|
341
|
-
expose :thing, decorate: ->(thing){ decorate(thing) }
|
|
347
|
+
expose :thing, decorate: ->(thing) { decorate(thing) }
|
|
342
348
|
thing = double("Thing")
|
|
343
349
|
expect(Thing).to receive(:new).with({}).and_return(thing)
|
|
344
350
|
expect(controller).to receive(:decorate).with(thing)
|
|
@@ -357,7 +363,7 @@ describe DecentExposure::Controller do
|
|
|
357
363
|
end
|
|
358
364
|
|
|
359
365
|
it "should throw error when used with other options" do
|
|
360
|
-
action = ->{ expose :thing, from: :foo, parent: :bar }
|
|
366
|
+
action = -> { expose :thing, from: :foo, parent: :bar }
|
|
361
367
|
expect(&action).to raise_error(ArgumentError, "Using :from option with other options doesn't make sense")
|
|
362
368
|
end
|
|
363
369
|
|
|
@@ -367,7 +373,7 @@ describe DecentExposure::Controller do
|
|
|
367
373
|
foo = double("Foo", thing: thing)
|
|
368
374
|
expect(controller).to receive(:foo).and_return(foo)
|
|
369
375
|
expect(controller).to receive(:decorate).with(thing).and_return(decorated_thing)
|
|
370
|
-
expose :thing, from: :foo, decorate: ->(thing){ decorate(thing) }
|
|
376
|
+
expose :thing, from: :foo, decorate: ->(thing) { decorate(thing) }
|
|
371
377
|
expect(controller.thing).to eq(decorated_thing)
|
|
372
378
|
end
|
|
373
379
|
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "support/rails_app"
|
|
3
|
+
require "rspec/rails"
|
|
4
|
+
|
|
5
|
+
RSpec.describe Api::BirdsController, type: :controller do
|
|
6
|
+
let(:bird) { Bird.new }
|
|
7
|
+
|
|
8
|
+
context "when birds relation is exposed" do
|
|
9
|
+
class Api::BirdsController
|
|
10
|
+
expose :birds, -> { Bird.all }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "fetches all birds" do
|
|
14
|
+
expect(Bird).to receive(:all).and_return([bird])
|
|
15
|
+
get :index
|
|
16
|
+
expect(controller.birds).to eq([bird])
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when a bird is exposed" do
|
|
21
|
+
class Api::BirdsController
|
|
22
|
+
expose :bird
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "finds model by id" do
|
|
26
|
+
expect(Bird).to receive(:find).with("bird-id").and_return(bird)
|
|
27
|
+
get :show, **request_params(id: "bird-id")
|
|
28
|
+
expect(controller.bird).to eq(bird)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "finds model by bird_id" do
|
|
32
|
+
expect(Bird).to receive(:find).with("bird-id").and_return(bird)
|
|
33
|
+
get :new, **request_params(bird_id: "bird-id")
|
|
34
|
+
expect(controller.bird).to eq(bird)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "builds bird if id is not provided" do
|
|
38
|
+
get :new
|
|
39
|
+
expect(controller.bird).to be_a(Bird)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "when bird_params is defined" do
|
|
44
|
+
class Api::BirdsController
|
|
45
|
+
expose :bird
|
|
46
|
+
|
|
47
|
+
def bird_params
|
|
48
|
+
params.require(:bird).permit(:name)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "bird is build with params set" do
|
|
53
|
+
post :create, **request_params(bird: {name: "crow"})
|
|
54
|
+
expect(controller.bird.name).to eq("crow")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "when a bird? with a question mark is exposed" do
|
|
59
|
+
class Api::BirdsController
|
|
60
|
+
expose :bird
|
|
61
|
+
expose :bird?, -> { bird.present? }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "exposes bird?" do
|
|
65
|
+
expect(Bird).to receive(:find).with("bird-id").and_return(bird)
|
|
66
|
+
get :show, **request_params(id: "bird-id")
|
|
67
|
+
expect(controller.bird?).to be true
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "support/rails_app"
|
|
3
|
+
require "rspec/rails"
|
|
4
|
+
|
|
5
|
+
RSpec.describe BirdsController, type: :controller do
|
|
6
|
+
let(:bird) { Bird.new }
|
|
7
|
+
|
|
8
|
+
context "when birds relation is exposed" do
|
|
9
|
+
class BirdsController
|
|
10
|
+
expose :birds, -> { Bird.all }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "fetches all birds" do
|
|
14
|
+
expect(Bird).to receive(:all).and_return([bird])
|
|
15
|
+
get :index
|
|
16
|
+
expect(controller.birds).to eq([bird])
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when a bird is exposed" do
|
|
21
|
+
class BirdsController
|
|
22
|
+
expose :bird
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "finds model by id" do
|
|
26
|
+
expect(Bird).to receive(:find).with("bird-id").and_return(bird)
|
|
27
|
+
get :show, **request_params(id: "bird-id")
|
|
28
|
+
expect(controller.bird).to eq(bird)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "finds model by bird_id" do
|
|
32
|
+
expect(Bird).to receive(:find).with("bird-id").and_return(bird)
|
|
33
|
+
get :new, **request_params(bird_id: "bird-id")
|
|
34
|
+
expect(controller.bird).to eq(bird)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "builds bird if id is not provided" do
|
|
38
|
+
get :new
|
|
39
|
+
expect(controller.bird).to be_a(Bird)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "when request.method is HEAD" do
|
|
43
|
+
it "builds bird if id is not provided" do
|
|
44
|
+
head :new
|
|
45
|
+
expect(controller.bird).to be_a(Bird)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "when bird_params is defined" do
|
|
51
|
+
class BirdsController
|
|
52
|
+
expose :bird
|
|
53
|
+
|
|
54
|
+
def bird_params
|
|
55
|
+
params.require(:bird).permit(:name)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "bird is build with params set" do
|
|
60
|
+
post :create, **request_params(bird: {name: "crow"})
|
|
61
|
+
expect(controller.bird.name).to eq("crow")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context "when a bird? with a question mark is exposed" do
|
|
66
|
+
class BirdsController
|
|
67
|
+
expose :bird
|
|
68
|
+
expose :bird?, -> { bird.present? }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "exposes bird?" do
|
|
72
|
+
expect(Bird).to receive(:find).with("bird-id").and_return(bird)
|
|
73
|
+
get :show, **request_params(id: "bird-id")
|
|
74
|
+
expect(controller.bird?).to be true
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "support/rails_app"
|
|
3
|
+
require "rspec/rails"
|
|
4
|
+
require "action_mailer"
|
|
5
|
+
|
|
6
|
+
class BirdsMailer < ActionMailer::Base
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class BirdsMailer
|
|
10
|
+
expose(:birds, -> { Bird.all })
|
|
11
|
+
expose(:bird)
|
|
12
|
+
|
|
13
|
+
def hello_birds
|
|
14
|
+
mail { |format| format.text { render plain: "Hello #{birds}" } }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def hello_bird(id:)
|
|
18
|
+
mail { |format| format.text { render plain: "Hello #{bird}" } }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def hello_bird_by_id(id)
|
|
22
|
+
bird = Bird.find(id)
|
|
23
|
+
mail { |format| format.text { render plain: "Hello #{bird}" } }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
RSpec.describe BirdsMailer, type: :mailer do
|
|
28
|
+
let(:bird) { double :bird }
|
|
29
|
+
let(:birds) { double :birds }
|
|
30
|
+
|
|
31
|
+
context "when birds relation is exposed" do
|
|
32
|
+
it "sends the email with exposed birds" do
|
|
33
|
+
expect(Bird).to receive(:all).and_return(birds)
|
|
34
|
+
expect(described_class.hello_birds.body.to_s)
|
|
35
|
+
.to include("Hello #{birds}")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "when bird is exposed" do
|
|
40
|
+
it "sends the email with exposed bird" do
|
|
41
|
+
expect(Bird).to receive(:find).with("some-id").and_return(bird)
|
|
42
|
+
expect(described_class.hello_bird(id: "some-id").body.to_s)
|
|
43
|
+
.to include("Hello #{bird}")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "with non hash argument" do
|
|
48
|
+
it "does not set params" do
|
|
49
|
+
expect(Bird).to receive(:find).with("some-id").and_return(bird)
|
|
50
|
+
expect(described_class.hello_bird_by_id("some-id").body.to_s)
|
|
51
|
+
.to include("Hello #{bird}")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -1,45 +1,44 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "spec_helper"
|
|
2
2
|
|
|
3
3
|
RSpec.describe DecentExposure::Generators::ScaffoldTemplatesGenerator, type: :generator do
|
|
4
|
-
|
|
5
4
|
subject(:generator) { described_class.new }
|
|
6
5
|
|
|
7
|
-
context
|
|
8
|
-
it
|
|
9
|
-
allow(generator).to receive(:copy_file).with(
|
|
10
|
-
allow(generator).to receive(:copy_file).with(
|
|
11
|
-
allow(generator).to receive(:copy_file).with(
|
|
12
|
-
allow(generator).to receive(:copy_file).with(
|
|
13
|
-
allow(generator).to receive(:copy_file).with(
|
|
14
|
-
allow(generator).to receive(:copy_file).with(
|
|
6
|
+
context "with erb" do
|
|
7
|
+
it "generates controller and erb views" do
|
|
8
|
+
allow(generator).to receive(:copy_file).with("controller.rb", "lib/templates/rails/scaffold_controller/controller.rb")
|
|
9
|
+
allow(generator).to receive(:copy_file).with("_form.html.erb", "lib/templates/erb/scaffold/_form.html.erb")
|
|
10
|
+
allow(generator).to receive(:copy_file).with("edit.html.erb", "lib/templates/erb/scaffold/edit.html.erb")
|
|
11
|
+
allow(generator).to receive(:copy_file).with("index.html.erb", "lib/templates/erb/scaffold/index.html.erb")
|
|
12
|
+
allow(generator).to receive(:copy_file).with("new.html.erb", "lib/templates/erb/scaffold/new.html.erb")
|
|
13
|
+
allow(generator).to receive(:copy_file).with("show.html.erb", "lib/templates/erb/scaffold/show.html.erb")
|
|
15
14
|
|
|
16
15
|
generator.generate
|
|
17
16
|
end
|
|
18
17
|
end
|
|
19
18
|
|
|
20
|
-
context
|
|
19
|
+
context "with haml" do
|
|
21
20
|
before do
|
|
22
21
|
allow(generator).to receive(:options).and_return(template_engine: :haml)
|
|
23
22
|
end
|
|
24
23
|
|
|
25
|
-
it
|
|
26
|
-
allow(generator).to receive(:copy_file).with(
|
|
27
|
-
allow(generator).to receive(:copy_file).with(
|
|
28
|
-
allow(generator).to receive(:copy_file).with(
|
|
29
|
-
allow(generator).to receive(:copy_file).with(
|
|
30
|
-
allow(generator).to receive(:copy_file).with(
|
|
31
|
-
allow(generator).to receive(:copy_file).with(
|
|
24
|
+
it "generates controller and haml views" do
|
|
25
|
+
allow(generator).to receive(:copy_file).with("controller.rb", "lib/templates/rails/scaffold_controller/controller.rb")
|
|
26
|
+
allow(generator).to receive(:copy_file).with("_form.html.haml", "lib/templates/haml/scaffold/_form.html.haml")
|
|
27
|
+
allow(generator).to receive(:copy_file).with("edit.html.haml", "lib/templates/haml/scaffold/edit.html.haml")
|
|
28
|
+
allow(generator).to receive(:copy_file).with("index.html.haml", "lib/templates/haml/scaffold/index.html.haml")
|
|
29
|
+
allow(generator).to receive(:copy_file).with("new.html.haml", "lib/templates/haml/scaffold/new.html.haml")
|
|
30
|
+
allow(generator).to receive(:copy_file).with("show.html.haml", "lib/templates/haml/scaffold/show.html.haml")
|
|
32
31
|
|
|
33
32
|
generator.generate
|
|
34
33
|
end
|
|
35
34
|
end
|
|
36
35
|
|
|
37
|
-
context
|
|
36
|
+
context "with invalid template_engine" do
|
|
38
37
|
before do
|
|
39
38
|
allow(generator).to receive(:options).and_return(template_engine: :foo_bar)
|
|
40
39
|
end
|
|
41
40
|
|
|
42
|
-
it
|
|
41
|
+
it "raises an ArgumentError" do
|
|
43
42
|
expect { generator.generate }. to raise_error(ArgumentError)
|
|
44
43
|
end
|
|
45
44
|
end
|
data/spec/support/rails_app.rb
CHANGED
|
@@ -1,37 +1,69 @@
|
|
|
1
|
-
require "active_support/all"
|
|
2
1
|
require "action_controller"
|
|
3
|
-
require "action_dispatch"
|
|
4
2
|
require "rails"
|
|
5
3
|
|
|
4
|
+
def request_params(params)
|
|
5
|
+
return params if Rails::VERSION::MAJOR < 5
|
|
6
|
+
{params: params}
|
|
7
|
+
end
|
|
8
|
+
|
|
6
9
|
module Rails
|
|
7
10
|
class App
|
|
8
|
-
def env_config
|
|
11
|
+
def env_config
|
|
12
|
+
{}
|
|
13
|
+
end
|
|
9
14
|
|
|
10
15
|
def routes
|
|
11
16
|
@routes ||= ActionDispatch::Routing::RouteSet.new.tap do |routes|
|
|
12
17
|
routes.draw do
|
|
13
|
-
|
|
18
|
+
resources :birds
|
|
19
|
+
|
|
20
|
+
namespace :api do
|
|
21
|
+
resources :birds
|
|
22
|
+
end
|
|
14
23
|
end
|
|
15
24
|
end
|
|
16
25
|
end
|
|
17
26
|
end
|
|
18
27
|
|
|
28
|
+
def self.root
|
|
29
|
+
""
|
|
30
|
+
end
|
|
31
|
+
|
|
19
32
|
def self.application
|
|
20
33
|
@app ||= App.new
|
|
21
34
|
end
|
|
22
35
|
end
|
|
23
36
|
|
|
24
37
|
class Bird
|
|
38
|
+
attr_accessor :name
|
|
39
|
+
def initialize(options = {})
|
|
40
|
+
options.each { |k, v| public_send("#{k}=", v) }
|
|
41
|
+
end
|
|
25
42
|
end
|
|
26
43
|
|
|
27
44
|
class ApplicationController < ActionController::Base
|
|
28
45
|
include Rails.application.routes.url_helpers
|
|
29
46
|
end
|
|
30
47
|
|
|
48
|
+
def base_api_class
|
|
49
|
+
return ApplicationController if Rails::VERSION::MAJOR < 5
|
|
50
|
+
ActionController::API
|
|
51
|
+
end
|
|
52
|
+
|
|
31
53
|
class BirdsController < ApplicationController
|
|
32
|
-
|
|
54
|
+
%i[index show edit new create update].each do |action|
|
|
55
|
+
define_method action do
|
|
56
|
+
head :ok
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
33
60
|
|
|
34
|
-
|
|
35
|
-
|
|
61
|
+
module Api
|
|
62
|
+
class BirdsController < base_api_class
|
|
63
|
+
%i[index show edit new create update].each do |action|
|
|
64
|
+
define_method action do
|
|
65
|
+
head :ok
|
|
66
|
+
end
|
|
67
|
+
end
|
|
36
68
|
end
|
|
37
69
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: decent_exposure
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pavel Pravosud
|
|
8
8
|
- Stephen Caudill
|
|
9
|
-
autorequire:
|
|
9
|
+
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2021-01-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -39,6 +39,20 @@ dependencies:
|
|
|
39
39
|
- - ">="
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
41
|
version: '4.0'
|
|
42
|
+
- !ruby/object:Gem::Dependency
|
|
43
|
+
name: actionmailer
|
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '0'
|
|
49
|
+
type: :development
|
|
50
|
+
prerelease: false
|
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0'
|
|
42
56
|
- !ruby/object:Gem::Dependency
|
|
43
57
|
name: rspec-rails
|
|
44
58
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -53,6 +67,20 @@ dependencies:
|
|
|
53
67
|
- - "~>"
|
|
54
68
|
- !ruby/object:Gem::Version
|
|
55
69
|
version: '3.0'
|
|
70
|
+
- !ruby/object:Gem::Dependency
|
|
71
|
+
name: standard
|
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
type: :development
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '0'
|
|
56
84
|
description: "\n DecentExposure helps you program to an interface, rather than
|
|
57
85
|
an\n implementation in your Rails controllers. The fact of the matter is that\n
|
|
58
86
|
\ sharing state via instance variables in controllers promotes close coupling\n
|
|
@@ -67,6 +95,7 @@ extra_rdoc_files: []
|
|
|
67
95
|
files:
|
|
68
96
|
- ".gitignore"
|
|
69
97
|
- ".travis.yml"
|
|
98
|
+
- CHANGELOG.md
|
|
70
99
|
- Gemfile
|
|
71
100
|
- LICENSE.txt
|
|
72
101
|
- README.md
|
|
@@ -75,8 +104,7 @@ files:
|
|
|
75
104
|
- decent_exposure.png
|
|
76
105
|
- gemfiles/Gemfile.rails-4.2.0
|
|
77
106
|
- gemfiles/Gemfile.rails-4.2.6
|
|
78
|
-
- gemfiles/Gemfile.rails-5.0.0
|
|
79
|
-
- hashrocket_logo.png
|
|
107
|
+
- gemfiles/Gemfile.rails-5.0.0
|
|
80
108
|
- lib/decent_exposure.rb
|
|
81
109
|
- lib/decent_exposure/attribute.rb
|
|
82
110
|
- lib/decent_exposure/behavior.rb
|
|
@@ -84,6 +112,7 @@ files:
|
|
|
84
112
|
- lib/decent_exposure/controller.rb
|
|
85
113
|
- lib/decent_exposure/exposure.rb
|
|
86
114
|
- lib/decent_exposure/flow.rb
|
|
115
|
+
- lib/decent_exposure/mailer.rb
|
|
87
116
|
- lib/decent_exposure/version.rb
|
|
88
117
|
- lib/generators/decent_exposure/USAGE
|
|
89
118
|
- lib/generators/decent_exposure/scaffold_templates_generator.rb
|
|
@@ -98,38 +127,41 @@ files:
|
|
|
98
127
|
- lib/generators/decent_exposure/templates/new.html.haml
|
|
99
128
|
- lib/generators/decent_exposure/templates/show.html.erb
|
|
100
129
|
- lib/generators/decent_exposure/templates/show.html.haml
|
|
101
|
-
- spec/controller_spec.rb
|
|
130
|
+
- spec/decent_exposure/controller_spec.rb
|
|
131
|
+
- spec/features/api_birds_controller_spec.rb
|
|
132
|
+
- spec/features/birds_controller_spec.rb
|
|
133
|
+
- spec/features/birds_mailer_spec.rb
|
|
102
134
|
- spec/generators/decent_exposure/scaffold_templates_generator_spec.rb
|
|
103
|
-
- spec/integration_spec.rb
|
|
104
135
|
- spec/spec_helper.rb
|
|
105
136
|
- spec/support/rails_app.rb
|
|
106
137
|
homepage: https://github.com/hashrocket/decent_exposure
|
|
107
138
|
licenses:
|
|
108
139
|
- MIT
|
|
109
140
|
metadata: {}
|
|
110
|
-
post_install_message:
|
|
141
|
+
post_install_message:
|
|
111
142
|
rdoc_options: []
|
|
112
143
|
require_paths:
|
|
113
144
|
- lib
|
|
114
145
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
115
146
|
requirements:
|
|
116
|
-
- - "
|
|
147
|
+
- - ">="
|
|
117
148
|
- !ruby/object:Gem::Version
|
|
118
149
|
version: '2.0'
|
|
119
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
151
|
requirements:
|
|
121
|
-
- - "
|
|
152
|
+
- - ">="
|
|
122
153
|
- !ruby/object:Gem::Version
|
|
123
|
-
version:
|
|
154
|
+
version: '0'
|
|
124
155
|
requirements: []
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
signing_key:
|
|
156
|
+
rubygems_version: 3.2.3
|
|
157
|
+
signing_key:
|
|
128
158
|
specification_version: 4
|
|
129
159
|
summary: A helper for creating declarative interfaces in controllers
|
|
130
160
|
test_files:
|
|
131
|
-
- spec/controller_spec.rb
|
|
161
|
+
- spec/decent_exposure/controller_spec.rb
|
|
162
|
+
- spec/features/api_birds_controller_spec.rb
|
|
163
|
+
- spec/features/birds_controller_spec.rb
|
|
164
|
+
- spec/features/birds_mailer_spec.rb
|
|
132
165
|
- spec/generators/decent_exposure/scaffold_templates_generator_spec.rb
|
|
133
|
-
- spec/integration_spec.rb
|
|
134
166
|
- spec/spec_helper.rb
|
|
135
167
|
- spec/support/rails_app.rb
|
data/hashrocket_logo.png
DELETED
|
Binary file
|
data/spec/integration_spec.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "support/rails_app"
|
|
3
|
-
require "rspec/rails"
|
|
4
|
-
|
|
5
|
-
describe BirdsController, type: :controller do
|
|
6
|
-
context "finds bird by id" do
|
|
7
|
-
let(:mockingbird){ double("Bird") }
|
|
8
|
-
before{ expect(Bird).to receive(:find).with("mockingbird").once.and_return(mockingbird) }
|
|
9
|
-
after{ expect(controller.bird).to eq(mockingbird) }
|
|
10
|
-
|
|
11
|
-
it "finds model by id" do
|
|
12
|
-
get :show, { id: "mockingbird" }
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
it "finds model by bird_id" do
|
|
16
|
-
get :show, { bird_id: "mockingbird" }
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "builds bird if id is not provided" do
|
|
21
|
-
bird = double("Bird")
|
|
22
|
-
expect(Bird).to receive(:new).with({}).and_return(bird)
|
|
23
|
-
get :show
|
|
24
|
-
expect(controller.bird).to eq(bird)
|
|
25
|
-
end
|
|
26
|
-
end
|