draper 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +16 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +24 -0
  4. data/.gitignore +3 -1
  5. data/.rubocop.yml +11 -0
  6. data/.travis.yml +3 -7
  7. data/CHANGELOG.md +26 -0
  8. data/Gemfile +4 -5
  9. data/Guardfile +5 -5
  10. data/README.md +61 -11
  11. data/Rakefile +1 -1
  12. data/draper.gemspec +12 -10
  13. data/lib/draper.rb +8 -3
  14. data/lib/draper/automatic_delegation.rb +5 -3
  15. data/lib/draper/collection_decorator.rb +1 -11
  16. data/lib/draper/compatibility/api_only.rb +23 -0
  17. data/lib/draper/configuration.rb +15 -0
  18. data/lib/draper/decoratable.rb +3 -4
  19. data/lib/draper/decorator.rb +4 -24
  20. data/lib/draper/finders.rb +0 -0
  21. data/lib/draper/helper_proxy.rb +1 -8
  22. data/lib/draper/railtie.rb +12 -21
  23. data/lib/draper/tasks/test.rake +2 -15
  24. data/lib/draper/test/devise_helper.rb +1 -8
  25. data/lib/draper/test/minitest_integration.rb +0 -0
  26. data/lib/draper/test/rspec_integration.rb +1 -5
  27. data/lib/draper/test_case.rb +4 -8
  28. data/lib/draper/undecorate.rb +8 -0
  29. data/lib/draper/version.rb +1 -1
  30. data/lib/draper/view_context.rb +3 -19
  31. data/lib/draper/view_context/build_strategy.rb +11 -2
  32. data/lib/generators/controller_override.rb +2 -2
  33. data/lib/generators/draper/install_generator.rb +14 -0
  34. data/lib/generators/draper/templates/application_decorator.rb +8 -0
  35. data/lib/generators/mini_test/decorator_generator.rb +1 -1
  36. data/lib/generators/rails/decorator_generator.rb +1 -8
  37. data/lib/generators/rspec/templates/decorator_spec.rb +2 -2
  38. data/spec/draper/collection_decorator_spec.rb +11 -26
  39. data/spec/draper/configuration_spec.rb +25 -0
  40. data/spec/draper/decoratable_spec.rb +29 -16
  41. data/spec/draper/decorated_association_spec.rb +9 -9
  42. data/spec/draper/decorates_assigned_spec.rb +6 -6
  43. data/spec/draper/decorator_spec.rb +112 -89
  44. data/spec/draper/draper_spec.rb +24 -0
  45. data/spec/draper/factory_spec.rb +26 -26
  46. data/spec/draper/finders_spec.rb +21 -21
  47. data/spec/draper/helper_proxy_spec.rb +3 -3
  48. data/spec/draper/lazy_helpers_spec.rb +2 -2
  49. data/spec/draper/undecorate_chain_spec.rb +20 -0
  50. data/spec/draper/view_context/build_strategy_spec.rb +26 -10
  51. data/spec/draper/view_context_spec.rb +49 -21
  52. data/spec/dummy/app/controllers/base_controller.rb +4 -0
  53. data/spec/dummy/app/controllers/posts_controller.rb +2 -2
  54. data/spec/dummy/app/decorators/post_decorator.rb +0 -0
  55. data/spec/dummy/app/views/posts/_post.html.erb +8 -6
  56. data/spec/dummy/config/boot.rb +1 -1
  57. data/spec/dummy/config/initializers/draper.rb +3 -0
  58. data/spec/dummy/config/mongoid.yml +104 -41
  59. data/spec/dummy/db/schema.rb +4 -4
  60. data/spec/dummy/fast_spec/post_decorator_spec.rb +1 -1
  61. data/spec/dummy/lib/tasks/test.rake +1 -1
  62. data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +4 -8
  63. data/spec/dummy/spec/decorators/devise_spec.rb +0 -9
  64. data/spec/dummy/spec/decorators/post_decorator_spec.rb +2 -4
  65. data/spec/dummy/spec/mailers/post_mailer_spec.rb +0 -8
  66. data/spec/dummy/spec/shared_examples/decoratable.rb +0 -2
  67. data/spec/dummy/test/decorators/minitest/devise_test.rb +0 -9
  68. data/spec/dummy/test/decorators/minitest/view_context_test.rb +3 -3
  69. data/spec/dummy/test/decorators/test_unit/devise_test.rb +0 -9
  70. data/spec/dummy/test/decorators/test_unit/view_context_test.rb +1 -1
  71. data/spec/generators/controller/controller_generator_spec.rb +3 -3
  72. data/spec/generators/decorator/decorator_generator_spec.rb +14 -12
  73. data/spec/generators/install/install_generator_spec.rb +19 -0
  74. data/spec/integration/integration_spec.rb +11 -8
  75. data/spec/performance/benchmark.rb +1 -1
  76. data/spec/spec_helper.rb +4 -4
  77. data/spec/support/matchers/have_text.rb +2 -2
  78. data/spec/support/shared_examples/view_helpers.rb +8 -8
  79. metadata +71 -29
  80. data/gemfiles/4.0.gemfile +0 -3
  81. data/gemfiles/4.1.gemfile +0 -3
  82. data/gemfiles/4.2.gemfile +0 -3
  83. data/spec/dummy/app/controllers/application_controller.rb +0 -4
