adequate_exposure 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a1d34ba1b491cb226abd1ed966b2e1fc51469a5
4
- data.tar.gz: f5a79cc81e6918171764fe3441f81e7da2a372bd
3
+ metadata.gz: 82a9cfe00dccb013cca09b85f68073902bb5928d
4
+ data.tar.gz: 15ec7db35c84401f82a3d8bab5af8079ccf5ea81
5
5
  SHA512:
6
- metadata.gz: 332ca67a8253cbb83e395a95bc79167a9ac355843a772adf1b373569c83086afcc2daed5eb30bbae058a4d57b9fe73992a28d3acaadcc60bac04f47f7bb8eb5d
7
- data.tar.gz: 2558b8622f561444eae1ba3b1c19d46b059cd83f2fe0705e06af4e33bb93e821392b6f02a5d11ebcda03fee01b162066072e60e66fa4cebff0dbdc02b6c01abb
6
+ metadata.gz: 8ade244f9a2785594a66b5ba042b2639a15157eb39f72234f3e2133d21a27bffe2dcecf3d61a6a79d9768b4a0d6ab5605cd3336600c3d49e848767708385c22a
7
+ data.tar.gz: 84260440dbd08e8444ce307994f4c564e97b76efc48a5e554d349a5018ba8c3d7d4ec0cf7801d860876cd306ba014ef1b5c2ff0f396b3ded2fdbe1faaedd7660
data/README.md CHANGED
@@ -2,19 +2,24 @@
2
2
 
3
3
  This is WIP. Please don't send pull requests yet, I'm still actively rewriting things.
4
4
 
5
- Adequate exposure. Exposing things, adequately.
5
+ Exposing things, adequately.
6
6
 
7
- Adequate exposure is a lightweight alternative to [Decent Exposure](https://github.com/voxdolo/decent_exposure). With it's narrowly focused api you can get exactly what you need without all the extra dressing.
7
+ Adequate exposure is a lightweight alternative to [Decent
8
+ Exposure](https://github.com/voxdolo/decent_exposure). With it's narrowly
9
+ focused api you can get exactly what you need without all the extra dressing.
8
10
 
9
- *Note: It is not the intent of the author to imply that Decent Exposure is inadequate.)*
11
+ *Note: It is not the intent of the author to imply that Decent Exposure is
12
+ inadequate.)*
10
13
 
11
- Installation is as simple as: `$ gem install adequate_exposure`. Once you have that down we can start talking about the API.
14
+ Installation is as simple as: `$ gem install adequate_exposure`. Once you have
15
+ that down we can start talking about the API.
12
16
 
13
17
  ## API
14
18
 
15
19
  The whole API consists of one `expose` method.
16
20
 
17
- In the simplest scenario you'll just use it to expose a model in the controller:
21
+ In the simplest scenario you'll just use it to expose a model in the
22
+ controller:
18
23
 
19
24
  ```ruby
20
25
  class ThingsController < ApplicationController
@@ -22,23 +27,12 @@ class ThingsController < ApplicationController
22
27
  end
23
28
  ```
24
29
 
25
- Now every time you call `thing` in your controller or view, it'll look for an id and try to perform `Thing.find(id)` or `Thing.new` if the id is not found. It'll also memoize the result in `@exposed_thing` instance variable.
30
+ Now every time you call `thing` in your controller or view, it'll look for an
31
+ id and try to perform `Thing.find(id)` or `Thing.new` if the id is not found.
32
+ It'll also memoize the result in `@exposed_thing` instance variable.
26
33
 
27
- You can also provide your own logic of how `thing` should be resolved by passing a block that'll be executed in your controller context.
28
-
29
- ```ruby
30
- class ThingsController < ApplicationController
31
- expose(:thing){ Thing.find(get_thing_id_somehow) }
32
-
33
- private
34
-
35
- def get_thing_id_somehow
36
- 42
37
- end
38
- end
39
- ```
40
-
41
- The default resolving workflow if pretty powerful and customizable. It could be expressed with the following pseudocode:
34
+ The default resolving workflow if pretty powerful and customizable. It could be
35
+ expressed with the following pseudocode:
42
36
 
