rails_best_practices 1.15.1 → 1.15.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aad6be6297629a1706250552dd2dc67a88d088f4
4
- data.tar.gz: 7416b40f8860088f0ef6734f44fb7dc68531a226
3
+ metadata.gz: 16424767a639f93e65221ccb0a759de20b7ce9fa
4
+ data.tar.gz: ce5f1080da4406d14d893246af12360ada46308f
5
5
  SHA512:
6
- metadata.gz: d3ccfe6ee0f2164b49c2d00db11505d858b0750c9167d39e7e9e3da251d3d7e4a122e7601dc158efc462bcc5a422c94c65e6e02ccce95fa68ac2a787fd30eaad
7
- data.tar.gz: 1be5179a45ca10b0b5ebb3436bf56af16fcca01a35ff93d8846365eb8390bda417750945ea2c21eec659b68cbde1cfd17e67dbdbecbddb1ad2f2d4c5a337d93d
6
+ metadata.gz: 998a80e8e4399e80a8cb555ac596a2758c8beea6bd2f7e8fe13017b4a8931baa40efd2f892a899733dd94803418bdadde63069e21cd351e5dee9db49a2ce8adc
7
+ data.tar.gz: fb113c8116c5b0e575d2b6fed6e500b83bad9d96fbace45bdbfbb1eca6f5ebf77648ba1af5e16a09327e7a6eb1dc90e9a29e4b1268e9b4cfd2c8b57fe03caaaf
@@ -347,13 +347,7 @@ module RailsBestPractices
347
347
  # check if the method is in the except methods list.
348
348
  def excepted?(method)
349
349
  is_ignored?(method.file) ||
350
- except_methods.any? do |except_method|
351
- class_name, method_name = except_method.split('#')
352
- (class_name == '*' && method_name == method.method_name) ||
353
- (method_name == '*' && class_name == method.class_name) ||
354
- (method_name == '*' && class_name == Prepares.klasses.find { |klass| klass.class_name == method.class_name }.try(:extend_class_name)) ||
355
- (class_name == method.class_name && method_name == method.method_name)
356
- end
350
+ except_methods.any? { |except_method| Exceptable.matches method, except_method }
357
351
  end
358
352
 
359
353
  def internal_except_methods
@@ -361,6 +355,29 @@ module RailsBestPractices
361
355
  end
362
356
  end
363
357
  end
358
+
359
+ def self.matches method, except_method
360
+ class_name, method_name = except_method.split('#')
361
+
362
+ method_name = ".*" if method_name == "*"
363
+ method_expression = Regexp.new method_name
364
+ matched = method.method_name =~ method_expression
365
+
366
+ if matched
367
+ class_name = ".*" if class_name == "*"
368
+ class_expression = Regexp.new class_name
369
+
370
+ class_names = Prepares.klasses
371
+ .select { |klass| klass.class_name == method.class_name }
372
+ .map(&:extend_class_name)
373
+ .compact
374
+
375
+ class_names.unshift method.class_name
376
+ matched = class_names.any? { |name| name =~ class_expression }
377
+ end
378
+
379
+ !!matched
380
+ end
364
381
  end
365
382
 
366
383
  # Helper to parse the access control.
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ module RailsBestPractices
3
+ module Core
4
+ class ChecksLoader
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ # load all lexical checks.
10
+ def load_lexicals
11
+ load_checks_from_config { |check_name| RailsBestPractices::Lexicals.const_get(check_name) }
12
+ end
13
+
14
+ # load all reviews according to configuration.
15
+ def load_reviews
16
+ load_checks_from_config { |check_name| RailsBestPractices::Reviews.const_get(check_name.gsub(/Check$/, 'Review')) }
17
+ end
18
+
19
+ private
20
+ # read the checks from yaml config.
21
+ def checks_from_config
22
+ @checks ||= YAML.load_file @config
23
+ end
24
+
25
+ # load all checks from the configuration
26
+ def load_checks_from_config(&block)
27
+ checks_from_config.inject([]) do |active_checks, check|
28
+ check_instance = instantiate_check(block, *check)
29
+ active_checks << check_instance unless check_instance.nil?
30
+ active_checks
31
+ end
32
+ end
33
+
34
+ # instantiates a check
35
+ def instantiate_check(block, check_name, options)
36
+ check_class = load_check_class(check_name, &block)
37
+ check_class.new(options || {}) unless check_class.nil?
38
+ end
39
+
40
+ # loads the class for a check by calling the given block
41
+ def load_check_class(check_name, &block)
42
+ block.call(check_name)
43
+ rescue NameError
44
+ # nothing to do, the check does not exist
45
+ end
46
+ end
47
+ end
48
+ end
@@ -43,9 +43,11 @@ module RailsBestPractices
43
43
  lexicals = Array(options[:lexicals])