@@ -7,7 +7,7 @@ module Draper
7
7
  let(:controller) { Class.new(base) { include ViewContext } }
8
8
 
9
9
  it "saves the superclass's view context" do
10
- ViewContext.should_receive(:current=).with(:controller_view_context)
10
+ expect(ViewContext).to receive(:current=).with(:controller_view_context)
11
11
  controller.new.view_context
12
12
  end
13
13
 
@@ -18,7 +18,7 @@ module Draper
18
18
 
19
19
  describe ".controller" do
20
20
  it "returns the stored controller from RequestStore" do
21
- RequestStore.stub store: {current_controller: :stored_controller}
21
+ allow(RequestStore).to receive_messages store: {current_controller: :stored_controller}
22
22
 
23
23
  expect(ViewContext.controller).to be :stored_controller
24
24
  end
@@ -27,34 +27,62 @@ module Draper
27
27
  describe ".controller=" do
28
28
  it "stores a controller in RequestStore" do
29
29
  store = {}
30
- RequestStore.stub store: store
30
+ allow(RequestStore).to receive_messages store: store
31
31
 
32
32
  ViewContext.controller = :stored_controller
33
33
  expect(store[:current_controller]).to be :stored_controller
34
34
  end
35
+
36
+ it "cleans context when controller changes" do
37
+ store = {
38
+ current_controller: :stored_controller,
39
+ current_view_context: :stored_view_context
40
+ }
41
+
42
+ allow(RequestStore).to receive_messages store: store
43
+
44
+ ViewContext.controller = :other_stored_controller
45
+
46
+ expect(store).to include(current_controller: :other_stored_controller)
47
+ expect(store).not_to include(:current_view_context)
48
+ end
49
+
50
+ it "doesn't clean context when controller is the same" do
51
+ store = {
52
+ current_controller: :stored_controller,
53
+ current_view_context: :stored_view_context
54
+ }
55
+
56
+ allow(RequestStore).to receive_messages store: store
57
+
58
+ ViewContext.controller = :stored_controller
59
+
60
+ expect(store).to include(current_controller: :stored_controller)
61
+ expect(store).to include(current_view_context: :stored_view_context)
62
+ end
35
63
  end
36
64
 
37
65
  describe ".current" do
38
66
  it "returns the stored view context from RequestStore" do
39
- RequestStore.stub store: {current_view_context: :stored_view_context}
67
+ allow(RequestStore).to receive_messages store: {current_view_context: :stored_view_context}
40
68
 