43
37
  ```ruby
44
38
  def fetch(scope, id)
@@ -70,11 +64,22 @@ def decorate(thing)
70
64
  end
71
65
  ```
72
66
 
73
- Each step is overridable with options. The acceptable options to the `expose` macro are:
67
+ Each step could be overrided with options. The acceptable options to the
68
+ `expose` macro are:
69
+
70
+ **fetch**
71
+
72
+ This is the entry point. Fetch proc defines how to resolve your exposure in the
73
+ first place.
74
+
75
+ ```ruby
76
+ expose :thing, fetch: ->{ get_thing_some_way_or_another }
77
+ ```
74
78
 
75
79
  **find**
76
80
 
77
- How to perform the finding. Could be useful if you don't want to use standard Rails finder.
81
+ Defines how to perform the finding. Could be useful if you don't want to use standard
82
+ Rails finder.
78
83
 
79
84
  ```ruby
80
85
  expose :thing, find: ->(id, scope){ scope.find_by(slug: id) }
@@ -90,7 +95,7 @@ expose :thing, build: ->(scope){ Thing.build_with_defaults }
90
95
 
91
96
  **id**
92
97
 
93
- Allows to specify how to extract id from parameters hash.
98
+ Specifies how to extract id from parameters hash.
94
99
 
95
100
  ```ruby
96
101
  # default
@@ -112,12 +117,11 @@ Defines the scope that's used in `find` and `build` steps.
112
117
 
113
118
  ```ruby
114
119
  expose :thing, scope: ->{ current_user.things }
115
- expose :thing, scope: :current_user # the same as above
116
120
  ```
117
121
 
118
122
  **model**
119
123
 
120
- Specify the model to use.
124
+ Specify the model class to use.
121
125
 
122
126
  ```ruby
123
127
  expose :thing, model: ->{ AnotherThing }
@@ -125,18 +129,10 @@ expose :thing, model: AnotherThing
125
129
  expose :thing, model: :another_thing
126
130
  ```
127
131
 
128
- **fetch**
129
-
130
- Allows to override the `fetch` logic that's happening when you first call exposed helper.
131
-
132
- ```ruby
133
- expose :thing, fetch: ->{ get_thing_some_way_or_another }
134
- expose(:thing){ get_thing_some_way_or_another }
135
- ```
136
132
 
137
133
  **decorate**
138
134
 
139
- Allows to define a block that wraps and instance before it's returned. Useful for decorators.
135
+ Allows to define a block that wraps an instance before it's returned. Useful for decorators.
140
136
 
