draper_new 3.0.0

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.
Files changed (144) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +15 -0
  5. data/.yardopts +1 -0
  6. data/CHANGELOG.md +230 -0
  7. data/CONTRIBUTING.md +20 -0
  8. data/Gemfile +16 -0
  9. data/Guardfile +26 -0
  10. data/LICENSE +7 -0
  11. data/README.md +587 -0
  12. data/Rakefile +69 -0
  13. data/draper_new.gemspec +31 -0
  14. data/gemfiles/4.0.gemfile +3 -0
  15. data/gemfiles/4.1.gemfile +3 -0
  16. data/gemfiles/4.2.6.gemfile +3 -0
  17. data/gemfiles/4.2.gemfile +3 -0
  18. data/lib/draper.rb +63 -0
  19. data/lib/draper/automatic_delegation.rb +56 -0
  20. data/lib/draper/collection_decorator.rb +100 -0
  21. data/lib/draper/decoratable.rb +96 -0
  22. data/lib/draper/decoratable/equality.rb +26 -0
  23. data/lib/draper/decorated_association.rb +35 -0
  24. data/lib/draper/decorates_assigned.rb +44 -0
  25. data/lib/draper/decorator.rb +293 -0
  26. data/lib/draper/delegation.rb +13 -0
  27. data/lib/draper/factory.rb +91 -0
  28. data/lib/draper/finders.rb +37 -0
  29. data/lib/draper/helper_proxy.rb +44 -0
  30. data/lib/draper/helper_support.rb +5 -0
  31. data/lib/draper/lazy_helpers.rb +15 -0
  32. data/lib/draper/railtie.rb +70 -0
  33. data/lib/draper/tasks/test.rake +22 -0
  34. data/lib/draper/test/devise_helper.rb +30 -0
  35. data/lib/draper/test/minitest_integration.rb +6 -0
  36. data/lib/draper/test/rspec_integration.rb +20 -0
  37. data/lib/draper/test_case.rb +42 -0
  38. data/lib/draper/undecorate.rb +9 -0
  39. data/lib/draper/version.rb +3 -0
  40. data/lib/draper/view_context.rb +104 -0
  41. data/lib/draper/view_context/build_strategy.rb +48 -0
  42. data/lib/draper/view_helpers.rb +37 -0
  43. data/lib/generators/controller_override.rb +17 -0
  44. data/lib/generators/mini_test/decorator_generator.rb +20 -0
  45. data/lib/generators/mini_test/templates/decorator_spec.rb +4 -0
  46. data/lib/generators/mini_test/templates/decorator_test.rb +4 -0
  47. data/lib/generators/rails/decorator_generator.rb +36 -0
  48. data/lib/generators/rails/templates/decorator.rb +19 -0
  49. data/lib/generators/rspec/decorator_generator.rb +9 -0
  50. data/lib/generators/rspec/templates/decorator_spec.rb +4 -0
  51. data/lib/generators/test_unit/decorator_generator.rb +9 -0
  52. data/lib/generators/test_unit/templates/decorator_test.rb +4 -0
  53. data/spec/draper/collection_decorator_spec.rb +307 -0
  54. data/spec/draper/decoratable/equality_spec.rb +10 -0
  55. data/spec/draper/decoratable_spec.rb +202 -0
  56. data/spec/draper/decorated_association_spec.rb +84 -0
  57. data/spec/draper/decorates_assigned_spec.rb +71 -0
  58. data/spec/draper/decorator_spec.rb +816 -0
  59. data/spec/draper/factory_spec.rb +251 -0
  60. data/spec/draper/finders_spec.rb +166 -0
  61. data/spec/draper/helper_proxy_spec.rb +61 -0
  62. data/spec/draper/lazy_helpers_spec.rb +21 -0
  63. data/spec/draper/undecorate_spec.rb +19 -0
  64. data/spec/draper/view_context/build_strategy_spec.rb +116 -0
  65. data/spec/draper/view_context_spec.rb +154 -0
  66. data/spec/draper/view_helpers_spec.rb +8 -0
  67. data/spec/dummy/.rspec +2 -0
  68. data/spec/dummy/Rakefile +7 -0
  69. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  70. data/spec/dummy/app/controllers/localized_urls.rb +5 -0
  71. data/spec/dummy/app/controllers/posts_controller.rb +20 -0
  72. data/spec/dummy/app/decorators/mongoid_post_decorator.rb +4 -0
  73. data/spec/dummy/app/decorators/post_decorator.rb +60 -0
  74. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  75. data/spec/dummy/app/mailers/application_mailer.rb +3 -0
  76. data/spec/dummy/app/mailers/post_mailer.rb +19 -0
  77. data/spec/dummy/app/models/admin.rb +5 -0
  78. data/spec/dummy/app/models/mongoid_post.rb +5 -0
  79. data/spec/dummy/app/models/post.rb +3 -0
  80. data/spec/dummy/app/models/user.rb +5 -0
  81. data/spec/dummy/app/views/layouts/application.html.erb +11 -0
  82. data/spec/dummy/app/views/post_mailer/decorated_email.html.erb +1 -0
  83. data/spec/dummy/app/views/posts/_post.html.erb +40 -0
  84. data/spec/dummy/app/views/posts/show.html.erb +1 -0
  85. data/spec/dummy/bin/rails +4 -0
  86. data/spec/dummy/config.ru +4 -0
  87. data/spec/dummy/config/application.rb +71 -0
  88. data/spec/dummy/config/boot.rb +5 -0
  89. data/spec/dummy/config/database.yml +25 -0
  90. data/spec/dummy/config/environment.rb +5 -0
  91. data/spec/dummy/config/environments/development.rb +33 -0
  92. data/spec/dummy/config/environments/production.rb +57 -0
  93. data/spec/dummy/config/environments/test.rb +31 -0
  94. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  95. data/spec/dummy/config/initializers/inflections.rb +15 -0
  96. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  97. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  98. data/spec/dummy/config/initializers/session_store.rb +8 -0
  99. data/spec/dummy/config/locales/en.yml +5 -0
  100. data/spec/dummy/config/mongoid.yml +79 -0
  101. data/spec/dummy/config/routes.rb +9 -0
  102. data/spec/dummy/db/migrate/20121019115657_create_posts.rb +8 -0
  103. data/spec/dummy/db/schema.rb +21 -0
  104. data/spec/dummy/db/seeds.rb +2 -0
  105. data/spec/dummy/fast_spec/post_decorator_spec.rb +37 -0
  106. data/spec/dummy/lib/tasks/test.rake +16 -0
  107. data/spec/dummy/public/404.html +26 -0
  108. data/spec/dummy/public/422.html +26 -0
  109. data/spec/dummy/public/500.html +25 -0
  110. data/spec/dummy/public/favicon.ico +0 -0
  111. data/spec/dummy/script/rails +6 -0
  112. data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +16 -0
  113. data/spec/dummy/spec/decorators/devise_spec.rb +64 -0
  114. data/spec/dummy/spec/decorators/helpers_spec.rb +21 -0
  115. data/spec/dummy/spec/decorators/post_decorator_spec.rb +66 -0
  116. data/spec/dummy/spec/decorators/spec_type_spec.rb +7 -0
  117. data/spec/dummy/spec/decorators/view_context_spec.rb +22 -0
  118. data/spec/dummy/spec/mailers/post_mailer_spec.rb +33 -0
  119. data/spec/dummy/spec/models/mongoid_post_spec.rb +8 -0
  120. data/spec/dummy/spec/models/post_spec.rb +6 -0
  121. data/spec/dummy/spec/shared_examples/decoratable.rb +24 -0
  122. data/spec/dummy/spec/spec_helper.rb +8 -0
  123. data/spec/dummy/test/decorators/minitest/devise_test.rb +64 -0
  124. data/spec/dummy/test/decorators/minitest/helpers_test.rb +21 -0
  125. data/spec/dummy/test/decorators/minitest/spec_type_test.rb +52 -0
  126. data/spec/dummy/test/decorators/minitest/view_context_test.rb +24 -0
  127. data/spec/dummy/test/decorators/test_unit/devise_test.rb +64 -0
  128. data/spec/dummy/test/decorators/test_unit/helpers_test.rb +21 -0
  129. data/spec/dummy/test/decorators/test_unit/view_context_test.rb +24 -0
  130. data/spec/dummy/test/minitest_helper.rb +2 -0
  131. data/spec/dummy/test/test_helper.rb +3 -0
  132. data/spec/generators/controller/controller_generator_spec.rb +22 -0
  133. data/spec/generators/decorator/decorator_generator_spec.rb +92 -0
  134. data/spec/integration/integration_spec.rb +66 -0
  135. data/spec/performance/active_record.rb +4 -0
  136. data/spec/performance/benchmark.rb +55 -0
  137. data/spec/performance/decorators.rb +45 -0
  138. data/spec/performance/models.rb +20 -0
  139. data/spec/spec_helper.rb +41 -0
  140. data/spec/support/dummy_app.rb +85 -0
  141. data/spec/support/matchers/have_text.rb +50 -0
  142. data/spec/support/shared_examples/decoratable_equality.rb +40 -0
  143. data/spec/support/shared_examples/view_helpers.rb +39 -0
  144. metadata +420 -0
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module Draper
4
+ describe LazyHelpers do
5
+ describe "#method_missing" do
6
+ let(:decorator) do
7
+ Struct.new(:helpers){include Draper::LazyHelpers}.new(double)
8
+ end
9
+
10
+ it "proxies methods to #helpers" do
11
+ decorator.helpers.stub(:foo) { |arg| arg }
12
+ expect(decorator.foo(:passed)).to be :passed
13
+ end
14
+
15
+ it "passes blocks" do
16
+ decorator.helpers.stub(:foo) { |&block| block.call }
17
+ expect(decorator.foo{:yielded}).to be :yielded
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Draper, '.undecorate' do
4
+ it 'undecorates a decorated object' do
5
+ object = Model.new
6
+ decorator = Draper::Decorator.new(object)
7
+ expect(Draper.undecorate(decorator)).to equal object
8
+ end
9
+
10
+ it 'passes a non-decorated object through' do
11
+ object = Model.new
12
+ expect(Draper.undecorate(object)).to equal object
13
+ end
14
+
15
+ it 'passes a non-decorator object through' do
16
+ object = Object.new
17
+ expect(Draper.undecorate(object)).to equal object
18
+ end
19
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ def fake_view_context
4
+ double("ViewContext")
5
+ end
6
+
7
+ def fake_controller(view_context = fake_view_context)
8
+ double("Controller", view_context: view_context, request: double("Request"))
9
+ end
10
+
11
+ module Draper
12
+ describe ViewContext::BuildStrategy::Full do
13
+ describe "#call" do
14
+ context "when a current controller is set" do
15
+ it "returns the controller's view context" do
16
+ view_context = fake_view_context
17
+ ViewContext.stub controller: fake_controller(view_context)
18
+ strategy = ViewContext::BuildStrategy::Full.new
19
+
20
+ expect(strategy.call).to be view_context
21
+ end
22
+ end
23
+
24
+ context "when a current controller is not set" do
25
+ it "uses ApplicationController" do
26
+ view_context = fake_view_context
27
+ stub_const "ApplicationController", double(new: fake_controller(view_context))
28
+ strategy = ViewContext::BuildStrategy::Full.new
29
+
30
+ expect(strategy.call).to be view_context
31
+ end
32
+ end
33
+
34
+ it "adds a request if one is not defined" do
35
+ controller = Class.new(ActionController::Base).new
36
+ ViewContext.stub controller: controller
37
+ strategy = ViewContext::BuildStrategy::Full.new
38
+
39
+ expect(controller.request).to be_nil
40
+ strategy.call
41
+ expect(controller.request).to be_an ActionController::TestRequest
42
+ expect(controller.params).to eq({})
43
+
44
+ # sanity checks
45
+ expect(controller.view_context.request).to be controller.request
46
+ expect(controller.view_context.params).to be controller.params
47
+ end
48
+
49
+ it "adds methods to the view context from the constructor block" do
50
+ ViewContext.stub controller: fake_controller
51
+ strategy = ViewContext::BuildStrategy::Full.new do
52
+ def a_helper_method; end
53
+ end
54
+
55
+ expect(strategy.call).to respond_to :a_helper_method
56
+ end
57
+
58
+ it "includes modules into the view context from the constructor block" do
59
+ view_context = Object.new
60
+ ViewContext.stub controller: fake_controller(view_context)
61
+ helpers = Module.new do
62
+ def a_helper_method; end
63
+ end
64
+ strategy = ViewContext::BuildStrategy::Full.new do
65
+ include helpers
66
+ end
67
+
68
+ expect(strategy.call).to respond_to :a_helper_method
69
+ end
70
+ end
71
+ end
72
+
73
+ describe ViewContext::BuildStrategy::Fast do
74
+ describe "#call" do
75
+ it "returns an instance of a subclass of ActionView::Base" do
76
+ strategy = ViewContext::BuildStrategy::Fast.new
77
+
78
+ returned = strategy.call
79
+
80
+ expect(returned).to be_an ActionView::Base
81
+ expect(returned.class).not_to be ActionView::Base
82
+ end
83
+
84
+ it "returns different instances each time" do
85
+ strategy = ViewContext::BuildStrategy::Fast.new
86
+
87
+ expect(strategy.call).not_to be strategy.call
88
+ end
89
+
90
+ it "returns the same subclass each time" do
91
+ strategy = ViewContext::BuildStrategy::Fast.new
92
+
93
+ expect(strategy.call.class).to be strategy.call.class
94
+ end
95
+
96
+ it "adds methods to the view context from the constructor block" do
97
+ strategy = ViewContext::BuildStrategy::Fast.new do
98
+ def a_helper_method; end
99
+ end
100
+
101
+ expect(strategy.call).to respond_to :a_helper_method
102
+ end
103
+
104
+ it "includes modules into the view context from the constructor block" do
105
+ helpers = Module.new do
106
+ def a_helper_method; end
107
+ end
108
+ strategy = ViewContext::BuildStrategy::Fast.new do
109
+ include helpers
110
+ end
111
+
112
+ expect(strategy.call).to respond_to :a_helper_method
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,154 @@
1
+ require 'spec_helper'
2
+
3
+ module Draper
4
+ describe ViewContext do
5
+ describe "#view_context" do
6
+ let(:base) { Class.new { def view_context; :controller_view_context; end } }
7
+ let(:controller) { Class.new(base) { include ViewContext } }
8
+
9
+ it "saves the superclass's view context" do
10
+ ViewContext.should_receive(:current=).with(:controller_view_context)
11
+ controller.new.view_context
12
+ end
13
+
14
+ it "returns the superclass's view context" do
15
+ expect(controller.new.view_context).to be :controller_view_context
16
+ end
17
+ end
18
+
19
+ describe ".controller" do
20
+ it "returns the stored controller from RequestStore" do
21
+ RequestStore.stub store: {current_controller: :stored_controller}
22
+
23
+ expect(ViewContext.controller).to be :stored_controller
24
+ end
25
+ end
26
+
27
+ describe ".controller=" do
28
+ it "stores a controller in RequestStore" do
29
+ store = {}
30
+ RequestStore.stub store: store
31
+
32
+ ViewContext.controller = :stored_controller
33
+ expect(store[:current_controller]).to be :stored_controller
34
+ end
35
+ end
36
+
37
+ describe ".current" do
38
+ it "returns the stored view context from RequestStore" do
39
+ RequestStore.stub store: {current_view_context: :stored_view_context}
40
+
41
+ expect(ViewContext.current).to be :stored_view_context
42
+ end
43
+
44
+ context "when no view context is stored" do
45
+ it "builds a view context" do
46
+ RequestStore.stub store: {}
47
+ ViewContext.stub build_strategy: ->{ :new_view_context }
48
+ HelperProxy.stub(:new).with(:new_view_context).and_return(:new_helper_proxy)
49
+
50
+ expect(ViewContext.current).to be :new_helper_proxy
51
+ end
52
+
53
+ it "stores the built view context" do
54
+ store = {}
55
+ RequestStore.stub store: store
56
+ ViewContext.stub build_strategy: ->{ :new_view_context }
57
+ HelperProxy.stub(:new).with(:new_view_context).and_return(:new_helper_proxy)
58
+
59
+ ViewContext.current
60
+ expect(store[:current_view_context]).to be :new_helper_proxy
61
+ end
62
+ end
63
+ end
64
+
65
+ describe ".current=" do
66
+ it "stores a helper proxy for the view context in RequestStore" do
67
+ store = {}
68
+ RequestStore.stub store: store
69
+ HelperProxy.stub(:new).with(:stored_view_context).and_return(:stored_helper_proxy)
70
+
71
+ ViewContext.current = :stored_view_context
72
+ expect(store[:current_view_context]).to be :stored_helper_proxy
73
+ end
74
+ end
75
+
76
+ describe ".clear!" do
77
+ it "clears the stored controller and view controller" do
78
+ store = {current_controller: :stored_controller, current_view_context: :stored_view_context}
79
+ RequestStore.stub store: store
80
+
81
+ ViewContext.clear!
82
+ expect(store).not_to have_key :current_controller
83
+ expect(store).not_to have_key :current_view_context
84
+ end
85
+ end
86
+
87
+ describe ".build" do
88
+ it "returns a new view context using the build strategy" do
89
+ ViewContext.stub build_strategy: ->{ :new_view_context }
90
+
91
+ expect(ViewContext.build).to be :new_view_context
92
+ end
93
+ end
94
+
95
+ describe ".build!" do
96
+ it "returns a helper proxy for the new view context" do
97
+ ViewContext.stub build_strategy: ->{ :new_view_context }
98
+ HelperProxy.stub(:new).with(:new_view_context).and_return(:new_helper_proxy)
99
+
100
+ expect(ViewContext.build!).to be :new_helper_proxy
101
+ end
102
+
103
+ it "stores the helper proxy" do
104
+ store = {}
105
+ RequestStore.stub store: store
106
+ ViewContext.stub build_strategy: ->{ :new_view_context }
107
+ HelperProxy.stub(:new).with(:new_view_context).and_return(:new_helper_proxy)
108
+
109
+ ViewContext.build!
110
+ expect(store[:current_view_context]).to be :new_helper_proxy
111
+ end
112
+ end
113
+
114
+ describe ".build_strategy" do
115
+ it "defaults to full" do
116
+ expect(ViewContext.build_strategy).to be_a ViewContext::BuildStrategy::Full
117
+ end
118
+
119
+ it "memoizes" do
120
+ expect(ViewContext.build_strategy).to be ViewContext.build_strategy
121
+ end
122
+ end
123
+
124
+ describe ".test_strategy" do
125
+ protect_module ViewContext
126
+
127
+ context "with :fast" do
128
+ it "creates a fast strategy" do
129
+ ViewContext.test_strategy :fast
130
+ expect(ViewContext.build_strategy).to be_a ViewContext::BuildStrategy::Fast
131
+ end
132
+
133
+ it "passes a block to the strategy" do
134
+ ViewContext::BuildStrategy::Fast.stub(:new) { |&block| block.call }
135
+
136
+ expect(ViewContext.test_strategy(:fast){:passed}).to be :passed
137
+ end
138
+ end
139
+
140
+ context "with :full" do
141
+ it "creates a full strategy" do
142
+ ViewContext.test_strategy :full
143
+ expect(ViewContext.build_strategy).to be_a ViewContext::BuildStrategy::Full
144
+ end
145
+
146
+ it "passes a block to the strategy" do
147
+ ViewContext::BuildStrategy::Full.stub(:new) { |&block| block.call }
148
+
149
+ expect(ViewContext.test_strategy(:full){:passed}).to be :passed
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'support/shared_examples/view_helpers'
3
+
4
+ module Draper
5
+ describe ViewHelpers do
6
+ it_behaves_like "view helpers", Class.new{include ViewHelpers}.new
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,4 @@
1
+ class ApplicationController < ActionController::Base
2
+ include LocalizedUrls
3
+ protect_from_forgery
4
+ end
@@ -0,0 +1,5 @@
1
+ module LocalizedUrls
2
+ def default_url_options(options = {})
3
+ {locale: I18n.locale, host: "www.example.com", port: 12345}
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ class PostsController < ApplicationController
2
+ decorates_assigned :post
3
+
4
+ def show
5
+ @post = Post.find(params[:id])
6
+ end
7
+
8
+ def mail
9
+ post = Post.find(params[:id])
10
+ email = PostMailer.decorated_email(post).deliver
11
+ render text: email.body
12
+ end
13
+
14
+ private
15
+
16
+ def goodnight_moon
17
+ "Goodnight, moon!"
18
+ end
19
+ helper_method :goodnight_moon
20
+ end
@@ -0,0 +1,4 @@
1
+ if defined?(Mongoid)
2
+ class MongoidPostDecorator < Draper::Decorator
3
+ end
4
+ end
@@ -0,0 +1,60 @@
1
+ class PostDecorator < Draper::Decorator
2
+ # don't delegate_all here because it helps to identify things we
3
+ # have to delegate for ActiveModel compatibility
4
+
5
+ # need to delegate attribute methods for AM::Serialization
6
+ # need to delegate id and new_record? for AR::Base#== (Rails 3.0 only)
7
+ delegate :id, :created_at, :new_record?
8
+
9
+ def posted_date
10
+ if created_at.to_date == DateTime.now.utc.to_date
11
+ "Today"
12
+ else
13
+ "Not Today"
14
+ end
15
+ end
16
+
17
+ def path_with_model
18
+ h.post_path(object)
19
+ end
20
+
21
+ def path_with_id
22
+ h.post_path(id: id)
23
+ end
24
+
25
+ def url_with_model
26
+ h.post_url(object)
27
+ end
28
+
29
+ def url_with_id
30
+ h.post_url(id: id)
31
+ end
32
+
33
+ def link
34
+ h.link_to id.to_s, self
35
+ end
36
+
37
+ def truncated
38
+ h.truncate("Once upon a time in a world far far away", length: 17, separator: ' ')
39
+ end
40
+
41
+ def html_escaped
42
+ h.html_escape("<script>danger</script>")
43
+ end
44
+
45
+ def hello_world
46
+ h.hello_world
47
+ end
48
+
49
+ def goodnight_moon
50
+ h.goodnight_moon
51
+ end
52
+
53
+ def updated_at
54
+ :overridden
55
+ end
56
+
57
+ def persisted?
58
+ true
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ module ApplicationHelper
2
+ def hello_world
3
+ "Hello, world!"
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationMailer < ActionMailer::Base
2
+ include LocalizedUrls
3
+ end