41
69
  expect(ViewContext.current).to be :stored_view_context
42
70
  end
43
71
 
44
72
  context "when no view context is stored" do
45
73
  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)
74
+ allow(RequestStore).to receive_messages store: {}
75
+ allow(ViewContext).to receive_messages build_strategy: ->{ :new_view_context }
76
+ allow(HelperProxy).to receive(:new).with(:new_view_context).and_return(:new_helper_proxy)
49
77
 
50
78
  expect(ViewContext.current).to be :new_helper_proxy
51
79
  end
52
80
 
53
81
  it "stores the built view context" do
54
82
  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)
83
+ allow(RequestStore).to receive_messages store: store
84
+ allow(ViewContext).to receive_messages build_strategy: ->{ :new_view_context }
85
+ allow(HelperProxy).to receive(:new).with(:new_view_context).and_return(:new_helper_proxy)
58
86
 
59
87
  ViewContext.current
60
88
  expect(store[:current_view_context]).to be :new_helper_proxy
@@ -65,8 +93,8 @@ module Draper
65
93
  describe ".current=" do
66
94
  it "stores a helper proxy for the view context in RequestStore" do
67
95
  store = {}
68
- RequestStore.stub store: store
69
- HelperProxy.stub(:new).with(:stored_view_context).and_return(:stored_helper_proxy)
96
+ allow(RequestStore).to receive_messages store: store
97
+ allow(HelperProxy).to receive(:new).with(:stored_view_context).and_return(:stored_helper_proxy)
70
98
 
71
99
  ViewContext.current = :stored_view_context
72
100
  expect(store[:current_view_context]).to be :stored_helper_proxy
@@ -76,7 +104,7 @@ module Draper
76
104
  describe ".clear!" do
77
105
  it "clears the stored controller and view controller" do
78
106
  store = {current_controller: :stored_controller, current_view_context: :stored_view_context}
79
- RequestStore.stub store: store
107
+ allow(RequestStore).to receive_messages store: store
80
108
 
81
109
  ViewContext.clear!
82
110
  expect(store).not_to have_key :current_controller
@@ -86,7 +114,7 @@ module Draper
86
114
 
87
115
  describe ".build" do
88
116
  it "returns a new view context using the build strategy" do
89
- ViewContext.stub build_strategy: ->{ :new_view_context }
117
+ allow(ViewContext).to receive_messages build_strategy: ->{ :new_view_context }
90
118
 
91
119
  expect(ViewContext.build).to be :new_view_context
92
120
  end
@@ -94,17 +122,17 @@ module Draper
94
122
 
95
123
  describe ".build!" do
96
124
  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)
125
+ allow(ViewContext).to receive_messages build_strategy: ->{ :new_view_context }
126
+ allow(HelperProxy).to receive(:new).with(:new_view_context).and_return(:new_helper_proxy)
99
127
 
100
128
  expect(ViewContext.build!).to be :new_helper_proxy
101
129
  end
102
130
 
103
131
  it "stores the helper proxy" do
104
132
  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)
133
+ allow(RequestStore).to receive_messages store: store
134
+ allow(ViewContext).to receive_messages build_strategy: ->{ :new_view_context }
135
+ allow(HelperProxy).to receive(:new).with(:new_view_context).and_return(:new_helper_proxy)
108
136
 
109
137
  ViewContext.build!
110
138
  expect(store[:current_view_context]).to be :new_helper_proxy
@@ -131,7 +159,7 @@ module Draper
131
159
  end
132
160
 
133
161
  it "passes a block to the strategy" do
134
- ViewContext::BuildStrategy::Fast.stub(:new) { |&block| block.call }
162
+ allow(ViewContext::BuildStrategy::Fast).to receive(:new) { |&block| block.call }
135
163
 
136
164
  expect(ViewContext.test_strategy(:fast){:passed}).to be :passed
137
165
  end