44
44
  prepares = Array(options[:prepares])
45
45
  reviews = Array(options[:reviews])
46
- @lexicals = lexicals.empty? ? load_lexicals : lexicals
46
+
47
+ checks_loader = ChecksLoader.new(@config)
48
+ @lexicals = lexicals.empty? ? checks_loader.load_lexicals : lexicals
47
49
  @prepares = prepares.empty? ? load_prepares : prepares
48
- @reviews = reviews.empty? ? load_reviews : reviews
50
+ @reviews = reviews.empty? ? checks_loader.load_reviews : reviews
49
51
  load_plugin_reviews if reviews.empty?
50
52
 
51
53
  @lexical_checker ||= CodeAnalyzer::CheckingVisitor::Plain.new(checkers: @lexicals)
@@ -66,7 +68,7 @@ module RailsBestPractices
66
68
  @lexical_checker.after_check
67
69
  end
68
70
 
69
- # parepare the file.
71
+ # prepare the file.
70
72
  #
71
73
  # @param [String] filename of the file
72
74
  # @param [String] content of the file
@@ -101,7 +103,7 @@ module RailsBestPractices
101
103
  end
102
104
 
103
105
  private
104
- # parse html tempalte code, erb, haml and slim.
106
+ # parse html template code, erb, haml and slim.
105
107
  #
106
108
  # @param [String] filename is the filename of the erb, haml or slim code.
107
109
  # @param [String] content is the source code of erb, haml or slim file.
@@ -132,41 +134,11 @@ module RailsBestPractices
132
134
  content
133
135
  end
134
136
 
135
- # load all lexical checks.
136
- def load_lexicals
137
- checks_from_config.inject([]) { |active_checks, check|
138
- begin
139
- check_name, options = *check
140
- klass = RailsBestPractices::Lexicals.const_get(check_name)
141
- options = Hash(options)
142
- active_checks << (options.empty? ? klass.new : klass.new(options))
143
- rescue
144
- # the check does not exist in the Lexicals namepace.
145
- end
146
- active_checks
147
- }
148
- end
149
-
150
137
  # load all prepares.
151
138
  def load_prepares
152
139
  Prepares.constants.map { |prepare| Prepares.const_get(prepare).new }
153
140
  end
154
141
 
155
- # load all reviews according to configuration.
156
- def load_reviews
157
- checks_from_config.inject([]) { |active_checks, check|
158
- begin
159
- check_name, options = *check
160
- klass = RailsBestPractices::Reviews.const_get(check_name.gsub(/Check$/, 'Review'))
161
- options = Hash(options)
162
- active_checks << (options.empty? ? klass.new : klass.new(options))
163
- rescue
164
- # the check does not exist in the Reviews namepace.
165
- end
166
- active_checks
167
- }
168
- end
169
-
170
142
  # load all plugin reviews.
171
143
  def load_plugin_reviews
172
144
  begin
@@ -183,19 +155,6 @@ module RailsBestPractices
183
155
  end
184
156
  end
185
157
  end
186
-
187
- # read the checks from yaml config.
188
- def checks_from_config
189
- @checks ||= YAML.load_file @config
190
- end
191
-
192
- # read the file content.
193
- #
194
- # @param [String] filename
195
- # @return [String] file conent
196
- def read_file(filename)
197
- File.open(filename, "r:UTF-8") { |f| f.read }
198
- end
199
158
  end
200
159
  end
201
160
  end
@@ -105,7 +105,7 @@ module RailsBestPractices
105
105
  end
106
106
 
107
107
  def internal_except_methods
108
- %w(rescue_action).map { |method_name| "*\##{method_name}" } +
108
+ %w(rescue_action default_url_options).map { |method_name| "*\##{method_name}" } +
109
109
  %w(Devise::OmniauthCallbacksController).map { |controller_name| "#{controller_name}#*" }
110
110
  end
111
111
 
@@ -29,6 +29,9 @@ module RailsBestPractices
29
29
  # check if the generated routes have the corresponding actions in controller for rails routes.
30
30
  add_callback :start_command, :start_command_call do |node|
31
31
  if "resources" == node.message.to_s
32
+ if (mod = module_option(node))
33
+ @namespaces << mod
34
+ end
32
35
  check_resources(node)
33
36
  @resource_controllers << node.arguments.all.first.to_s
34
37
  elsif "resource" == node.message.to_s
@@ -40,6 +43,7 @@ module RailsBestPractices
40
43
  add_callback :end_command do |node|
41
44
  if "resources" == node.message.to_s
42
45
  @resource_controllers.pop
46
+ @namespaces.pop if module_option(node)
43
47
  elsif "resource" == node.message.to_s
