draper 1.0.0.beta3 → 1.0.0.beta4
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.
- data/CHANGELOG.markdown +39 -21
- data/Readme.markdown +5 -3
- data/draper.gemspec +1 -0
- data/lib/draper.rb +2 -5
- data/lib/draper/collection_decorator.rb +12 -11
- data/lib/draper/decoratable.rb +1 -1
- data/lib/draper/decorated_association.rb +20 -5
- data/lib/draper/decorator.rb +21 -9
- data/lib/draper/railtie.rb +10 -3
- data/lib/draper/test/rspec_integration.rb +49 -4
- data/lib/draper/version.rb +1 -1
- data/lib/draper/view_context.rb +6 -4
- data/spec/draper/collection_decorator_spec.rb +53 -16
- data/spec/draper/decoratable_spec.rb +34 -6
- data/spec/draper/decorated_association_spec.rb +188 -5
- data/spec/draper/decorator_spec.rb +68 -17
- data/spec/draper/finders_spec.rb +16 -16
- metadata +19 -6
data/CHANGELOG.markdown
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# Draper Changelog
|
2
2
|
|
3
|
+
## 1.0.0.beta4
|
4
|
+
|
5
|
+
* Fixed a race condition with capybara integration. [https://github.com/drapergem/draper/commit/e79464931e7b98c85ed5d78ed9ca38d51f43006e](https://github.com/drapergem/draper/commit/e79464931e7b98c85ed5d78ed9ca38d51f43006e)
|
6
|
+
|
7
|
+
* `[]` can be decorated again. [https://github.com/drapergem/draper/commit/597fbdf0c80583f5ea6df9f7350fefeaa0cca989](https://github.com/drapergem/draper/commit/597fbdf0c80583f5ea6df9f7350fefeaa0cca989)
|
8
|
+
|
9
|
+
* `model == decorator` as well as `decorator == model`. [https://github.com/drapergem/draper/commit/46f8a6823c50c13e5c9ab3c07723f335c4e291bc](https://github.com/drapergem/draper/commit/46f8a6823c50c13e5c9ab3c07723f335c4e291bc)
|
10
|
+
|
11
|
+
* Preliminary Mongoid integration. [https://github.com/drapergem/draper/commit/892d1954202c61fd082a07213c8d4a23560687bc](https://github.com/drapergem/draper/commit/892d1954202c61fd082a07213c8d4a23560687bc)
|
12
|
+
|
13
|
+
* Add a helper method `sign_in` for devise in decorator specs. [https://github.com/drapergem/draper/commit/66a30093ed4207d02d8fa60bda4df2da091d85a3](https://github.com/drapergem/draper/commit/66a30093ed4207d02d8fa60bda4df2da091d85a3)
|
14
|
+
|
15
|
+
* Brought back `context`. [https://github.com/drapergem/draper/commit/9609156b997b3a469386eef3a5f043b24d8a2fba](https://github.com/drapergem/draper/commit/9609156b997b3a469386eef3a5f043b24d8a2fba)
|
16
|
+
|
17
|
+
* Fixed issue where classes were incorrectly being looked up. [https://github.com/drapergem/draper/commit/ee2a015514ff87dfd2158926457e988c2fc3fd79](https://github.com/drapergem/draper/commit/ee2a015514ff87dfd2158926457e988c2fc3fd79)
|
18
|
+
|
19
|
+
* Integrate RequestStore for per-request storage. [https://github.com/drapergem/draper/commit/fde1cde9adfb856750c1f616d8b62d221ef97fc6](https://github.com/drapergem/draper/commit/fde1cde9adfb856750c1f616d8b62d221ef97fc6)
|
20
|
+
|
3
21
|
## 1.0.0.beta3
|
4
22
|
|
5
23
|
* Relaxed Rails version requirement to 3.0. Support for < 3.2 should be
|
@@ -7,13 +25,13 @@
|
|
7
25
|
|
8
26
|
## 1.0.0.beta2
|
9
27
|
|
10
|
-
* `has_finders` is now `decorates_finders`. [https://github.com/
|
28
|
+
* `has_finders` is now `decorates_finders`. [https://github.com/drapergem/draper/commit/33f18aa062e0d3848443dbd81047f20d5665579f](https://github.com/drapergem/draper/commit/33f18aa062e0d3848443dbd81047f20d5665579f)
|
11
29
|
|
12
|
-
* If a finder method is used, and the source class is not set and cannot be inferred, an `UninferrableSourceError` is raised. [https://github.com/
|
30
|
+
* If a finder method is used, and the source class is not set and cannot be inferred, an `UninferrableSourceError` is raised. [https://github.com/drapergem/draper/commit/8ef5bf2f02f7033e3cd4f1f5de7397b02c984fe3](https://github.com/drapergem/draper/commit/8ef5bf2f02f7033e3cd4f1f5de7397b02c984fe3)
|
13
31
|
|
14
|
-
* Class methods are now properly delegated again. [https://github.com/
|
32
|
+
* Class methods are now properly delegated again. [https://github.com/drapergem/draper/commit/731995a5feac4cd06cf9328d2892c0eca9992db6](https://github.com/drapergem/draper/commit/731995a5feac4cd06cf9328d2892c0eca9992db6)
|
15
33
|
|
16
|
-
* We no longer `respond_to?` private methods on the source. [https://github.com/
|
34
|
+
* We no longer `respond_to?` private methods on the source. [https://github.com/drapergem/draper/commit/18ebac81533a6413aa20a3c26f23e91d0b12b031](https://github.com/drapergem/draper/commit/18ebac81533a6413aa20a3c26f23e91d0b12b031)
|
17
35
|
|
18
36
|
* Rails versioning relaxed to support Rails 4 [https://github.com/drapergem/draper/commit/8bfd393b5baa7aa1488076a5e2cb88648efaa815](https://github.com/drapergem/draper/commit/8bfd393b5baa7aa1488076a5e2cb88648efaa815)
|
19
37
|
|
@@ -50,27 +68,27 @@ And many small bug fixes and refactorings.
|
|
50
68
|
|
51
69
|
## 0.17.0
|
52
70
|
|
53
|
-
* [Fix earlier fix of `view_context` priming](https://github.com/
|
54
|
-
* [Add `denies_all`](https://github.com/
|
55
|
-
* [Properly proxy associations with regard to `find`](https://github.com/
|
71
|
+
* [Fix earlier fix of `view_context` priming](https://github.com/drapergem/draper/commit/5da44336)
|
72
|
+
* [Add `denies_all`](https://github.com/drapergem/draper/commit/148e732)
|
73
|
+
* [Properly proxy associations with regard to `find`](https://github.com/drapergem/draper/commit/d46d19205e)
|
56
74
|
|
57
75
|
## 0.16.0
|
58
76
|
|
59
|
-
* [Automatically prime `view_context`](https://github.com/
|
60
|
-
* [Fixed bug where rspec eq matchers didn't work]((https://github.com/
|
61
|
-
* [Sequel ORM support](https://github.com/
|
77
|
+
* [Automatically prime `view_context`](https://github.com/drapergem/draper/commit/057ab4e8)
|
78
|
+
* [Fixed bug where rspec eq matchers didn't work]((https://github.com/drapergem/draper/commit/57617b)
|
79
|
+
* [Sequel ORM support](https://github.com/drapergem/draper/commit/7d4942)
|
62
80
|
* Fixed issues with newer minitest
|
63
|
-
* [Changed the way the `view_context` gets set](https://github.com/
|
81
|
+
* [Changed the way the `view_context` gets set](https://github.com/drapergem/draper/commit/0b03d9c)
|
64
82
|
|
65
83
|
## 0.15.0
|
66
84
|
|
67
85
|
* Proper minitest integration
|
68
|
-
* [We can properly decorate scoped associations](https://github.com/
|
69
|
-
* [Fixed awkward eager loading](https://github.com/
|
86
|
+
* [We can properly decorate scoped associations](https://github.com/drapergem/draper/issues/223)
|
87
|
+
* [Fixed awkward eager loading](https://github.com/drapergem/draper/commit/7dc3510b)
|
70
88
|
|
71
89
|
## 0.14.0
|
72
90
|
|
73
|
-
* [Properly prime the view context in Rails Console](https://github.com/
|
91
|
+
* [Properly prime the view context in Rails Console](https://github.com/drapergem/draper/commit/738074f)
|
74
92
|
* Make more gems development requirements only
|
75
93
|
|
76
94
|
## 0.13.0
|
@@ -82,7 +100,7 @@ And many small bug fixes and refactorings.
|
|
82
100
|
|
83
101
|
## 0.12.3
|
84
102
|
|
85
|
-
* [Fix i18n issue](https://github.com/
|
103
|
+
* [Fix i18n issue](https://github.com/drapergem/draper/issues/202)
|
86
104
|
|
87
105
|
## 0.12.2
|
88
106
|
|
@@ -93,13 +111,13 @@ And many small bug fixes and refactorings.
|
|
93
111
|
## 0.12.0
|
94
112
|
|
95
113
|
* Added Changelog
|
96
|
-
* [Prevented double decoration](https://github.com/
|
97
|
-
* [`ActiveModel::Errors` support](https://github.com/
|
98
|
-
* [Fixed autoloading issue](https://github.com/
|
99
|
-
* [Re-did generators](https://github.com/
|
100
|
-
* [Added capybara integration](https://github.com/
|
114
|
+
* [Prevented double decoration](https://github.com/drapergem/draper/issues/173)
|
115
|
+
* [`ActiveModel::Errors` support](https://github.com/drapergem/draper/commit/19496f0c)
|
116
|
+
* [Fixed autoloading issue](https://github.com/drapergem/draper/issues/188)
|
117
|
+
* [Re-did generators](https://github.com/drapergem/draper/commit/9155e58f)
|
118
|
+
* [Added capybara integration](https://github.com/drapergem/draper/commit/57c8678e)
|
101
119
|
* Fixed a few bugs with the `DecoratedEnumerableProxy`
|
102
120
|
|
103
121
|
## 0.11.1
|
104
122
|
|
105
|
-
* [Fixed regression, we don't want to introduce a hard dependency on Rails](https://github.com/
|
123
|
+
* [Fixed regression, we don't want to introduce a hard dependency on Rails](https://github.com/drapergem/draper/issues/107)
|
data/Readme.markdown
CHANGED
@@ -12,10 +12,12 @@
|
|
12
12
|
1. `h` to proxy to Rails/application helpers like `h.current_user`
|
13
13
|
2. the name of your decorated model to access the wrapped object like `article.created_at`
|
14
14
|
5. Wrap models in your controller with the decorator using:
|
15
|
-
1. `.decorate` method with a single object
|
16
|
-
ex: `ArticleDecorator.decorate(Article.
|
15
|
+
1. `.decorate` method with a single object,
|
16
|
+
ex: `ArticleDecorator.decorate(Article.first)`
|
17
17
|
2. `.new` method with single object
|
18
18
|
ex: `ArticleDecorator.new(Article.first)`
|
19
|
+
3. `.decorate_collection` method with a collection,
|
20
|
+
ex: `ArticleDecorator.decorate_collection(Article.all)`
|
19
21
|
6. Call decorator methods from your view templates
|
20
22
|
ex: `<%= @article_decorator.created_at %>`
|
21
23
|
|
@@ -201,7 +203,7 @@ ArticleDecorator.new(Article.find(params[:id]))
|
|
201
203
|
|
202
204
|
```ruby
|
203
205
|
ArticleDecorator.decorate(Article.first) # Returns one instance of ArticleDecorator
|
204
|
-
ArticleDecorator.
|
206
|
+
ArticleDecorator.decorate_collection(Article.all) # Returns CollectionDecorator of ArticleDecorator
|
205
207
|
```
|
206
208
|
|
207
209
|
### In Your Views
|
data/draper.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
s.add_dependency 'activesupport', '>= 3.0'
|
20
20
|
s.add_dependency 'actionpack', '>= 3.0'
|
21
|
+
s.add_dependency 'request_store', '~> 1.0.0'
|
21
22
|
|
22
23
|
s.add_development_dependency 'ammeter'
|
23
24
|
s.add_development_dependency 'rake', '~> 0.9.2'
|
data/lib/draper.rb
CHANGED
@@ -14,10 +14,7 @@ require 'draper/view_context'
|
|
14
14
|
require 'draper/collection_decorator'
|
15
15
|
require 'draper/railtie' if defined?(Rails)
|
16
16
|
|
17
|
-
|
18
|
-
require 'draper/test/rspec_integration' if defined?(RSpec) and RSpec.respond_to?(:configure)
|
19
|
-
require 'draper/test/minitest_integration' if defined?(MiniTest::Rails)
|
20
|
-
require 'draper/test/test_unit_integration'
|
17
|
+
require 'active_support/core_ext/hash/keys'
|
21
18
|
|
22
19
|
module Draper
|
23
20
|
def self.setup_action_controller(base)
|
@@ -37,7 +34,7 @@ module Draper
|
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
40
|
-
def self.
|
37
|
+
def self.setup_orm(base)
|
41
38
|
base.class_eval do
|
42
39
|
include Draper::Decoratable
|
43
40
|
end
|
@@ -3,20 +3,21 @@ module Draper
|
|
3
3
|
include Enumerable
|
4
4
|
include ViewHelpers
|
5
5
|
|
6
|
-
attr_accessor :source, :
|
6
|
+
attr_accessor :source, :context, :decorator_class
|
7
7
|
alias_method :to_source, :source
|
8
8
|
|
9
9
|
delegate :as_json, *(Array.instance_methods - Object.instance_methods), to: :decorated_collection
|
10
10
|
|
11
11
|
# @param source collection to decorate
|
12
|
-
# @param
|
13
|
-
#
|
14
|
-
# @option options [Class,Symbol] :with the class used to decorate
|
12
|
+
# @param [Hash] options (optional)
|
13
|
+
# @option options [Class, Symbol] :with the class used to decorate
|
15
14
|
# items, or `:infer` to call each item's `decorate` method instead
|
15
|
+
# @option options [Hash] :context context available to each item's decorator
|
16
16
|
def initialize(source, options = {})
|
17
|
+
options.assert_valid_keys(:with, :context)
|
17
18
|
@source = source
|
18
|
-
@decorator_class = options.
|
19
|
-
@
|
19
|
+
@decorator_class = options.fetch(:with) { self.class.inferred_decorator_class }
|
20
|
+
@context = options.fetch(:context, {})
|
20
21
|
end
|
21
22
|
|
22
23
|
class << self
|
@@ -56,18 +57,18 @@ module Draper
|
|
56
57
|
"#<CollectionDecorator of #{decorator_class} for #{source.inspect}>"
|
57
58
|
end
|
58
59
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
60
|
+
def context=(value)
|
61
|
+
@context = value
|
62
|
+
each {|item| item.context = value } if @decorated_collection
|
62
63
|
end
|
63
64
|
|
64
65
|
protected
|
65
66
|
|
66
67
|
def decorate_item(item)
|
67
68
|
if decorator_class == :infer
|
68
|
-
item.decorate(
|
69
|
+
item.decorate(context: context)
|
69
70
|
else
|
70
|
-
decorator_class.decorate(item,
|
71
|
+
decorator_class.decorate(item, context: context)
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
data/lib/draper/decoratable.rb
CHANGED
@@ -1,19 +1,24 @@
|
|
1
1
|
module Draper
|
2
2
|
class DecoratedAssociation
|
3
3
|
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :base, :association, :options
|
5
5
|
|
6
|
-
def initialize(
|
7
|
-
@
|
6
|
+
def initialize(base, association, options)
|
7
|
+
@base = base
|
8
8
|
@association = association
|
9
|
+
options.assert_valid_keys(:with, :scope, :context)
|
9
10
|
@options = options
|
10
11
|
end
|
11
12
|
|
12
13
|
def call
|
13
|
-
return undecorated if undecorated.nil?
|
14
|
+
return undecorated if undecorated.nil?
|
14
15
|
decorate
|
15
16
|
end
|
16
17
|
|
18
|
+
def source
|
19
|
+
base.source
|
20
|
+
end
|
21
|
+
|
17
22
|
private
|
18
23
|
|
19
24
|
def undecorated
|
@@ -25,7 +30,7 @@ module Draper
|
|
25
30
|
end
|
26
31
|
|
27
32
|
def decorate
|
28
|
-
@decorated ||= decorator_class.send(decorate_method, undecorated,
|
33
|
+
@decorated ||= decorator_class.send(decorate_method, undecorated, decorator_options)
|
29
34
|
end
|
30
35
|
|
31
36
|
def decorate_method
|
@@ -51,5 +56,15 @@ module Draper
|
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
59
|
+
def decorator_options
|
60
|
+
decorator_class # Ensures options[:with] = :infer for unspecified collections
|
61
|
+
|
62
|
+
dec_options = collection? ? options.slice(:with, :context) : options.slice(:context)
|
63
|
+
dec_options[:context] = base.context unless dec_options.key?(:context)
|
64
|
+
if dec_options[:context].respond_to?(:call)
|
65
|
+
dec_options[:context] = dec_options[:context].call(base.context)
|
66
|
+
end
|
67
|
+
dec_options
|
68
|
+
end
|
54
69
|
end
|
55
70
|
end
|
data/lib/draper/decorator.rb
CHANGED
@@ -5,14 +5,15 @@ module Draper
|
|
5
5
|
include Draper::ViewHelpers
|
6
6
|
include ActiveModel::Serialization if defined?(ActiveModel::Serialization)
|
7
7
|
|
8
|
-
attr_accessor :source, :
|
8
|
+
attr_accessor :source, :context
|
9
9
|
|
10
10
|
alias_method :model, :source
|
11
11
|
alias_method :to_source, :source
|
12
12
|
|
13
13
|
# Initialize a new decorator instance by passing in
|
14
14
|
# an instance of the source class. Pass in an optional
|
15
|
-
# context inside the options hash is
|
15
|
+
# :context inside the options hash which is available
|
16
|
+
# for later use.
|
16
17
|
#
|
17
18
|
# A decorator cannot be applied to other instances of the
|
18
19
|
# same decorator and will instead result in a decorator
|
@@ -23,11 +24,13 @@ module Draper
|
|
23
24
|
#
|
24
25
|
# @param [Object] source object to decorate
|
25
26
|
# @param [Hash] options (optional)
|
27
|
+
# @option options [Hash] :context context available to the decorator
|
26
28
|
def initialize(source, options = {})
|
29
|
+
options.assert_valid_keys(:context)
|
27
30
|
source.to_a if source.respond_to?(:to_a) # forces evaluation of a lazy query from AR
|
28
31
|
@source = source
|
29
|
-
@
|
30
|
-
handle_multiple_decoration if source.is_a?(Draper::Decorator)
|
32
|
+
@context = options.fetch(:context, {})
|
33
|
+
handle_multiple_decoration(options) if source.is_a?(Draper::Decorator)
|
31
34
|
end
|
32
35
|
|
33
36
|
class << self
|
@@ -38,7 +41,7 @@ module Draper
|
|
38
41
|
#
|
39
42
|
# @param [String, Symbol, Class] Class or name of class to decorate.
|
40
43
|
def self.decorates(klass)
|
41
|
-
@source_class = klass.to_s.
|
44
|
+
@source_class = klass.to_s.camelize.constantize
|
42
45
|
end
|
43
46
|
|
44
47
|
# @return [Class] The source class corresponding to this
|
@@ -72,9 +75,15 @@ module Draper
|
|
72
75
|
# @param [Symbol] association name of association to decorate, like `:products`
|
73
76
|
# @option options [Class] :with the decorator to apply to the association
|
74
77
|
# @option options [Symbol] :scope a scope to apply when fetching the association
|
78
|
+
# @option options [Hash, #call] :context context available to decorated
|
79
|
+
# objects in collection. Passing a `lambda` or similar will result in that
|
80
|
+
# block being called when the association is evaluated. The block will be
|
81
|
+
# passed the base decorator's `context` Hash and should return the desired
|
82
|
+
# context Hash for the decorated items.
|
75
83
|
def self.decorates_association(association, options = {})
|
84
|
+
options.assert_valid_keys(:with, :scope, :context)
|
76
85
|
define_method(association) do
|
77
|
-
decorated_associations[association] ||= Draper::DecoratedAssociation.new(
|
86
|
+
decorated_associations[association] ||= Draper::DecoratedAssociation.new(self, association, options)
|
78
87
|
decorated_associations[association].call
|
79
88
|
end
|
80
89
|
end
|
@@ -82,7 +91,8 @@ module Draper
|
|
82
91
|
# A convenience method for decorating multiple associations. Calls
|
83
92
|
# decorates_association on each of the given symbols.
|
84
93
|
#
|
85
|
-
# @param [Symbols*] associations
|
94
|
+
# @param [Symbols*] associations names of associations to decorate
|
95
|
+
# @param [Hash] options passed to `decorate_association`
|
86
96
|
def self.decorates_associations(*associations)
|
87
97
|
options = associations.extract_options!
|
88
98
|
associations.each do |association|
|
@@ -128,7 +138,9 @@ module Draper
|
|
128
138
|
# for the keys listed below)
|
129
139
|
# @option options [Class,Symbol] :with (self) the class used to decorate
|
130
140
|
# items, or `:infer` to call each item's `decorate` method instead
|
141
|
+
# @option options [Hash] :context context available to decorated items
|
131
142
|
def self.decorate_collection(source, options = {})
|
143
|
+
options.assert_valid_keys(:with, :context)
|
132
144
|
Draper::CollectionDecorator.new(source, options.reverse_merge(with: self))
|
133
145
|
end
|
134
146
|
|
@@ -244,9 +256,9 @@ module Draper
|
|
244
256
|
self.class.security.allow?(method)
|
245
257
|
end
|
246
258
|
|
247
|
-
def handle_multiple_decoration
|
259
|
+
def handle_multiple_decoration(options)
|
248
260
|
if source.instance_of?(self.class)
|
249
|
-
self.
|
261
|
+
self.context = source.context unless options.has_key?(:context)
|
250
262
|
self.source = source.source
|
251
263
|
elsif source.decorated_with?(self.class)
|
252
264
|
warn "Reapplying #{self.class} decorator to target that is already decorated with it. Call stack:\n#{caller(1).join("\n")}"
|
data/lib/draper/railtie.rb
CHANGED
@@ -16,6 +16,11 @@ module Draper
|
|
16
16
|
|
17
17
|
config.after_initialize do |app|
|
18
18
|
app.config.paths.add 'app/decorators', eager_load: true
|
19
|
+
|
20
|
+
# Test Support
|
21
|
+
require 'draper/test/rspec_integration' if defined?(RSpec) and RSpec.respond_to?(:configure)
|
22
|
+
require 'draper/test/minitest_integration' if defined?(MiniTest::Rails)
|
23
|
+
require 'draper/test/test_unit_integration'
|
19
24
|
end
|
20
25
|
|
21
26
|
initializer "draper.setup_action_controller" do |app|
|
@@ -30,9 +35,11 @@ module Draper
|
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
33
|
-
initializer "draper.
|
34
|
-
|
35
|
-
|
38
|
+
initializer "draper.setup_orm" do |app|
|
39
|
+
[:active_record, :mongoid].each do |orm|
|
40
|
+
ActiveSupport.on_load orm do
|
41
|
+
Draper.setup_orm self
|
42
|
+
end
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
@@ -3,6 +3,39 @@ module Draper
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
included { metadata[:type] = :decorator }
|
5
5
|
end
|
6
|
+
|
7
|
+
module DeviseHelper
|
8
|
+
def sign_in(user)
|
9
|
+
warden.stub :authenticate! => user
|
10
|
+
controller.stub :current_user => user
|
11
|
+
user
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def request
|
17
|
+
@request ||= ::ActionDispatch::TestRequest.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def controller
|
21
|
+
return @controller if @controller
|
22
|
+
@controller = ApplicationController.new
|
23
|
+
@controller.request = request
|
24
|
+
::Draper::ViewContext.current = @controller.view_context
|
25
|
+
@controller
|
26
|
+
end
|
27
|
+
|
28
|
+
# taken from Devise's helper but uses the request method instead of @request
|
29
|
+
# and we don't really need the rest of their helper
|
30
|
+
def warden
|
31
|
+
@warden ||= begin
|
32
|
+
manager = Warden::Manager.new(nil) do |config|
|
33
|
+
config.merge! Devise.warden_config
|
34
|
+
end
|
35
|
+
request.env['warden'] = Warden::Proxy.new(request.env, manager)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
6
39
|
end
|
7
40
|
|
8
41
|
RSpec.configure do |config|
|
@@ -11,12 +44,24 @@ RSpec.configure do |config|
|
|
11
44
|
:file_path => /spec[\\\/]decorators/
|
12
45
|
}
|
13
46
|
|
47
|
+
if defined?(Devise)
|
48
|
+
config.include Draper::DeviseHelper, :type => :decorator
|
49
|
+
end
|
14
50
|
end
|
15
51
|
|
16
|
-
|
17
|
-
|
52
|
+
module Draper
|
53
|
+
module RSpec
|
54
|
+
class Railtie < Rails::Railtie
|
55
|
+
config.after_initialize do |app|
|
56
|
+
if defined?(Capybara)
|
57
|
+
require 'capybara/rspec/matchers'
|
18
58
|
|
19
|
-
|
20
|
-
|
59
|
+
::RSpec.configure do |config|
|
60
|
+
config.include Capybara::RSpecMatchers, :type => :decorator
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
21
65
|
end
|
22
66
|
end
|
67
|
+
|
data/lib/draper/version.rb
CHANGED
data/lib/draper/view_context.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'request_store'
|
2
|
+
|
1
3
|
module Draper
|
2
4
|
module ViewContext
|
3
5
|
def view_context
|
@@ -7,19 +9,19 @@ module Draper
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def self.current_controller
|
10
|
-
|
12
|
+
RequestStore.store[:current_controller] || ApplicationController.new
|
11
13
|
end
|
12
14
|
|
13
15
|
def self.current_controller=(controller)
|
14
|
-
|
16
|
+
RequestStore.store[:current_controller] = controller
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.current
|
18
|
-
|
20
|
+
RequestStore.store[:current_view_context] ||= build_view_context
|
19
21
|
end
|
20
22
|
|
21
23
|
def self.current=(context)
|
22
|
-
|
24
|
+
RequestStore.store[:current_view_context] = context
|
23
25
|
end
|
24
26
|
|
25
27
|
def self.build_view_context
|
@@ -16,33 +16,70 @@ describe Draper::CollectionDecorator do
|
|
16
16
|
subject.map{|item| item.source}.should == source
|
17
17
|
end
|
18
18
|
|
19
|
-
context "with
|
20
|
-
subject { Draper::CollectionDecorator.new(source, with: ProductDecorator, some:
|
19
|
+
context "with context" do
|
20
|
+
subject { Draper::CollectionDecorator.new(source, with: ProductDecorator, context: {some: 'context'}) }
|
21
21
|
|
22
|
-
its(:
|
22
|
+
its(:context) { should == {some: 'context'} }
|
23
23
|
|
24
|
-
it "passes
|
24
|
+
it "passes context to the individual decorators" do
|
25
25
|
subject.each do |item|
|
26
|
-
item.
|
26
|
+
item.context.should == {some: 'context'}
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
it "does not tie the individual decorators' contexts together" do
|
31
|
+
subject.each do |item|
|
32
|
+
item.context.should == {some: 'context'}
|
33
|
+
item.context = {alt: 'context'}
|
34
|
+
item.context.should == {alt: 'context'}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#context=" do
|
39
|
+
it "updates the collection decorator's context" do
|
40
|
+
subject.context = {other: 'context'}
|
41
|
+
subject.context.should == {other: 'context'}
|
34
42
|
end
|
35
43
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
44
|
+
context "when the collection is already decorated" do
|
45
|
+
it "updates the items' context" do
|
46
|
+
subject.decorated_collection
|
47
|
+
subject.context = {other: 'context'}
|
48
|
+
subject.each do |item|
|
49
|
+
item.context.should == {other: 'context'}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when the collection has not yet been decorated" do
|
55
|
+
it "does not trigger decoration" do
|
56
|
+
subject.should_not_receive(:decorated_collection)
|
57
|
+
subject.context = {other: 'context'}
|
58
|
+
end
|
59
|
+
|
60
|
+
it "sets context after decoration is triggered" do
|
61
|
+
subject.context = {other: 'context'}
|
62
|
+
subject.each do |item|
|
63
|
+
item.context.should == {other: 'context'}
|
64
|
+
end
|
40
65
|
end
|
41
66
|
end
|
42
67
|
end
|
43
68
|
end
|
44
69
|
|
45
70
|
describe "#initialize" do
|
71
|
+
describe "options validation" do
|
72
|
+
let(:valid_options) { {with: ProductDecorator, context: {}} }
|
73
|
+
|
74
|
+
it "does not raise error on valid options" do
|
75
|
+
expect { Draper::CollectionDecorator.new(source, valid_options) }.to_not raise_error
|
76
|
+
end
|
77
|
+
|
78
|
+
it "raises error on invalid options" do
|
79
|
+
expect { Draper::CollectionDecorator.new(source, valid_options.merge(foo: 'bar')) }.to raise_error(ArgumentError, 'Unknown key: foo')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
46
83
|
context "when the :with option is given" do
|
47
84
|
context "and the decorator can't be inferred from the class" do
|
48
85
|
subject { Draper::CollectionDecorator.new(source, with: ProductDecorator) }
|
@@ -123,14 +160,14 @@ describe Draper::CollectionDecorator do
|
|
123
160
|
end
|
124
161
|
|
125
162
|
describe "#localize" do
|
126
|
-
before { subject.helpers.should_receive(:localize).with(:an_object, {some:
|
163
|
+
before { subject.helpers.should_receive(:localize).with(:an_object, {some: 'parameter'}) }
|
127
164
|
|
128
165
|
it "delegates to helpers" do
|
129
|
-
subject.localize(:an_object, some:
|
166
|
+
subject.localize(:an_object, some: 'parameter')
|
130
167
|
end
|
131
168
|
|
132
169
|
it "is aliased to #l" do
|
133
|
-
subject.l(:an_object, some:
|
170
|
+
subject.l(:an_object, some: 'parameter')
|
134
171
|
end
|
135
172
|
end
|
136
173
|
|
@@ -9,9 +9,9 @@ describe Draper::Decoratable do
|
|
9
9
|
subject.decorate.source.should be subject
|
10
10
|
end
|
11
11
|
|
12
|
-
it "accepts
|
13
|
-
decorator = subject.decorate(some:
|
14
|
-
decorator.
|
12
|
+
it "accepts context" do
|
13
|
+
decorator = subject.decorate(context: {some: 'context'})
|
14
|
+
decorator.context.should == {some: 'context'}
|
15
15
|
end
|
16
16
|
|
17
17
|
it "is not memoized" do
|
@@ -45,6 +45,34 @@ describe Draper::Decoratable do
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
describe "#==" do
|
49
|
+
context "with itself" do
|
50
|
+
it "returns true" do
|
51
|
+
(subject == subject).should be_true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with another instance" do
|
56
|
+
it "returns false" do
|
57
|
+
(subject == Product.new).should be_false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with a decorated version of itself" do
|
62
|
+
it "returns true" do
|
63
|
+
decorator = double(source: subject)
|
64
|
+
(subject == decorator).should be_true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "with a decorated other instance" do
|
69
|
+
it "returns false" do
|
70
|
+
decorator = double(source: Product.new)
|
71
|
+
(subject == decorator).should be_false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
48
76
|
describe "#===" do
|
49
77
|
context "with itself" do
|
50
78
|
it "returns true" do
|
@@ -125,9 +153,9 @@ describe Draper::Decoratable do
|
|
125
153
|
decorator.source.should be Product.scoped
|
126
154
|
end
|
127
155
|
|
128
|
-
it "accepts
|
129
|
-
decorator = Product.decorate(some:
|
130
|
-
decorator.
|
156
|
+
it "accepts context" do
|
157
|
+
decorator = Product.decorate(context: {some: 'context'})
|
158
|
+
decorator.context.should == {some: 'context'}
|
131
159
|
end
|
132
160
|
|
133
161
|
it "is not memoized" do
|
@@ -1,10 +1,52 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Draper::DecoratedAssociation do
|
4
|
-
let(:decorated_association) { Draper::DecoratedAssociation.new(
|
4
|
+
let(:decorated_association) { Draper::DecoratedAssociation.new(base, association, options) }
|
5
5
|
let(:source) { Product.new }
|
6
|
+
let(:base) { source.decorate }
|
6
7
|
let(:options) { {} }
|
7
8
|
|
9
|
+
describe "#initialize" do
|
10
|
+
describe "options validation" do
|
11
|
+
let(:association) { :similar_products }
|
12
|
+
let(:valid_options) { {with: ProductDecorator, scope: :foo, context: {}} }
|
13
|
+
|
14
|
+
it "does not raise error on valid options" do
|
15
|
+
expect { Draper::DecoratedAssociation.new(base, association, valid_options) }.to_not raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it "raises error on invalid options" do
|
19
|
+
expect { Draper::DecoratedAssociation.new(base, association, valid_options.merge(foo: 'bar')) }.to raise_error(ArgumentError, 'Unknown key: foo')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#base" do
|
25
|
+
subject { decorated_association.base }
|
26
|
+
let(:association) { :similar_products }
|
27
|
+
|
28
|
+
it "returns the base decorator" do
|
29
|
+
should be base
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns a Decorator" do
|
33
|
+
subject.class.should == ProductDecorator
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#source" do
|
38
|
+
subject { decorated_association.source }
|
39
|
+
let(:association) { :similar_products }
|
40
|
+
|
41
|
+
it "returns the base decorator's source" do
|
42
|
+
should be base.source
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns a Model" do
|
46
|
+
subject.class.should == Product
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
8
50
|
describe "#call" do
|
9
51
|
subject { decorated_association.call }
|
10
52
|
|
@@ -22,10 +64,11 @@ describe Draper::DecoratedAssociation do
|
|
22
64
|
end
|
23
65
|
|
24
66
|
context "when the association is empty" do
|
25
|
-
it "
|
67
|
+
it "returns an empty collection decorator" do
|
26
68
|
source.stub(:similar_products).and_return([])
|
27
|
-
subject.
|
69
|
+
subject.should be_a Draper::CollectionDecorator
|
28
70
|
subject.should be_empty
|
71
|
+
subject.first.should be_nil
|
29
72
|
end
|
30
73
|
end
|
31
74
|
end
|
@@ -44,10 +87,11 @@ describe Draper::DecoratedAssociation do
|
|
44
87
|
end
|
45
88
|
|
46
89
|
context "when the association is empty" do
|
47
|
-
it "
|
90
|
+
it "returns an empty collection decorator" do
|
48
91
|
source.stub(:poro_similar_products).and_return([])
|
49
|
-
subject.
|
92
|
+
subject.should be_a Draper::CollectionDecorator
|
50
93
|
subject.should be_empty
|
94
|
+
subject.first.should be_nil
|
51
95
|
end
|
52
96
|
end
|
53
97
|
end
|
@@ -126,5 +170,144 @@ describe Draper::DecoratedAssociation do
|
|
126
170
|
subject.source.should be scoped
|
127
171
|
end
|
128
172
|
end
|
173
|
+
|
174
|
+
context "base has context" do
|
175
|
+
let(:association) { :similar_products }
|
176
|
+
let(:base) { source.decorate(context: {some: 'context'}) }
|
177
|
+
|
178
|
+
context "when no context is specified" do
|
179
|
+
it "it should inherit context from base" do
|
180
|
+
subject.context.should == {some: 'context'}
|
181
|
+
end
|
182
|
+
|
183
|
+
it "it should share context hash with base" do
|
184
|
+
subject.context.should be base.context
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "when static context is specified" do
|
189
|
+
let(:options) { {context: {other: 'context'}} }
|
190
|
+
|
191
|
+
it "it should get context from static option" do
|
192
|
+
subject.context.should == {other: 'context'}
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "when lambda context is specified" do
|
197
|
+
let(:options) { {context: lambda {|context| context.merge(other: 'protext')}} }
|
198
|
+
|
199
|
+
it "it should get generated context" do
|
200
|
+
subject.context.should == {some: 'context', other: 'protext'}
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#decorator_options" do
|
207
|
+
subject { decorated_association.send(:decorator_options) }
|
208
|
+
|
209
|
+
context "collection association" do
|
210
|
+
let(:association) { :similar_products }
|
211
|
+
|
212
|
+
context "no options" do
|
213
|
+
it "should return default options" do
|
214
|
+
should == {with: :infer, context: {}}
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should set with: to :infer" do
|
218
|
+
decorated_association.send(:options).should == options
|
219
|
+
subject
|
220
|
+
decorated_association.send(:options).should == {with: :infer}
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context "option with: ProductDecorator" do
|
225
|
+
let(:options) { {with: ProductDecorator} }
|
226
|
+
it "should pass with: from options" do
|
227
|
+
should == {with: ProductDecorator, context: {}}
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "option scope: :to_a" do
|
232
|
+
let(:options) { {scope: :to_a} }
|
233
|
+
it "should strip scope: from options" do
|
234
|
+
decorated_association.send(:options).should == options
|
235
|
+
should == {with: :infer, context: {}}
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context "base has context" do
|
240
|
+
let(:base) { source.decorate(context: {some: 'context'}) }
|
241
|
+
|
242
|
+
context "no options" do
|
243
|
+
it "should return context from base" do
|
244
|
+
should == {with: :infer, context: {some: 'context'}}
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context "option context: {other: 'context'}" do
|
249
|
+
let(:options) { {context: {other: 'context'}} }
|
250
|
+
it "should return specified context" do
|
251
|
+
should == {with: :infer, context: {other: 'context'}}
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "option context: lambda" do
|
256
|
+
let(:options) { {context: lambda {|context| context.merge(other: 'protext')}} }
|
257
|
+
it "should return specified context" do
|
258
|
+
should == {with: :infer, context: {some: 'context', other: 'protext'}}
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context "singular association" do
|
265
|
+
let(:association) { :previous_version }
|
266
|
+
|
267
|
+
context "no options" do
|
268
|
+
it "should return default options" do
|
269
|
+
should == {context: {}}
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "option with: ProductDecorator" do
|
274
|
+
let(:options) { {with: ProductDecorator} }
|
275
|
+
it "should strip with: from options" do
|
276
|
+
should == {context: {}}
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
context "option scope: :decorate" do
|
281
|
+
let(:options) { {scope: :decorate} }
|
282
|
+
it "should strip scope: from options" do
|
283
|
+
decorated_association.send(:options).should == options
|
284
|
+
should == {context: {}}
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
context "base has context" do
|
289
|
+
let(:base) { source.decorate(context: {some: 'context'}) }
|
290
|
+
|
291
|
+
context "no options" do
|
292
|
+
it "should return context from base" do
|
293
|
+
should == {context: {some: 'context'}}
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context "option context: {other: 'context'}" do
|
298
|
+
let(:options) { {context: {other: 'context'}} }
|
299
|
+
it "should return specified context" do
|
300
|
+
should == {context: {other: 'context'}}
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context "option context: lambda" do
|
305
|
+
let(:options) { {context: lambda {|context| context.merge(other: 'protext')}} }
|
306
|
+
it "should return specified context" do
|
307
|
+
should == {context: {some: 'context', other: 'protext'}}
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
129
312
|
end
|
130
313
|
end
|
@@ -7,13 +7,25 @@ describe Draper::Decorator do
|
|
7
7
|
let(:source) { Product.new }
|
8
8
|
|
9
9
|
describe "#initialize" do
|
10
|
+
describe "options validation" do
|
11
|
+
let(:valid_options) { {context: {}} }
|
12
|
+
|
13
|
+
it "does not raise error on valid options" do
|
14
|
+
expect { decorator_class.new(source, valid_options) }.to_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it "raises error on invalid options" do
|
18
|
+
expect { decorator_class.new(source, valid_options.merge(foo: 'bar')) }.to raise_error(ArgumentError, 'Unknown key: foo')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
10
22
|
it "sets the source" do
|
11
23
|
subject.source.should be source
|
12
24
|
end
|
13
25
|
|
14
|
-
it "stores
|
15
|
-
decorator = decorator_class.new(source, some:
|
16
|
-
decorator.
|
26
|
+
it "stores context" do
|
27
|
+
decorator = decorator_class.new(source, context: {some: 'context'})
|
28
|
+
decorator.context.should == {some: 'context'}
|
17
29
|
end
|
18
30
|
|
19
31
|
context "when decorating an instance of itself" do
|
@@ -23,16 +35,16 @@ describe Draper::Decorator do
|
|
23
35
|
end
|
24
36
|
|
25
37
|
context "when options are supplied" do
|
26
|
-
it "overwrites existing
|
27
|
-
decorator = ProductDecorator.new(source, role: :admin)
|
28
|
-
ProductDecorator.new(decorator, role: :user).
|
38
|
+
it "overwrites existing context" do
|
39
|
+
decorator = ProductDecorator.new(source, context: {role: :admin})
|
40
|
+
ProductDecorator.new(decorator, context: {role: :user}).context.should == {role: :user}
|
29
41
|
end
|
30
42
|
end
|
31
43
|
|
32
44
|
context "when no options are supplied" do
|
33
|
-
it "preserves existing
|
34
|
-
decorator = ProductDecorator.new(source, role: :admin)
|
35
|
-
ProductDecorator.new(decorator).
|
45
|
+
it "preserves existing context" do
|
46
|
+
decorator = ProductDecorator.new(source, context: {role: :admin})
|
47
|
+
ProductDecorator.new(decorator).context.should == {role: :admin}
|
36
48
|
end
|
37
49
|
end
|
38
50
|
end
|
@@ -55,10 +67,31 @@ describe Draper::Decorator do
|
|
55
67
|
end
|
56
68
|
end
|
57
69
|
|
70
|
+
describe "#context=" do
|
71
|
+
it "modifies the context" do
|
72
|
+
decorator = decorator_class.new(source, context: {some: 'context'})
|
73
|
+
decorator.context = {some: 'other_context'}
|
74
|
+
decorator.context.should == {some: 'other_context'}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
58
78
|
describe ".decorate_collection" do
|
59
79
|
subject { ProductDecorator.decorate_collection(source) }
|
60
80
|
let(:source) { [Product.new, Widget.new] }
|
61
81
|
|
82
|
+
describe "options validation" do
|
83
|
+
let(:valid_options) { {with: :infer, context: {}} }
|
84
|
+
before(:each) { Draper::CollectionDecorator.stub(:new) }
|
85
|
+
|
86
|
+
it "does not raise error on valid options" do
|
87
|
+
expect { ProductDecorator.decorate_collection(source, valid_options) }.to_not raise_error
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raises error on invalid options" do
|
91
|
+
expect { ProductDecorator.decorate_collection(source, valid_options.merge(foo: 'bar')) }.to raise_error(ArgumentError, 'Unknown key: foo')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
62
95
|
it "returns a collection decorator" do
|
63
96
|
subject.should be_a Draper::CollectionDecorator
|
64
97
|
subject.source.should be source
|
@@ -77,11 +110,11 @@ describe Draper::Decorator do
|
|
77
110
|
end
|
78
111
|
end
|
79
112
|
|
80
|
-
context "with
|
81
|
-
subject { ProductDecorator.decorate_collection(source, with: :infer, some:
|
113
|
+
context "with context" do
|
114
|
+
subject { ProductDecorator.decorate_collection(source, with: :infer, context: {some: 'context'}) }
|
82
115
|
|
83
|
-
it "passes the
|
84
|
-
subject.
|
116
|
+
it "passes the context to the collection decorator" do
|
117
|
+
subject.context.should == {some: 'context'}
|
85
118
|
end
|
86
119
|
end
|
87
120
|
end
|
@@ -104,14 +137,14 @@ describe Draper::Decorator do
|
|
104
137
|
end
|
105
138
|
|
106
139
|
describe "#localize" do
|
107
|
-
before { subject.helpers.should_receive(:localize).with(:an_object, {some:
|
140
|
+
before { subject.helpers.should_receive(:localize).with(:an_object, {some: 'parameter'}) }
|
108
141
|
|
109
142
|
it "delegates to #helpers" do
|
110
|
-
subject.localize(:an_object, some:
|
143
|
+
subject.localize(:an_object, some: 'parameter')
|
111
144
|
end
|
112
145
|
|
113
146
|
it "is aliased to #l" do
|
114
|
-
subject.l(:an_object, some:
|
147
|
+
subject.l(:an_object, some: 'parameter')
|
115
148
|
end
|
116
149
|
end
|
117
150
|
|
@@ -223,8 +256,26 @@ describe Draper::Decorator do
|
|
223
256
|
describe "overridden association method" do
|
224
257
|
let(:decorated_association) { ->{} }
|
225
258
|
|
259
|
+
describe "options validation" do
|
260
|
+
let(:valid_options) { {with: ProductDecorator, scope: :foo, context: {}} }
|
261
|
+
before(:each) { Draper::DecoratedAssociation.stub(:new).and_return(decorated_association) }
|
262
|
+
|
263
|
+
it "does not raise error on valid options" do
|
264
|
+
expect { decorator_class.decorates_association :similar_products, valid_options }.to_not raise_error
|
265
|
+
end
|
266
|
+
|
267
|
+
it "raises error on invalid options" do
|
268
|
+
expect { decorator_class.decorates_association :similar_products, valid_options.merge(foo: 'bar') }.to raise_error(ArgumentError, 'Unknown key: foo')
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
226
272
|
it "creates a DecoratedAssociation" do
|
227
|
-
Draper::DecoratedAssociation.should_receive(:new).with(
|
273
|
+
Draper::DecoratedAssociation.should_receive(:new).with(subject, :similar_products, {with: ProductDecorator}).and_return(decorated_association)
|
274
|
+
subject.similar_products
|
275
|
+
end
|
276
|
+
|
277
|
+
it "receives the Decorator" do
|
278
|
+
Draper::DecoratedAssociation.should_receive(:new).with(kind_of(decorator_class), :similar_products, {with: ProductDecorator}).and_return(decorated_association)
|
228
279
|
subject.similar_products
|
229
280
|
end
|
230
281
|
|
data/spec/draper/finders_spec.rb
CHANGED
@@ -15,9 +15,9 @@ describe Draper::Finders do
|
|
15
15
|
decorator.source.should be found
|
16
16
|
end
|
17
17
|
|
18
|
-
it "passes
|
19
|
-
decorator = ProductDecorator.find(1, some:
|
20
|
-
decorator.
|
18
|
+
it "passes context to the decorator" do
|
19
|
+
decorator = ProductDecorator.find(1, context: {some: 'context'})
|
20
|
+
decorator.context.should == {some: 'context'}
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -55,10 +55,10 @@ describe Draper::Finders do
|
|
55
55
|
ProductDecorator.find_or_create_by_name_and_size("apples", "large")
|
56
56
|
end
|
57
57
|
|
58
|
-
it "passes
|
59
|
-
Product.should_receive(:find_by_name_and_size).with("apples", "large", {some:
|
60
|
-
decorator = ProductDecorator.find_by_name_and_size("apples", "large", some:
|
61
|
-
decorator.
|
58
|
+
it "passes context to the decorator" do
|
59
|
+
Product.should_receive(:find_by_name_and_size).with("apples", "large", context: {some: 'context'})
|
60
|
+
decorator = ProductDecorator.find_by_name_and_size("apples", "large", context: {some: 'context'})
|
61
|
+
decorator.context.should == {some: 'context'}
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -84,9 +84,9 @@ describe Draper::Finders do
|
|
84
84
|
collection.first.should be_a ProductDecorator
|
85
85
|
end
|
86
86
|
|
87
|
-
it "passes
|
88
|
-
collection = ProductDecorator.all(some:
|
89
|
-
collection.
|
87
|
+
it "passes context to the collection decorator" do
|
88
|
+
collection = ProductDecorator.all(context: {some: 'context'})
|
89
|
+
collection.context.should == {some: 'context'}
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
@@ -104,9 +104,9 @@ describe Draper::Finders do
|
|
104
104
|
decorator.source.should be first
|
105
105
|
end
|
106
106
|
|
107
|
-
it "passes
|
108
|
-
decorator = ProductDecorator.first(some:
|
109
|
-
decorator.
|
107
|
+
it "passes context to the decorator" do
|
108
|
+
decorator = ProductDecorator.first(context: {some: 'context'})
|
109
|
+
decorator.context.should == {some: 'context'}
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
@@ -124,9 +124,9 @@ describe Draper::Finders do
|
|
124
124
|
decorator.source.should be last
|
125
125
|
end
|
126
126
|
|
127
|
-
it "passes
|
128
|
-
decorator = ProductDecorator.last(some:
|
129
|
-
decorator.
|
127
|
+
it "passes context to the decorator" do
|
128
|
+
decorator = ProductDecorator.last(context: {some: 'context'})
|
129
|
+
decorator.context.should == {some: 'context'}
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: draper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta4
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-12-
|
13
|
+
date: 2012-12-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -44,6 +44,22 @@ dependencies:
|
|
44
44
|
- - ! '>='
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '3.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: request_store
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.0.0
|
47
63
|
- !ruby/object:Gem::Dependency
|
48
64
|
name: ammeter
|
49
65
|
requirement: !ruby/object:Gem::Requirement
|
@@ -274,9 +290,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
274
290
|
- - ! '>='
|
275
291
|
- !ruby/object:Gem::Version
|
276
292
|
version: '0'
|
277
|
-
segments:
|
278
|
-
- 0
|
279
|
-
hash: -1515210213471723462
|
280
293
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
281
294
|
none: false
|
282
295
|
requirements:
|
@@ -285,7 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
285
298
|
version: 1.3.1
|
286
299
|
requirements: []
|
287
300
|
rubyforge_project: draper
|
288
|
-
rubygems_version: 1.8.
|
301
|
+
rubygems_version: 1.8.23
|
289
302
|
signing_key:
|
290
303
|
specification_version: 3
|
291
304
|
summary: Decorator pattern implementation for Rails.
|