@@ -144,7 +172,7 @@ module Draper
144
172
  end
145
173
 
146
174
  it "passes a block to the strategy" do
147
- ViewContext::BuildStrategy::Full.stub(:new) { |&block| block.call }
175
+ allow(ViewContext::BuildStrategy::Full).to receive(:new) { |&block| block.call }
148
176
 
149
177
  expect(ViewContext.test_strategy(:full){:passed}).to be :passed
150
178
  end
@@ -0,0 +1,4 @@
1
+ class BaseController < ActionController::Base
2
+ include LocalizedUrls
3
+ protect_from_forgery
4
+ end
@@ -1,4 +1,4 @@
1
- class PostsController < ApplicationController
1
+ class PostsController < BaseController
2
2
  decorates_assigned :post
3
3
 
4
4
  def show
@@ -8,7 +8,7 @@ class PostsController < ApplicationController
8
8
  def mail
9
9
  post = Post.find(params[:id])
10
10
  email = PostMailer.decorated_email(post).deliver
11
- render text: email.body
11
+ render html: email.body.to_s.html_safe
12
12
  end
13
13
 
14
14
  private
File without changes
@@ -20,14 +20,16 @@
20
20
  <dt>Helpers from the controller:</dt>
21
21
  <dd id="goodnight_moon"><%= post.goodnight_moon %></dd>
22
22
 
23
- <dt>Path with decorator:</dt>
24
- <dd id="path_with_decorator"><%= post_path(post) %></dd>
23
+ <% unless defined? mailer %>
24
+ <dt>Path with decorator:</dt>
25
+ <dd id="path_with_decorator"><%= post_url(post) %></dd>
25
26
 
26
- <dt>Path with model:</dt>
27
- <dd id="path_with_model"><%= post.path_with_model %></dd>
27
+ <dt>Path with model:</dt>
28
+ <dd id="path_with_model"><%= post.path_with_model %></dd>
28
29
 
29
- <dt>Path with id:</dt>
30
- <dd id="path_with_id"><%= post.path_with_id %></dd>
30
+ <dt>Path with id:</dt>
31
+ <dd id="path_with_id"><%= post.path_with_id %></dd>
32
+ <% end %>
31
33
 
32
34
  <dt>URL with decorator:</dt>
33
35
  <dd id="url_with_decorator"><%= post_url(post) %></dd>
@@ -2,4 +2,4 @@ require 'rubygems'
2
2
 
3
3
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
4
4
 
5
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
5
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
@@ -0,0 +1,3 @@
1
+ Draper.configure do |config|
2
+ config.default_controller = BaseController
3
+ end
@@ -1,54 +1,117 @@
1
1
  development:
2
- # Configure available database sessions. (required)
3
- sessions:
4
- # Defines the default session. (required)
2
+ # Configure available database clients. (required)
3
+ clients:
4
+ # Defines the default client. (required)
5
5
  default:
6
6
  # Defines the name of the default database that Mongoid can connect to.
7
7
  # (required).
8
8
  database: dummy_development
9
- # Provides the hosts the default session can connect to. Must be an array
9
+ # Provides the hosts the default client can connect to. Must be an array
10
10
  # of host:port pairs. (required)
11
11
  hosts:
12
12
  - localhost:27017
13
13
  options:
14
- # Change whether the session persists in safe mode by default.
15
- # (default: false)
16
- # safe: false
17
-
18
- # Change the default consistency model to :eventual or :strong.
19
- # :eventual will send reads to secondaries, :strong sends everything
20
- # to master. (default: :eventual)
21
- # consistency: :eventual
22
-
23
- # How many times Moped should attempt to retry an operation after
24
- # failure. (default: 30)
25
- # max_retries: 30
26
-
27
- # The time in seconds that Moped should wait before retrying an
28
- # operation on failure. (default: 1)
29
- # retry_interval: 1
30
- # Configure Mongoid specific options. (optional)
31
- options:
32
- # Configuration for whether or not to allow access to fields that do
33
- # not have a field definition on the model. (default: true)
34
- # allow_dynamic_fields: true
14
+ # Change the default write concern. (default = { w: 1 })
15
+ # write:
16
+ # w: 1
17
+
18
+ # Change the default read preference. Valid options for mode are: :secondary,
19
+ # :secondary_preferred, :primary, :primary_preferred, :nearest
20
+ # (default: primary)
21
+ # read:
22
+ # mode: :secondary_preferred
23
+ # tag_sets:
24
+ # - use: web
25
+
26
+ # The name of the user for authentication.
27
+ # user: 'user'
28
+
29
+ # The password of the user for authentication.
30
+ # password: 'password'
31
+
32
+ # The user's database roles.
33
+ # roles:
34
+ # - 'dbOwner'
35
+
36
+ # Change the default authentication mechanism. Valid options are: :scram,
37
+ # :mongodb_cr, :mongodb_x509, and :plain. (default on 3.0 is :scram, default
38
+ # on 2.4 and 2.6 is :plain)
39
+ # auth_mech: :scram
40
+
41
+ # The database or source to authenticate the user against. (default: admin)
42
+ # auth_source: admin
43
+
44
+ # Force a the driver cluster to behave in a certain manner instead of auto-
45
+ # discovering. Can be one of: :direct, :replica_set, :sharded. Set to :direct
46
+ # when connecting to hidden members of a replica set.
47
+ # connect: :direct
48
+
49
+ # Changes the default time in seconds the server monitors refresh their status
50
+ # via ismaster commands. (default: 10)
51
+ # heartbeat_frequency: 10
52
+
53
+ # The time in seconds for selecting servers for a near read preference. (default: 5)
54
+ # local_threshold: 5
55
+
56
+ # The timeout in seconds for selecting a server for an operation. (default: 30)
57
+ # server_selection_timeout: 30
58
+
59
+ # The maximum number of connections in the connection pool. (default: 5)
60
+ # max_pool_size: 5
61
+
62
+ # The minimum number of connections in the connection pool. (default: 1)
63
+ # min_pool_size: 1
64
+
65
+ # The time to wait, in seconds, in the connection pool for a connection
66
+ # to be checked in before timing out. (default: 5)
67
+ # wait_queue_timeout: 5
35
68
 
36
- # Enable the identity map, needed for eager loading. (default: false)
37
- # identity_map_enabled: false
69
+ # The time to wait to establish a connection before timing out, in seconds.
70
+ # (default: 5)
71
+ # connect_timeout: 5
38
72
 
73
+ # The timeout to wait to execute operations on a socket before raising an error.
74
+ # (default: 5)
75
+ # socket_timeout: 5
76
+
77
+ # The name of the replica set to connect to. Servers provided as seeds that do
78
+ # not belong to this replica set will be ignored.
79
+ # replica_set: name
80
+
81
+ # Whether to connect to the servers via ssl. (default: false)
82
+ # ssl: true
83
+
84
+ # The certificate file used to identify the connection against MongoDB.
85
+ # ssl_cert: /path/to/my.cert
86
+
87
+ # The private keyfile used to identify the connection against MongoDB.
88
+ # Note that even if the key is stored in the same file as the certificate,
89
+ # both need to be explicitly specified.
90
+ # ssl_key: /path/to/my.key
91
+
92
+ # A passphrase for the private key.
93
+ # ssl_key_pass_phrase: password
94
+
95
+ # Whether or not to do peer certification validation. (default: true)
96
+ # ssl_verify: true
97
+
98
+ # The file containing a set of concatenated certification authority certifications
99
+ # used to validate certs passed from the other end of the connection.
100
+ # ssl_ca_cert: /path/to/ca.cert
101
+
102
+
103
+ # Configure Mongoid specific options. (optional)
104
+ options:
39
105
  # Includes the root model name in json serialization. (default: false)