141
137
  ```ruby
142
138
  expose :thing, decorate: ->(thing){ ThingDecorator.new(thing) }
@@ -144,7 +140,7 @@ expose :thing, decorate: ->(thing){ ThingDecorator.new(thing) }
144
140
 
145
141
  ## Contributing
146
142
 
147
- 1. Fork it ( https://github.com/[my-github-username]/adequate_exposure/fork )
143
+ 1. Fork it (https://github.com/rwz/adequate_exposure/fork)
148
144
  2. Create your feature branch (`git checkout -b my-new-feature`)
149
145
  3. Commit your changes (`git commit -am 'Add some feature'`)
150
146
  4. Push to the branch (`git push origin my-new-feature`)
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = AdequateExposure::VERSION
9
9
  spec.authors = ["Pavel Pravosud"]
10
10
  spec.email = ["pavel@pravosud.com"]
11
- spec.summary = "More adequate than decent"
11
+ spec.summary = "Exposing things, adequately"
12
12
  spec.homepage = "https://github.com/rwz/adequate_exposure"
13
13
  spec.license = "MIT"
14
14
  spec.files = `git ls-files -z`.split("\x0")
@@ -1,5 +1,3 @@
1
- require "active_support/core_ext/module/delegation"
2
-
3
1
  module AdequateExposure
4
2
  class Context
5
3
  attr_reader :context, :attribute
@@ -1,11 +1,12 @@
1
- require "active_support/core_ext/hash/reverse_merge"
2
-
3
1
  module AdequateExposure
4
2
  module Controller
5
- def expose(name, **options, &block)
6
- options = options.merge(name: name)
7
- options.reverse_merge! fetch: block if block_given?
8
- Exposure.new(options).expose! self
3
+ def expose(*args, &block)
4
+ Exposure.expose! self, *args, &block
5
+ end
6
+
7
+ def expose!(name, *args, &block)
8
+ expose name, *args, &block
9
+ before_action name
9
10
  end
10
11
  end
11
12
  end
@@ -1,27 +1,92 @@
1
1
  module AdequateExposure
2
2
  class Exposure
3
- attr_reader :options
3
+ attr_reader :controller, :options
4
4
 
5
- def initialize(options)
6
- @options = options
5
+ def self.expose!(*args, &block)
6
+ new(*args, &block).expose!
7
7
  end
8
8
 
9
- def expose!(controller)
10
- expose_attribute! controller
11
- expose_helper_methods! controller
9
+ def initialize(controller, name, fetch_block=nil, **options, &block)
10
+ @controller = controller
11
+ @options = options.with_indifferent_access.merge(name: name)
12
+
13
+ merge_lambda_option :fetch, fetch_block if fetch_block
14
+ merge_lambda_option :fetch, block if block_given?
15
+
16
+ assert_singleton_option :fetch
17
+ assert_singleton_option :from
18
+ assert_incompatible_options_pair :parent, :model
19
+ assert_incompatible_options_pair :parent, :scope
20
+
21
+ normalize_options
22
+ end
23
+
24
+ def expose!
25
+ expose_attribute!
26
+ expose_helper_methods!
12
27
  end
13
28
 
14
29
  private
15
30
 
16
- def expose_attribute!(controller)
31
+ def expose_attribute!
17
32
  attribute.expose! controller
18
33
  end
19
34
 
20
- def expose_helper_methods!(controller)
35
+ def expose_helper_methods!
21
36
  helper_methods = [ attribute.getter_method_name, attribute.setter_method_name ]
22
37
  controller.helper_method *helper_methods
23
38
  end
24
39
 
40
+ def normalize_options
41
+ exposure_name = options.fetch(:name)
42
+
43
+ normalize_non_proc_option :id do |ids|
44
+ ->{ Array.wrap(ids).map{ |id| params[id] }.find(&:present?) }
45
+ end
46
+
47
+ normalize_non_proc_option :model do |value|
48
+ model = if [String, Symbol].include?(value.class)
49
+ value.to_s.classify.constantize
50
+ else
51
+ value
52
+ end
53
+
54
+ ->{ model }
55
+ end
56
+
57
+ normalize_non_proc_option :build do |params_method_name|
58
+ ->(scope){ scope.new(send(params_method_name)) }
59
+ end
60
+
61
+ normalize_non_proc_option :scope do |custom_scope|
62
+ ->(model){ model.send(custom_scope) }
63
+ end
64
+
65
+ if parent = options.delete(:parent)
66
+ merge_lambda_option :scope, ->{ send(parent).send(exposure_name.to_s.pluralize) }
67
+ end
68
+
69
+ if from = options.delete(:from)
70
+ merge_lambda_option :fetch, ->{ send(from).send(exposure_name) }
71
+ end
72
+ end
73
+
74
+ def normalize_non_proc_option(name)
75
+ option_value = options[name]
76
+ return if Proc === option_value
77
+ if option_value.present?
78
+ merge_lambda_option name, yield(option_value)
79
+ end
80
+ end
81
+
82
+ def merge_lambda_option(name, body)
83
+ if previous_value = options[name] and Proc === previous_value
84
+ fail ArgumentError, "#{name.to_s.titleize} block is already defined"
85
+ end
86
+
87
+ options[name] = body
88
+ end
89
+
25
90
  def attribute
26
91
  @attribute ||= begin
27
92
  local_options = options
@@ -37,5 +102,17 @@ module AdequateExposure
37
102
  )
38
103
  end
39
104
  end
105
+
106
+ def assert_incompatible_options_pair(key1, key2)
107
+ if options.key?(key1) && options.key?(key2)
108
+ fail ArgumentError, "Using #{key1.inspect} option with #{key2.inspect} doesn't make sense"
109
+ end
110
+ end
111
+
112
+ def assert_singleton_option(name)
113
+ if options.except(name, :name).any? && options.key?(name)
114
+ fail ArgumentError, "Using #{name.inspect} option with other options doesn't make sense"
115
+ end
116
+ end
40
117
  end
41
118
  end
@@ -1,14 +1,10 @@
1
- require "active_support/hash_with_indifferent_access"
2
- require "active_support/core_ext/array/wrap"
3
- require "active_support/core_ext/string/inflections"
4
-
5
1
  module AdequateExposure
6
2
  class Flow
7
3
  attr_reader :controller, :options
8
4
  delegate :params, to: :controller
9
5
 
10
- def initialize(controller, **options)
11
- @controller, @options = controller, HashWithIndifferentAccess.new(options)
6
+ def initialize(controller, options)
7
+ @controller, @options = controller, options.with_indifferent_access
12
8
  end
13
9
 
14
10
  def name
@@ -26,19 +22,20 @@ module AdequateExposure
26
22
  protected
27
23
 
28
24
  def default_fetch
29
- id ? decorate(find(id, scope)) : decorate(build(scope))
25
+ computed_scope = scope(model)
26
+ id ? decorate(find(id, computed_scope)) : decorate(build(computed_scope))
30
27
  end
31
28
 
32
29
  def default_id
33
- fetch_first_defined_param %I[#{name}_id id]
30
+ params["#{name}_id"] || params[:id]
34
31
  end
35
32
 
36
- def default_scope
33
+ def default_scope(model)
37
34
  model
38
35
  end
39
36
 
40
37
  def default_model
41
- symbol_to_class(name)
38
+ name.to_s.classify.constantize
42
39
  end
43
40
 
44
41
  def default_find(id, scope)
@@ -46,32 +43,25 @@ module AdequateExposure
46
43
  end
47
44
 
48
45
  def default_build(scope)
49
- scope.new
46
+ scope.new(exposure_params)
50
47
  end
51
48
 
52
49
  def default_decorate(instance)
53
50
  instance
54
51
  end
55
52
 
56
- def handle_custom_model(value)
57
- Class === value ? value : symbol_to_class(value)
58
- end
59
-
60
- def handle_custom_scope(value)
61
- scope_parent = controller.instance_exec{ send value }
62
- scope_parent.send(name.to_s.pluralize)
63
- end
53
+ def exposure_params
54
+ params_method_name = "#{name}_params"
64
55
 
65
- def handle_custom_id(value)
66
- fetch_first_defined_param value
56
+ if controller.respond_to?(params_method_name, true)
57
+ controller.send(params_method_name)
58
+ else
59
+ {}
60
+ end
67
61
  end
68
62
 
69
63
  private
70
64
 
71
- def id_attribute_name
72
- Array.wrap(possible_id_keys).detect{ |key| params.key?(key) }
73
- end
74
-
75
65
  def handle_action(name, *args)
76
66
  if options.key?(name)
77
67
  handle_custom_action(name, *args)
@@ -84,22 +74,11 @@ module AdequateExposure
84
74
  value = options[name]
85
75
 
86
76
  if Proc === value
77
+ args = args.first(value.parameters.length)
87
78
  controller.instance_exec(*args, &value)
88
79
  else
89
- send("handle_custom_#{name}", value, *args)
80
+ fail ArgumentError, "Can't handle #{name.inspect} => #{value.inspect} option"
90
81
  end
91
82
  end
92
-
93
- def symbol_to_class(symbol)
94
- symbol.to_s.classify.constantize
95
- end
96
-
97
- def fetch_first_defined_param(keys)
98
- Array.wrap(keys).each do |key|
99
- return params[key] if params.key?(key)
100
- end
101
-
102
- nil
103
- end
104
83
  end
105
84
  end
@@ -1,3 +1,3 @@
1
1
  module AdequateExposure
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,4 +1,4 @@
1
- require "active_support/lazy_load_hooks"
1
+ require "active_support/all"
2
2
 
3
3
  module AdequateExposure
4
4
  autoload :Controller, "adequate_exposure/controller"
@@ -43,10 +43,15 @@ describe AdequateExposure::Controller do
43
43
  end
44
44
  end
45
45
 
46
- context "with block" do
47
- before do
48
- expose(:thing){ compute_thing }
46
+ context ".expose!" do
47
+ it "supports eager expose" do
48
+ expect(controller_klass).to receive(:before_action).with(:thing)
49
+ controller_klass.expose! :thing
49
50
  end
51
+ end
52
+
53
+ context "with block" do
54
+ before{ expose(:thing){ compute_thing } }
50
55
 
51
56
  it "executes block to calculate the value" do
52
57
  allow(controller).to receive(:compute_thing).and_return(42)
@@ -63,6 +68,24 @@ describe AdequateExposure::Controller do
63
68
  controller.thing = :foobar
64
69
  expect(controller.thing).to eq(:foobar)
65
70
  end
71
+
72
+ it "throws and error when providing options with block" do
73
+ action = ->{ expose(:thing, id: :some_id){ some_code } }
74
+ expect(&action).to raise_error(ArgumentError, "Using :fetch option with other options doesn't make sense")
75
+ end
76
+ end
77
+
78
+ context "passing fetch block as an argument instead of block" do
79
+ it "is equivalent to passing block" do
80
+ expose :thing, ->{ compute_thing }
81
+ expect(controller).to receive(:compute_thing).and_return(42)
82
+ expect(controller.thing).to eq(42)
83
+ end
84
+
85
+ it "throws an error when passing both block and block-argument" do
86
+ action = ->{ expose(:thing, ->{}){} }
87
+ expect(&action).to raise_error(ArgumentError, "Fetch block is already defined")
88
+ end
66
89
  end
67
90
 
68
91
  context "redefine fetch" do
@@ -77,14 +100,36 @@ describe AdequateExposure::Controller do
77
100
  end
78
101
 
79
102
  context "default behaviour" do
80
- before{ expose :thing }
81
103
 
82
- it "builds a new instance when id is not provided" do
83
- expect(controller.thing).to be_instance_of(Thing)
104
+ context "build" do
105
+ let(:thing){ double("Thing") }
106
+
107
+ after{ expect(controller.thing).to eq(thing) }
108
+
109
+ it "builds a new instance with empty hash when strong parameters method is not available" do
110
+ expose :thing
111
+ expect(Thing).to receive(:new).with({}).and_return(thing)
112
+ end
113
+
114
+ it "builds a new instance with attributes when strong parameters method is available" do
115
+ expose :thing
116
+ expect(Thing).to receive(:new).with(foo: :bar).and_return(thing)
117
+ expect(controller).to receive(:thing_params).and_return(foo: :bar)
118
+ end
119
+
120
+ it "allows to specify strong parameters method name with a symbol passed to build option" do
121
+ expose :thing, build: :custom_params_method_name
122
+ expect(Thing).to receive(:new).with(foo: :bar).and_return(thing)
123
+ expect(controller).to receive(:custom_params_method_name).and_return(foo: :bar)
124
+ end
84
125
  end
85
126
 
86
127
  context "find" do
87
- before{ expect(Thing).to receive(:find).with(10) }
128
+ before do
129
+ expose :thing
130
+ expect(Thing).to receive(:find).with(10)
131
+ end
132
+
88
133
  after{ controller.thing }
89
134
 
90
135
  it "finds Thing if thing_id param is provided" do
@@ -97,8 +142,46 @@ describe AdequateExposure::Controller do
97
142
  end
98
143
  end
99
144
 
145
+ context "parent option" do
146
+ context "with scope/model options" do
147
+ it "throws an error when used with scope option" do
148
+ action = ->{ expose :thing, scope: :foo, parent: :something }
149
+ expect(&action).to raise_error(ArgumentError, "Using :parent option with :scope doesn't make sense")
150
+ end
151
+
152
+ it "throws an error when used with model option" do
153
+ action = ->{ expose :thing, model: :foo, parent: :something }
154
+ expect(&action).to raise_error(ArgumentError, "Using :parent option with :model doesn't make sense")
155
+ end
156
+ end
157
+
158
+ context "build/find" do
159
+ let(:current_user){ double("User") }
160
+ let(:scope){ double("Scope") }
161
+
162
+ before do
163
+ expect(controller).to receive(:current_user).and_return(current_user)
164
+ expect(current_user).to receive(:things).and_return(scope)
165
+ expose :thing, parent: :current_user
166
+ end
167
+
168
+ after{ expect(controller.thing).to eq(42) }
169
+
170
+ it "sets the scope to belong to parent defined by controller method" do
171
+ expect(scope).to receive(:new).with({}).and_return(42)
172
+ end
173
+
174
+ it "scopes the find to proper scope" do
175
+ controller.params.merge! thing_id: 10
176
+ expect(scope).to receive(:find).with(10).and_return(42)
177
+ end
178
+ end
179
+ end
180
+
100
181
  context "override model" do
101
- after{ expect(controller.thing).to be_instance_of(DifferentThing) }
182
+ let(:different_thing){ double("DifferentThing") }
183
+ before{ expect(DifferentThing).to receive(:new).with({}).and_return(different_thing) }
184
+ after{ expect(controller.thing).to eq(different_thing) }
102
185
 
103
186
  it "allows overriding model class with proc" do
104
187
  expose :thing, model: ->{ DifferentThing }
@@ -111,6 +194,10 @@ describe AdequateExposure::Controller do
111
194
  it "allows overriding model class with symbol" do
112
195
  expose :thing, model: :different_thing
113
196
  end
197
+
198
+ it "allows overriding model class with string" do
199
+ expose :thing, model: "DifferentThing"
200
+ end
114
201
  end
115
202
 
116
203
  context "override scope" do
@@ -121,17 +208,12 @@ describe AdequateExposure::Controller do
121
208
  expect(controller.thing).to eq(42)
122
209
  end
123
210
 
124
- it "allows overriding with symbol" do
125
- current_user = double("User")
211
+ it "allows overriding model scope using symbol" do
126
212
  scope = double("Scope")
127
- scoped_thing = double("Thing")
128
-
129
- expect(controller).to receive(:current_user).and_return(current_user)
130
- expect(current_user).to receive(:things).and_return(scope)
131
- expect(scope).to receive(:new).and_return(scoped_thing)
132
- expose :thing, scope: :current_user
133
-
134
- expect(controller.thing).to eq(scoped_thing)
213
+ expect(Thing).to receive(:custom_scope).and_return(scope)
214
+ expect(scope).to receive(:new).and_return(42)
215
+ expose :thing, scope: :custom_scope
216
+ expect(controller.thing).to eq(42)
135
217
  end
136
218
  end
137
219
 
@@ -160,8 +242,27 @@ describe AdequateExposure::Controller do
160
242
  context "override decorator" do
161
243
  it "allows specify decorator" do
162
244
  expose :thing, decorate: ->(thing){ decorate(thing) }
163
- expect(controller).to receive(:decorate).with(an_instance_of(Thing))
245
+ thing = double("Thing")
246
+ expect(Thing).to receive(:new).with({}).and_return(thing)
247
+ expect(controller).to receive(:decorate).with(thing)
164
248
  controller.thing
165
249
  end
166
250
  end
251
+
252
+ context "from option" do
253
+ it "allows scope to be called from method" do
254
+ post = double("Post")
255
+ comments = double("Comments")
256
+ allow(controller).to receive(:post).and_return(post)
257
+ expect(post).to receive(:comments).and_return(comments)
258
+ expose :comments, from: :post
259
+
260
+ expect(controller.comments).to eq(comments)
261
+ end
262
+
263
+ it "should throw error when used with other options" do
264
+ action = ->{ expose :thing, from: :foo, parent: :bar }
265
+ expect(&action).to raise_error(ArgumentError, "Using :from option with other options doesn't make sense")
266
+ end
267
+ end
167
268
  end
@@ -1,5 +1,4 @@
1
1
  require "active_support/all"
2
- require "active_support/dependencies/autoload"
3
2
  require "action_controller"
4
3
  require "action_dispatch"
5
4
  require "rails"
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.1
4
+ version: 0.0.2
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-02 00:00:00.000000000 Z
11
+ date: 2014-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -85,7 +85,7 @@ rubyforge_project:
85
85
  rubygems_version: 2.2.2
86
86
  signing_key:
87
87
  specification_version: 4
88
- summary: More adequate than decent
88
+ summary: Exposing things, adequately
89
89
  test_files:
90
90
  - spec/controller_spec.rb
91
91
  - spec/integration_spec.rb