44
48
  @resource_controllers.pop
45
49
  end
@@ -52,6 +56,10 @@ module RailsBestPractices
52
56
  @namespaces << node.arguments.all.first.to_s if check_method_add_block?(node)
53
57
  when "resources", "resource"
54
58
  @resource_controllers << node.arguments.all.first.to_s if check_method_add_block?(node)
59
+ when 'scope'
60
+ if check_method_add_block?(node) && (mod = module_option(node))
61
+ @namespaces << mod
62
+ end
55
63
  else
56
64
  end
57
65
  end
@@ -64,6 +72,10 @@ module RailsBestPractices
64
72
  @namespaces.pop
65
73
  when "resources", "resource"
66
74
  @resource_controllers.pop
75
+ when 'scope'
76
+ if check_method_add_block?(node) && module_option(node)
77
+ @namespaces.pop
78
+ end
67
79
  end
68
80
  end
69
81
  end
@@ -143,6 +155,13 @@ module RailsBestPractices
143
155
  end
144
156
  end
145
157
 
158
+ def module_option(node)
159
+ option_node = node.arguments[1].last
160
+ if option_node && option_node.sexp_type == :bare_assoc_hash && hash_key_exist?(option_node, 'module')
161
+ option_node.hash_value('module').to_s
162
+ end
163
+ end
164
+
146
165
  def option_with_hash(node)
147
166
  node.arguments.all.size > 1 && :bare_assoc_hash == node.arguments.all[1].sexp_type
148
167
  end
@@ -22,7 +22,7 @@ module RailsBestPractices
22
22
  interesting_files MODEL_FILES
23
23
  url "http://rails-bestpractices.com/posts/19-use-observer"
24
24
 
25
- def initialize
25
+ def initialize(options = {})
26
26
  super
27
27
  @callbacks = []
28
28
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module RailsBestPractices
3
- VERSION = "1.15.1"
3
+ VERSION = "1.15.2"
4
4
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module RailsBestPractices::Core
4
+ describe ChecksLoader do
5
+ let(:checks_loader) { ChecksLoader.new(RailsBestPractices::Analyzer::DEFAULT_CONFIG) }
6
+
7
+ describe "load_lexicals" do
8
+ it "should load lexical checks from the default configuration" do
9
+ lexicals = checks_loader.load_lexicals
10
+ expect(lexicals.map(&:class)).to include(RailsBestPractices::Lexicals::RemoveTrailingWhitespaceCheck)
11
+ end
12
+ end
13
+
14
+ describe "load_reviews" do
15
+ it "should load the reviews from the default the configuration" do
16
+ reviews = checks_loader.load_reviews
17
+ expect(reviews.map(&:class)).to include(RailsBestPractices::Reviews::AlwaysAddDbIndexReview)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ module RailsBestPractices::Core
4
+ describe Check::Exceptable do
5
+ let(:method) { Method.new "BlogPost", "approve", "public", {} }
6
+
7
+ context "wildcard class and method" do
8
+ let(:except_method) { '*#*' }
9
+
10
+ it "matches" do
11
+ expect(Check::Exceptable.matches(method, except_method)).to eql true
12
+ end
13
+ end
14
+
15
+ context "wildcard class and matching explicit method" do
16
+ let(:except_method) { '*#approve' }
17
+
18
+ it "matches" do
19
+ expect(Check::Exceptable.matches(method, except_method)).to eql true
20
+ end
21
+ end
22
+
23
+ context "wildcard class and non-matching explicit method" do
24
+ let(:except_method) { '*#disapprove' }
25
+
26
+ it "matches" do
27
+ expect(Check::Exceptable.matches(method, except_method)).to eql false
28
+ end
29
+ end
30
+
31
+ context "matching class and wildcard method" do
32
+ let(:except_method) { 'BlogPost#*' }
33
+
34
+ it "matches" do
35
+ expect(Check::Exceptable.matches(method, except_method)).to eql true
36
+ end
37
+ end
38
+
39
+ context "non-matching class and wildcard method" do
40
+ let(:except_method) { 'User#*' }
41
+
42
+ it "matches" do
43
+ expect(Check::Exceptable.matches(method, except_method)).to eql false
44
+ end
45
+ end
46
+
47
+ context "matching class and matching method" do
48
+ let(:except_method) { 'BlogPost#approve' }
49
+
50
+ it "matches" do
51
+ expect(Check::Exceptable.matches(method, except_method)).to eql true
52
+ end
53
+ end
54
+
55
+ context "non-matching class and non-matching method" do
56
+ let(:except_method) { 'User#disapprove' }
57
+
58
+ it "matches" do
59
+ expect(Check::Exceptable.matches(method, except_method)).to eql false
60
+ end
61
+ end
62
+ end
63
+ end
@@ -186,7 +186,7 @@ module RailsBestPractices
186
186
  end