40
106
  # include_root_in_json: false
41
107
 
42
- # Include the _type field in serializaion. (default: false)
108
+ # Include the _type field in serialization. (default: false)
43
109
  # include_type_for_serialization: false
44
110
 
45
111
  # Preload all models in development, needed when models use
46
112
  # inheritance. (default: false)
47
113
  # preload_models: false
48
114
 
49
- # Protect id and type from mass assignment. (default: true)
50
- # protect_sensitive_fields: true
51
-
52
115
  # Raise an error when performing a #find and the document is not found.
53
116
  # (default: true)
54
117
  # raise_not_found_error: true
@@ -57,23 +120,23 @@ development:
57
120
  # existing method. (default: false)
58
121
  # scope_overwrite_exception: false
59
122
 
60
- # Skip the database version check, used when connecting to a db without
61
- # admin access. (default: false)
62
- # skip_version_check: false
63
-
64
- # User Active Support's time zone in conversions. (default: true)
123
+ # Use Active Support's time zone in conversions. (default: true)
65
124
  # use_activesupport_time_zone: true
66
125
 
67
126
  # Ensure all times are UTC in the app side. (default: false)
68
127
  # use_utc: false
128
+
129
+ # Set the Mongoid and Ruby driver log levels when not in a Rails
130
+ # environment. The Mongoid logger will be set to the Rails logger
131
+ # otherwise.(default: :info)
132
+ # log_level: :info
69
133
  test:
70
- sessions:
134
+ clients:
71
135
  default:
72
136
  database: dummy_test
73
137
  hosts:
74
138
  - localhost:27017
75
139
  options:
76
- # In the test environment we lower the retries and retry interval to
77
- # low amounts for fast failures.
78
- max_retries: 1
79
- retry_interval: 0
140
+ read:
141
+ mode: :primary
142
+ max_pool_size: 1
@@ -11,11 +11,11 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20121019115657) do
14
+ ActiveRecord::Schema.define(version: 20121019115657) do
15
15
 
16
- create_table "posts", :force => true do |t|
17
- t.datetime "created_at", :null => false
18
- t.datetime "updated_at", :null => false
16
+ create_table "posts", force: true do |t|
17
+ t.datetime "created_at", null: false
18
+ t.datetime "updated_at", null: false
19
19
  end
20
20
 
21
21
  end
@@ -32,6 +32,6 @@ describe PostDecorator do
32
32
  end
33
33
 
34
34
  it "can't be passed implicitly to url_for" do
35
- expect{decorator.link}.to raise_error
35
+ expect{decorator.link}.to raise_error ArgumentError
36
36
  end
37
37
  end
@@ -13,4 +13,4 @@ RSpec::Core::RakeTask.new :fast_spec do |t|
13
13
  t.pattern = "fast_spec/**/*_spec.rb"
14
14
  end
15
15
 
16
- task :default => [:test, :spec, :fast_spec]
16
+ task default: [:test, :spec, :fast_spec]
@@ -2,15 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe Draper::CollectionDecorator do
4
4
  describe "#active_model_serializer" do
5
- it "returns ActiveModel::ArraySerializer" do
6
- collection_decorator = Draper::CollectionDecorator.new([])
7
- if defined?(ActiveModel::ArraySerializerSupport)
8
- collection_serializer = collection_decorator.active_model_serializer
9
- else
10
- collection_serializer = ActiveModel::Serializer.serializer_for(collection_decorator)
11
- end
5
+ it "returns ActiveModel::Serializer::CollectionSerializer" do
6
+ collection_decorator = Draper::CollectionDecorator.new([])
7
+ collection_serializer = ActiveModel::Serializer.serializer_for(collection_decorator)
12
8
 
13
- expect(collection_serializer).to be ActiveModel::ArraySerializer
9
+ expect(collection_serializer).to be ActiveModel::Serializer::CollectionSerializer
14
10
  end
15
11
  end
16
12
  end