draper_new 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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