187
187
 
188
188
  describe "namespace" do
189
- it "should restrict auto-generated routes" do
189
+ before do
190
190
  content =<<-EOF
191
191
  class Admin::CommentsController < ApplicationController
192
192
  def show; end
@@ -198,7 +198,9 @@ module RailsBestPractices
198
198
  end
199
199
  EOF
200
200
  runner.prepare('app/controllers/admin/comments_controller.rb', content)
201
+ end
201
202
 
203
+ it "should restrict auto-generated routes" do
202
204
  content =<<-EOF
203
205
  RailsBestPracticesCom::Application.routes.draw do
204
206
  namespace :admin do
@@ -210,6 +212,30 @@ module RailsBestPractices
210
212
  expect(runner.errors.size).to eq(1)
211
213
  expect(runner.errors[0].to_s).to eq("config/routes.rb:3 - restrict auto-generated routes admin/comments (except: [:index])")
212
214
  end
215
+
216
+ it "should restrict auto-generated routes with scope :module" do
217
+ content =<<-EOF
218
+ RailsBestPracticesCom::Application.routes.draw do
219
+ scope module: :admin do
220
+ resources :comments
221
+ end
222
+ end
223
+ EOF
224
+ runner.review('config/routes.rb', content)
225
+ expect(runner.errors.size).to eq(1)
226
+ expect(runner.errors[0].to_s).to eq("config/routes.rb:3 - restrict auto-generated routes admin/comments (except: [:index])")
227
+ end
228
+
229
+ it "should restrict auto-generated routes with resources :module" do
230
+ content =<<-EOF
231
+ RailsBestPracticesCom::Application.routes.draw do
232
+ resources :comments, module: :admin
233
+ end
234
+ EOF
235
+ runner.review('config/routes.rb', content)
236
+ expect(runner.errors.size).to eq(1)
237
+ expect(runner.errors[0].to_s).to eq("config/routes.rb:2 - restrict auto-generated routes admin/comments (except: [:index])")
238
+ end
213
239
  end
214
240
 
215
241
  describe "nested routes" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_best_practices
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.15.1
4
+ version: 1.15.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-05 00:00:00.000000000 Z
11
+ date: 2014-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -200,7 +200,6 @@ executables:
200
200
  extensions: []
201
201
  extra_rdoc_files: []
202
202
  files:
203
- - ".gemtest"
204
203
  - ".gitignore"
205
204
  - ".rspec"
206
205
  - ".ruby-version"
@@ -218,6 +217,7 @@ files:
218
217
  - lib/rails_best_practices/command.rb
219
218
  - lib/rails_best_practices/core.rb
220
219
  - lib/rails_best_practices/core/check.rb
220
+ - lib/rails_best_practices/core/checks_loader.rb
221
221
  - lib/rails_best_practices/core/configs.rb
222
222
  - lib/rails_best_practices/core/controllers.rb
223
223
  - lib/rails_best_practices/core/error.rb
@@ -294,9 +294,11 @@ files:
294
294
  - spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb
295
295
  - spec/rails_best_practices/analyzer_spec.rb
296
296
  - spec/rails_best_practices/core/check_spec.rb
297
+ - spec/rails_best_practices/core/checks_loader_spec.rb
297
298
  - spec/rails_best_practices/core/configs_spec.rb
298
299
  - spec/rails_best_practices/core/controllers_spec.rb
299
300
  - spec/rails_best_practices/core/error_spec.rb
301
+ - spec/rails_best_practices/core/except_methods_spec.rb
300
302
  - spec/rails_best_practices/core/gems_spec.rb
301
303
  - spec/rails_best_practices/core/helpers_spec.rb
302
304
  - spec/rails_best_practices/core/klasses_spec.rb
@@ -406,9 +408,11 @@ test_files:
406
408
  - spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb
407
409
  - spec/rails_best_practices/analyzer_spec.rb
408
410
  - spec/rails_best_practices/core/check_spec.rb
411
+ - spec/rails_best_practices/core/checks_loader_spec.rb
409
412
  - spec/rails_best_practices/core/configs_spec.rb
410
413
  - spec/rails_best_practices/core/controllers_spec.rb
411
414
  - spec/rails_best_practices/core/error_spec.rb
415
+ - spec/rails_best_practices/core/except_methods_spec.rb
412
416
  - spec/rails_best_practices/core/gems_spec.rb
413
417
  - spec/rails_best_practices/core/helpers_spec.rb
414
418
  - spec/rails_best_practices/core/klasses_spec.rb
data/.gemtest DELETED
File without changes