drape 1.0.0.beta1

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 (181) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +27 -0
  3. data/.gitignore +18 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +1159 -0
  6. data/.travis.yml +14 -0
  7. data/.yardopts +1 -0
  8. data/CHANGELOG.md +230 -0
  9. data/CONTRIBUTING.md +20 -0
  10. data/Gemfile +16 -0
  11. data/Guardfile +26 -0
  12. data/LICENSE +7 -0
  13. data/README.md +592 -0
  14. data/Rakefile +76 -0
  15. data/drape.gemspec +31 -0
  16. data/gemfiles/5.0.gemfile +8 -0
  17. data/lib/drape.rb +63 -0
  18. data/lib/drape/automatic_delegation.rb +55 -0
  19. data/lib/drape/collection_decorator.rb +102 -0
  20. data/lib/drape/decoratable.rb +93 -0
  21. data/lib/drape/decoratable/equality.rb +26 -0
  22. data/lib/drape/decorated_association.rb +33 -0
  23. data/lib/drape/decorates_assigned.rb +44 -0
  24. data/lib/drape/decorator.rb +282 -0
  25. data/lib/drape/delegation.rb +13 -0
  26. data/lib/drape/factory.rb +91 -0
  27. data/lib/drape/finders.rb +36 -0
  28. data/lib/drape/helper_proxy.rb +43 -0
  29. data/lib/drape/helper_support.rb +5 -0
  30. data/lib/drape/lazy_helpers.rb +13 -0
  31. data/lib/drape/railtie.rb +69 -0
  32. data/lib/drape/tasks/test.rake +9 -0
  33. data/lib/drape/test/devise_helper.rb +30 -0
  34. data/lib/drape/test/minitest_integration.rb +6 -0
  35. data/lib/drape/test/rspec_integration.rb +20 -0
  36. data/lib/drape/test_case.rb +42 -0
  37. data/lib/drape/undecorate.rb +9 -0
  38. data/lib/drape/version.rb +3 -0
  39. data/lib/drape/view_context.rb +104 -0
  40. data/lib/drape/view_context/build_strategy.rb +46 -0
  41. data/lib/drape/view_helpers.rb +34 -0
  42. data/lib/generators/controller_override.rb +17 -0
  43. data/lib/generators/mini_test/decorator_generator.rb +20 -0
  44. data/lib/generators/mini_test/templates/decorator_spec.rb +4 -0
  45. data/lib/generators/mini_test/templates/decorator_test.rb +4 -0
  46. data/lib/generators/rails/decorator_generator.rb +36 -0
  47. data/lib/generators/rails/templates/decorator.rb +19 -0
  48. data/lib/generators/rspec/decorator_generator.rb +9 -0
  49. data/lib/generators/rspec/templates/decorator_spec.rb +4 -0
  50. data/lib/generators/test_unit/decorator_generator.rb +9 -0
  51. data/lib/generators/test_unit/templates/decorator_test.rb +4 -0
  52. data/spec/draper/collection_decorator_spec.rb +305 -0
  53. data/spec/draper/decoratable/equality_spec.rb +10 -0
  54. data/spec/draper/decoratable_spec.rb +203 -0
  55. data/spec/draper/decorated_association_spec.rb +85 -0
  56. data/spec/draper/decorates_assigned_spec.rb +70 -0
  57. data/spec/draper/decorator_spec.rb +828 -0
  58. data/spec/draper/factory_spec.rb +250 -0
  59. data/spec/draper/finders_spec.rb +165 -0
  60. data/spec/draper/helper_proxy_spec.rb +61 -0
  61. data/spec/draper/lazy_helpers_spec.rb +21 -0
  62. data/spec/draper/undecorate_spec.rb +19 -0
  63. data/spec/draper/view_context/build_strategy_spec.rb +116 -0
  64. data/spec/draper/view_context_spec.rb +160 -0
  65. data/spec/draper/view_helpers_spec.rb +8 -0
  66. data/spec/dummy/.gitignore +21 -0
  67. data/spec/dummy/Rakefile +6 -0
  68. data/spec/dummy/app/assets/config/manifest.js +3 -0
  69. data/spec/dummy/app/assets/images/.keep +0 -0
  70. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  71. data/spec/dummy/app/assets/javascripts/cable.js +13 -0
  72. data/spec/dummy/app/assets/javascripts/channels/.keep +0 -0
  73. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  74. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  75. data/spec/dummy/app/channels/application_cable/connection.rb +5 -0
  76. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  77. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  78. data/spec/dummy/app/controllers/posts_controller.rb +21 -0
  79. data/spec/dummy/app/decorators/mongoid_post_decorator.rb +4 -0
  80. data/spec/dummy/app/decorators/post_decorator.rb +59 -0
  81. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  82. data/spec/dummy/app/jobs/application_job.rb +2 -0
  83. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  84. data/spec/dummy/app/mailers/post_mailer.rb +18 -0
  85. data/spec/dummy/app/models/admin.rb +5 -0
  86. data/spec/dummy/app/models/application_record.rb +3 -0
  87. data/spec/dummy/app/models/concerns/.keep +0 -0
  88. data/spec/dummy/app/models/mongoid_post.rb +5 -0
  89. data/spec/dummy/app/models/post.rb +3 -0
  90. data/spec/dummy/app/models/user.rb +5 -0
  91. data/spec/dummy/app/views/layouts/application.html.erb +9 -0
  92. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  93. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  94. data/spec/dummy/app/views/post_mailer/decorated_email.html.erb +31 -0
  95. data/spec/dummy/app/views/posts/_post.html.erb +40 -0
  96. data/spec/dummy/app/views/posts/show.html.erb +1 -0
  97. data/spec/dummy/bin/bundle +3 -0
  98. data/spec/dummy/bin/rails +9 -0
  99. data/spec/dummy/bin/rake +9 -0
  100. data/spec/dummy/bin/setup +34 -0
  101. data/spec/dummy/bin/spring +15 -0
  102. data/spec/dummy/bin/update +29 -0
  103. data/spec/dummy/config.ru +5 -0
  104. data/spec/dummy/config/application.rb +21 -0
  105. data/spec/dummy/config/boot.rb +2 -0
  106. data/spec/dummy/config/cable.yml +10 -0
  107. data/spec/dummy/config/database.yml +25 -0
  108. data/spec/dummy/config/environment.rb +5 -0
  109. data/spec/dummy/config/environments/development.rb +51 -0
  110. data/spec/dummy/config/environments/production.rb +91 -0
  111. data/spec/dummy/config/environments/test.rb +42 -0
  112. data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +6 -0
  113. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
  114. data/spec/dummy/config/initializers/assets.rb +11 -0
  115. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  116. data/spec/dummy/config/initializers/callback_terminator.rb +6 -0
  117. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  118. data/spec/dummy/config/initializers/devise.rb +3 -0
  119. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  120. data/spec/dummy/config/initializers/inflections.rb +16 -0
  121. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  122. data/spec/dummy/config/initializers/per_form_csrf_tokens.rb +4 -0
  123. data/spec/dummy/config/initializers/request_forgery_protection.rb +4 -0
  124. data/spec/dummy/config/initializers/session_store.rb +3 -0
  125. data/spec/dummy/config/initializers/ssl_options.rb +4 -0
  126. data/spec/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  127. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  128. data/spec/dummy/config/locales/en.yml +23 -0
  129. data/spec/dummy/config/mongoid.yml +16 -0
  130. data/spec/dummy/config/puma.rb +47 -0
  131. data/spec/dummy/config/routes.rb +8 -0
  132. data/spec/dummy/config/secrets.yml +22 -0
  133. data/spec/dummy/config/spring.rb +6 -0
  134. data/spec/dummy/db/migrate/20121019115657_create_posts.rb +7 -0
  135. data/spec/dummy/db/schema.rb +19 -0
  136. data/spec/dummy/db/seeds.rb +2 -0
  137. data/spec/dummy/lib/assets/.keep +0 -0
  138. data/spec/dummy/lib/tasks/.keep +0 -0
  139. data/spec/dummy/lib/tasks/test.rake +16 -0
  140. data/spec/dummy/log/.keep +0 -0
  141. data/spec/dummy/public/404.html +67 -0
  142. data/spec/dummy/public/422.html +67 -0
  143. data/spec/dummy/public/500.html +66 -0
  144. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  145. data/spec/dummy/public/apple-touch-icon.png +0 -0
  146. data/spec/dummy/public/favicon.ico +0 -0
  147. data/spec/dummy/public/robots.txt +5 -0
  148. data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +12 -0
  149. data/spec/dummy/spec/decorators/devise_spec.rb +64 -0
  150. data/spec/dummy/spec/decorators/helpers_spec.rb +21 -0
  151. data/spec/dummy/spec/decorators/post_decorator_spec.rb +66 -0
  152. data/spec/dummy/spec/decorators/spec_type_spec.rb +7 -0
  153. data/spec/dummy/spec/decorators/view_context_spec.rb +22 -0
  154. data/spec/dummy/spec/mailers/post_mailer_spec.rb +33 -0
  155. data/spec/dummy/spec/models/mongoid_post_spec.rb +8 -0
  156. data/spec/dummy/spec/models/post_spec.rb +6 -0
  157. data/spec/dummy/spec/shared_examples/decoratable.rb +26 -0
  158. data/spec/dummy/spec/spec_helper.rb +8 -0
  159. data/spec/dummy/test/controllers/.keep +0 -0
  160. data/spec/dummy/test/fixtures/.keep +0 -0
  161. data/spec/dummy/test/fixtures/files/.keep +0 -0
  162. data/spec/dummy/test/helpers/.keep +0 -0
  163. data/spec/dummy/test/integration/.keep +0 -0
  164. data/spec/dummy/test/mailers/.keep +0 -0
  165. data/spec/dummy/test/models/.keep +0 -0
  166. data/spec/dummy/test/test_helper.rb +10 -0
  167. data/spec/dummy/vendor/assets/javascripts/.keep +0 -0
  168. data/spec/dummy/vendor/assets/stylesheets/.keep +0 -0
  169. data/spec/generators/controller/controller_generator_spec.rb +24 -0
  170. data/spec/generators/decorator/decorator_generator_spec.rb +94 -0
  171. data/spec/integration/integration_spec.rb +68 -0
  172. data/spec/performance/active_record.rb +4 -0
  173. data/spec/performance/benchmark.rb +57 -0
  174. data/spec/performance/decorators.rb +41 -0
  175. data/spec/performance/models.rb +20 -0
  176. data/spec/spec_helper.rb +41 -0
  177. data/spec/support/dummy_app.rb +88 -0
  178. data/spec/support/matchers/have_text.rb +50 -0
  179. data/spec/support/shared_examples/decoratable_equality.rb +40 -0
  180. data/spec/support/shared_examples/view_helpers.rb +39 -0
  181. metadata +497 -0
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples/decoratable'
3
+
4
+ if defined?(Mongoid)
5
+ describe MongoidPost do
6
+ it_behaves_like 'a decoratable model'
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'shared_examples/decoratable'
3
+
4
+ describe Post do
5
+ it_behaves_like 'a decoratable model'
6
+ end
@@ -0,0 +1,26 @@
1
+ shared_examples_for 'a decoratable model' do
2
+ describe '.decorate' do
3
+ it 'applies a collection decorator to a scope' do
4
+ described_class.create
5
+ decorated = described_class.limit(1).decorate
6
+
7
+ expect(decorated.size).to eq(1)
8
+ expect(decorated).to be_decorated
9
+ end
10
+ end
11
+
12
+ describe '#==' do
13
+ it "is true for other instances' decorators" do
14
+ if defined?(Mongoid) && Mongoid::VERSION.to_f < 3.1 && described_class < Mongoid::Document
15
+ pending 'Mongoid < 3.1 overrides `#==`'
16
+ end
17
+
18
+ described_class.create
19
+ one = described_class.first
20
+ other = described_class.first
21
+
22
+ expect(one).not_to be(other)
23
+ expect(one == other.decorate).to be_truthy
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ require 'rspec/rails'
4
+
5
+ RSpec.configure do |config|
6
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
7
+ config.order = :random
8
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,10 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ require 'rails/test_help'
4
+
5
+ class ActiveSupport::TestCase
6
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
7
+ fixtures :all
8
+
9
+ # Add more helper methods to be used by all tests here...
10
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'rails'
3
+
4
+ # TODO: Fix this file
5
+ # require 'ammeter/init'
6
+ # require 'generators/controller_override'
7
+ # require 'generators/rails/decorator_generator'
8
+
9
+ # describe Rails::Generators::ControllerGenerator do
10
+ # destination File.expand_path('../tmp', __FILE__)
11
+ #
12
+ # before { prepare_destination }
13
+ # after(:all) { FileUtils.rm_rf destination_root }
14
+ #
15
+ # describe 'the generated decorator' do
16
+ # subject { file('app/decorators/your_model_decorator.rb') }
17
+ #
18
+ # describe 'naming' do
19
+ # before { run_generator %w(YourModels) }
20
+ #
21
+ # it { should contain 'class YourModelDecorator' }
22
+ # end
23
+ # end
24
+ # end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'rails'
3
+
4
+ # TODO: Fix this file
5
+ # require 'ammeter/init'
6
+ # require 'generators/rails/decorator_generator'
7
+ #
8
+ # describe Rails::Generators::DecoratorGenerator do
9
+ # destination File.expand_path("../tmp", __FILE__)
10
+ #
11
+ # before { prepare_destination }
12
+ # after(:all) { FileUtils.rm_rf destination_root }
13
+ #
14
+ # describe "the generated decorator" do
15
+ # subject { file("app/decorators/your_model_decorator.rb") }
16
+ #
17
+ # describe "naming" do
18
+ # before { run_generator %w(YourModel) }
19
+ #
20
+ # it { should contain "class YourModelDecorator" }
21
+ # end
22
+ #
23
+ # describe "namespacing" do
24
+ # subject { file("app/decorators/namespace/your_model_decorator.rb") }
25
+ # before { run_generator %w(Namespace::YourModel) }
26
+ #
27
+ # it { should contain "class Namespace::YourModelDecorator" }
28
+ # end
29
+ #
30
+ # describe "inheritance" do
31
+ # context "by default" do
32
+ # before { run_generator %w(YourModel) }
33
+ #
34
+ # it { should contain "class YourModelDecorator < Drape::Decorator" }
35
+ # end
36
+ #
37
+ # context "with the --parent option" do
38
+ # before { run_generator %w(YourModel --parent=FooDecorator) }
39
+ #
40
+ # it { should contain "class YourModelDecorator < FooDecorator" }
41
+ # end
42
+ #
43
+ # context "with an ApplicationDecorator" do
44
+ # before do
45
+ # allow_any_instance_of(Object).to receive(:require).with("application_decorator").and_return(
46
+ # stub_const "ApplicationDecorator", Class.new
47
+ # )
48
+ # end
49
+ #
50
+ # before { run_generator %w(YourModel) }
51
+ #
52
+ # it { should contain "class YourModelDecorator < ApplicationDecorator" }
53
+ # end
54
+ # end
55
+ # end
56
+ #
57
+ # context "with -t=rspec" do
58
+ # describe "the generated spec" do
59
+ # subject { file("spec/decorators/your_model_decorator_spec.rb") }
60
+ #
61
+ # describe "naming" do
62
+ # before { run_generator %w(YourModel -t=rspec) }
63
+ #
64
+ # it { should contain "describe YourModelDecorator" }
65
+ # end
66
+ #
67
+ # describe "namespacing" do
68
+ # subject { file("spec/decorators/namespace/your_model_decorator_spec.rb") }
69
+ # before { run_generator %w(Namespace::YourModel -t=rspec) }
70
+ #
71
+ # it { should contain "describe Namespace::YourModelDecorator" }
72
+ # end
73
+ # end
74
+ # end
75
+ #
76
+ # context "with -t=test_unit" do
77
+ # describe "the generated test" do
78
+ # subject { file("test/decorators/your_model_decorator_test.rb") }
79
+ #
80
+ # describe "naming" do
81
+ # before { run_generator %w(YourModel -t=test_unit) }
82
+ #
83
+ # it { should contain "class YourModelDecoratorTest < Drape::TestCase" }
84
+ # end
85
+ #
86
+ # describe "namespacing" do
87
+ # subject { file("test/decorators/namespace/your_model_decorator_test.rb") }
88
+ # before { run_generator %w(Namespace::YourModel -t=test_unit) }
89
+ #
90
+ # it { should contain "class Namespace::YourModelDecoratorTest < Drape::TestCase" }
91
+ # end
92
+ # end
93
+ # end
94
+ # end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'support/dummy_app'
3
+ require 'support/matchers/have_text'
4
+
5
+ app = DummyApp.new(ENV['RAILS_ENV'])
6
+ spec_types = {
7
+ view: ['/posts/1', 'PostsController'],
8
+ mailer: ['/posts/1/mail', 'PostMailer']
9
+ }
10
+
11
+ app.start_server do
12
+ spec_types.each do |type, (path, controller)|
13
+ page = app.get(path)
14
+
15
+ describe "in a #{type}" do
16
+ it 'runs in the correct environment' do
17
+ expect(page).to have_text(app.environment).in('#environment')
18
+ end
19
+
20
+ it 'uses the correct view context controller' do
21
+ expect(page).to have_text(controller).in('#controller')
22
+ end
23
+
24
+ it 'can use built-in helpers' do
25
+ expect(page).to have_text('Once upon a...').in('#truncated')
26
+ end
27
+
28
+ it 'can use built-in private helpers' do
29
+ # Nokogiri unescapes text!
30
+ expect(page).to have_text('<script>danger</script>').in('#html_escaped')
31
+ end
32
+
33
+ it 'can use user-defined helpers from app/helpers' do
34
+ expect(page).to have_text('Hello, world!').in('#hello_world')
35
+ end
36
+
37
+ it 'can use user-defined helpers from the controller' do
38
+ expect(page).to have_text('Goodnight, moon!').in('#goodnight_moon')
39
+ end
40
+
41
+ if type != :mailer
42
+ it 'can be passed to path helpers' do
43
+ expect(page).to have_text('/posts/1').in('#path_with_decorator')
44
+ end
45
+
46
+ it 'can use path helpers with a model' do
47
+ expect(page).to have_text('/posts/1').in('#path_with_model')
48
+ end
49
+
50
+ it 'can use path helpers with an id' do
51
+ expect(page).to have_text('/posts/1').in('#path_with_id')
52
+ end
53
+ end
54
+
55
+ it 'can be passed to url helpers' do
56
+ expect(page).to have_text('http://test.host/posts/1').in('#url_with_decorator')
57
+ end
58
+
59
+ it 'can use url helpers with a model' do
60
+ expect(page).to have_text('http://test.host/posts/1').in('#url_with_model')
61
+ end
62
+
63
+ it 'can use url helpers with an id' do
64
+ expect(page).to have_text('http://test.host/posts/1').in('#url_with_id')
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,4 @@
1
+ module ActiveRecord
2
+ class Base
3
+ end
4
+ end
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+
3
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5
+
6
+ Bundler.require(:default) if defined?(Bundler)
7
+
8
+ require 'benchmark'
9
+ require 'drape'
10
+ require './performance/models'
11
+ require './performance/decorators'
12
+
13
+ Benchmark.bm do |bm|
14
+ puts "\n[ Exclusivelly using #method_missing for model delegation ]"
15
+ [1_000, 10_000, 100_000].each do |i|
16
+ puts "\n[ #{i} ]"
17
+ bm.report('#new ') do
18
+ i.times do
19
+ ProductDecorator.decorate(Product.new)
20
+ end
21
+ end
22
+
23
+ bm.report('#hello_world ') do
24
+ i.times do
25
+ ProductDecorator.decorate(Product.new).hello_world
26
+ end
27
+ end
28
+
29
+ bm.report('#sample_class_method ') do
30
+ i.times do
31
+ ProductDecorator.decorate(Product.new).class.sample_class_method
32
+ end
33
+ end
34
+ end
35
+
36
+ puts "\n[ Defining methods on method_missing first hit ]"
37
+ [1_000, 10_000, 100_000].each do |i|
38
+ puts "\n[ #{i} ]"
39
+ bm.report('#new ') do
40
+ i.times do
41
+ FastProductDecorator.decorate(FastProduct.new)
42
+ end
43
+ end
44
+
45
+ bm.report('#hello_world ') do
46
+ i.times do
47
+ FastProductDecorator.decorate(FastProduct.new).hello_world
48
+ end
49
+ end
50
+
51
+ bm.report('#sample_class_method ') do
52
+ i.times do
53
+ FastProductDecorator.decorate(FastProduct.new).class.sample_class_method
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,41 @@
1
+ require './performance/models'
2
+ class ProductDecorator < Drape::Decorator
3
+ def awesome_title
4
+ 'Awesome Title'
5
+ end
6
+
7
+ # Original #method_missing
8
+ def method_missing(method, *args, &block)
9
+ if allow?(method)
10
+ begin
11
+ model.send(method, *args, &block)
12
+ rescue NoMethodError
13
+ super
14
+ end
15
+ else
16
+ super
17
+ end
18
+ end
19
+ end
20
+
21
+ class FastProductDecorator < Drape::Decorator
22
+ def awesome_title
23
+ 'Awesome Title'
24
+ end
25
+
26
+ # Modified #method_missing
27
+ def method_missing(method, *args, &block)
28
+ if allow?(method)
29
+ begin
30
+ self.class.send :define_method, method do |*inner_args, &inner_block|
31
+ model.send(method, *inner_args, &inner_block)
32
+ end
33
+ send(method, *args, &block)
34
+ rescue NoMethodError
35
+ super
36
+ end
37
+ else
38
+ super
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ require './performance/active_record'
2
+ class Product < ActiveRecord::Base
3
+ def self.sample_class_method
4
+ 'sample class method'
5
+ end
6
+
7
+ def hello_world
8
+ 'Hello, World'
9
+ end
10
+ end
11
+
12
+ class FastProduct < ActiveRecord::Base
13
+ def self.sample_class_method
14
+ 'sample class method'
15
+ end
16
+
17
+ def hello_world
18
+ 'Hello, World'
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ require 'bundler/setup'
2
+ require 'drape'
3
+ require 'rails/version'
4
+ require 'action_controller'
5
+ require 'action_controller/test_case'
6
+
7
+ RSpec.configure do |config|
8
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
9
+ config.order = :random
10
+ config.mock_with :rspec do |mocks|
11
+ mocks.yield_receiver_to_any_instance_implementation_blocks = true
12
+ end
13
+ end
14
+
15
+ class Model; include Drape::Decoratable; end
16
+
17
+ class Product < Model; end
18
+ class SpecialProduct < Product; end
19
+ class Other < Model; end
20
+ class ProductDecorator < Drape::Decorator; end
21
+ class ProductsDecorator < Drape::CollectionDecorator; end
22
+
23
+ class ProductPresenter < Drape::Decorator; end
24
+
25
+ class OtherDecorator < Drape::Decorator; end
26
+
27
+ module Namespaced
28
+ class Product < Model; end
29
+ class ProductDecorator < Drape::Decorator; end
30
+
31
+ class OtherDecorator < Drape::Decorator; end
32
+ end
33
+
34
+ # After each example, revert changes made to the class
35
+ def protect_class(klass)
36
+ before { stub_const klass.name, Class.new(klass) }
37
+ end
38
+
39
+ def protect_module(mod)
40
+ before { stub_const mod.name, mod.dup }
41
+ end
@@ -0,0 +1,88 @@
1
+ require 'socket'
2
+ require 'net/http'
3
+
4
+ # Adapted from code by Jon Leighton
5
+ # https://github.com/jonleighton/focused_controller/blob/ec7ccf1/test/acceptance/app_test.rb
6
+
7
+ class DummyApp
8
+ def initialize(environment)
9
+ unless ['development', 'production'].include?(environment.to_s)
10
+ raise ArgumentError, 'Environment must be development or production'
11
+ end
12
+
13
+ @environment = environment
14
+ end
15
+
16
+ attr_reader :environment
17
+
18
+ def url
19
+ "http://#{localhost}:#{port}"
20
+ end
21
+
22
+ def get(path)
23
+ Net::HTTP.get(URI(url + path))
24
+ end
25
+
26
+ def within_app(&block)
27
+ Dir.chdir(root, &block)
28
+ end
29
+
30
+ def start_server
31
+ within_app do
32
+ IO.popen("bundle exec rails s -e #{@environment} -p #{port} 2>&1") do |out|
33
+ start = Time.now
34
+ started = false
35
+ output = ''
36
+ timeout = 60.0
37
+
38
+ while !started && !out.eof? && Time.now - start <= timeout
39
+ output << read_output(out)
40
+ sleep 0.1
41
+
42
+ begin
43
+ TCPSocket.new(localhost, port)
44
+ rescue Errno::ECONNREFUSED
45
+ next
46
+ end
47
+
48
+ started = true
49
+ end
50
+
51
+ raise "Server failed to start:\n#{output}" unless started
52
+
53
+ yield
54
+
55
+ Process.kill('KILL', out.pid)
56
+ File.delete('tmp/pids/server.pid')
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def root
64
+ File.expand_path('../../dummy', __FILE__)
65
+ end
66
+
67
+ def localhost
68
+ '127.0.0.1'
69
+ end
70
+
71
+ def port
72
+ @port ||= begin
73
+ server = TCPServer.new(localhost, 0)
74
+ server.addr[1]
75
+ ensure
76
+ server.close if server
77
+ end
78
+ end
79
+
80
+ def read_output(stream)
81
+ read = IO.select([stream], [], [stream], 0.1)
82
+ output = ''
83
+ loop { output << stream.read_nonblock(1024) } if read
84
+ output
85
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, EOFError
86
+ output
87
+ end
88
+ end