arca 2.2.0 → 2.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b0591095b4b348fcbd76cf72ef3cea8aeecb8016
4
- data.tar.gz: bd32d70f3788e5238761d3368b6944b923860c54
2
+ SHA256:
3
+ metadata.gz: 326dbd7961f9ccfe0b39d77572d3fcc6599179feaf88a81f3fdfdc64ce0bb8e2
4
+ data.tar.gz: e0298827379b3759f81eaac23fb9d626b8ce20ae4150a4c44b01379157c6263a
5
5
  SHA512:
6
- metadata.gz: 9ea28b0b452751d96980314871b79df23b5ea261e9defbc9e3f331690d1c5ca4f4fee7b8c6c65461298faab770034c1c58e752b89cd9f5aa833b032b784a5c5b
7
- data.tar.gz: 5477fd14ed651d2681b8167db4ef3ee5ea60ae7246f73cb9e9e36c025df1f2747678d1db410b47113d8f78985bde696cf25b2cfee7e4b69bd90e92f35f001250
6
+ metadata.gz: 421d318fdbabf614179e883b5b009d3f7f8a560dbaed1c885ddcc09d14f656f774b162f3d111c576cf0b2fc5f63bfe913e7be09cb043c1c84a8fc18961a9a1c4
7
+ data.tar.gz: 6d9f740fb81d86ef2b2ede9b803ac04e77a3327b2053f48e4cbcbf551217293939cacba68b0c5ef87e47e8c90972eb7afe96ead015364011b7d34a21c0f6dae1
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ActiveRecord Callback Analyzer
2
2
 
3
- Arca is a callback analyzer for ActiveRecord models ideally suited for digging yourself out of callback hell. At best it will help you move towards a [more maintainable design](http://adequate.io/culling-the-activerecord-lifecycle) and at worst it can be used in your test suite to give you feedback when callbacks change.
3
+ Arca is a callback analyzer for ActiveRecord models ideally suited for digging yourself out of callback hell. At best it will help you move towards a [more maintainable design](https://web.archive.org/web/20161016162603/http://adequate.io/culling-the-activerecord-lifecycle) and at worst it can be used in your test suite to give you feedback when callbacks change.
4
4
 
5
5
  Arca helps you answer questions like:
6
6
 
@@ -10,6 +10,8 @@ Arca helps you answer questions like:
10
10
 
11
11
  The Arca library has two main components, the collector and the reporter. Include the collector module in ActiveRecord::Base before your models are loaded.
12
12
 
13
+ At GitHub, we test callbacks by whitelisting existing callbacks, and adding a lint test to ensure new callbacks are not added without review. The [examples](examples) folder is a good starting point.
14
+
13
15
  ## Requirements
14
16
 
15
17
  ![travis-ci build status](https://travis-ci.org/jonmagic/arca.svg)
@@ -34,7 +36,9 @@ class ActiveRecord::Base
34
36
  include Arca::Collector
35
37
  end
36
38
 
37
- # load your app
39
+ # load your app. It's important to setup before loading your models because Arca
40
+ # works by wrapping itself around the callback method definitions (before_save,
41
+ # after_save, etc) and then records how and where those methods are used.
38
42
  ```
39
43
 
40
44
  In this example the `Annoucements` module is included in `Ticket` and defines it's own callback.
@@ -212,6 +216,12 @@ have to update this test to make it pass.
212
216
  ---------------------------------------------
213
217
  ```
214
218
 
219
+ ## Contributors
220
+
221
+ - [@jonmagic](https://github.com/jonmagic)
222
+ - [@jch](https://github.com/jch)
223
+ - [@bensheldon](https://github.com/bensheldon)
224
+
215
225
  ## License
216
226
 
217
227
  The MIT License (MIT)
data/arca.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "arca"
3
- spec.version = "2.2.0"
3
+ spec.version = "2.3.0"
4
4
  spec.date = "2015-08-07"
5
5
  spec.summary = "ActiveRecord callback analyzer"
6
6
  spec.description = "Arca is a callback analyzer for ActiveRecord ideally suited for digging yourself out of callback hell"
@@ -0,0 +1,42 @@
1
+ require "minitest"
2
+
3
+ class ActiveRecordLintTest < Minitest::Test
4
+ def test_callbacks_must_be_defined_in_the_base_model_file
5
+ whitelist_path = File.expand_path("../active_record_callback_whitelist.txt", __FILE__)
6
+ whitelisted_callbacks = if File.exists?(whitelist_path)
7
+ File.read(whitelist_path).split("\n")
8
+ else
9
+ ""
10
+ end
11
+
12
+ # git grep... list classes with a parent. Does not handle classes nested within a module
13
+ # xargs... arca analyze. We skip line numbers so we can diff the results
14
+ # grep... filter for callbacks defined in external files or callbacks without names
15
+ #
16
+ # To update the whitelist, save the output up to script/audit-callbacks.
17
+ callback_output = IO.popen(<<-CMD).read
18
+ git grep -h '^class.*< ' -- '*.rb' | cut -d' ' -f 2 | sort -u | \
19
+ xargs bundle exec audit-callbaks.rb --skip-line-num | \
20
+ grep -E 'external:true|block$'
21
+ CMD
22
+
23
+ actual_callbacks = callback_output.split("\n")
24
+
25
+ new_bad_callbacks = actual_callbacks - whitelisted_callbacks
26
+ unnecessary_whitelist_entries = whitelisted_callbacks - actual_callbacks
27
+
28
+ message = ""
29
+ if new_bad_callbacks.any?
30
+ message << "The following ActiveRecord callbacks must be defined in the base model file with a named method:\n\n"
31
+ message << new_bad_callbacks.join("\n")
32
+ end
33
+
34
+ if unnecessary_whitelist_entries.any?
35
+ message << "\n\n" unless message.empty?
36
+ message << "Hooray! You removed a bad ActiveRecord callback. Please update #{whitelist_path} and remove the following\n\n"
37
+ message << unnecessary_whitelist_entries.join("\n")
38
+ end
39
+
40
+ assert message.empty?, message
41
+ end
42
+ end
@@ -0,0 +1,75 @@
1
+ # Prints a list of Active Record callbacks for the given models
2
+ #
3
+ # Usage:
4
+ # bundle exec audit-callbacks.rb [--skip-line-num] [Model1 Model2...]
5
+ #
6
+ skip_line_num = false
7
+ if ARGV.first == "--skip-line-num"
8
+ ARGV.shift
9
+ skip_line_num = true
10
+ end
11
+
12
+ unless ARGV.size > 0
13
+ $stderr.puts "No models specified. Try script/audit-callbacks User Issue."
14
+ exit 1
15
+ end
16
+
17
+ # Arca must be required after ActiveRecord, but before the environment loads so
18
+ # we can install Arca::Collector.
19
+ require "active_record"
20
+ require "arca"
21
+ class ActiveRecord::Base
22
+ include Arca::Collector
23
+ end
24
+
25
+ require "config/environment"
26
+
27
+ # Returns a formatted string of a callback analysis.
28
+ #
29
+ # Examples:
30
+ #
31
+ # An unnamed (block) before_destroy callback defined in the same file as the model
32
+ # Ability before_destroy app/models/ability.rb external:false block
33
+ #
34
+ # A after_destroy callback named `dereference_asset` defined in a file outside of the model (external:true)
35
+ # Avatar after_destroy app/models/asset_uploadable.rb external:true dereference_asset
36
+ #
37
+ # A before_save callback defined by a callback class
38
+ # IssueComment before_save app/models/referrer.rb external:true Referrer::ReferenceMentionsCallback
39
+ #
40
+ def format_callback(callback, skip_line_num:)
41
+ path = Arca.relative_path(callback.callback_file_path)
42
+ path << ":#{callback.callback_line_number}" unless skip_line_num
43
+
44
+ # Arca outputs object ids which triggers a diff
45
+ # e.g. #<Referrer::ReferenceMentionsCallback:0x007f8bca3a1b48>
46
+ target = if match = /#<(.+):.+>/.match(callback.target_symbol.to_s)
47
+ match[1]
48
+ else
49
+ callback.target_symbol
50
+ end
51
+
52
+ [
53
+ callback.model.name,
54
+ callback.callback_symbol,
55
+ path,
56
+ "external:#{callback.external_callback?}",
57
+ target
58
+ ].map(&:to_s).join(" ")
59
+ end
60
+
61
+ ARGV.each do |model_name|
62
+ begin
63
+ model_class = model_name.constantize
64
+ rescue NameError # test classes
65
+ next
66
+ end
67
+
68
+ next unless model_class.ancestors.include?(ActiveRecord::Base)
69
+
70
+ Arca[model_class].analyzed_callbacks.each do |callback_symbol, callbacks|
71
+ callbacks.each do |callback|
72
+ puts format_callback(callback, skip_line_num: skip_line_num)
73
+ end
74
+ end
75
+ end
@@ -33,8 +33,8 @@ module Arca
33
33
  # Duplicate args before modifying.
34
34
  args_copy = args.dup
35
35
 
36
- # Add target_symbol :inline to args_copy if a block, Proc, or Class
37
- # was given.
36
+ # Add target_symbol :inline to args_copy if given a block or Proc and
37
+ # class name if a class or instance was given.
38
38
  if block
39
39
  args_copy.unshift(:inline)
40
40
  elsif args_copy.first.kind_of?(Proc)
data/lib/arca/model.rb CHANGED
@@ -15,9 +15,11 @@ module Arca
15
15
  # they are used in the life cycle of an ActiveRecord model.
16
16
  CALLBACKS = [
17
17
  :after_initialize, :after_find, :after_touch, :before_validation, :after_validation,
18
- :before_save, :around_save, :after_save, :before_create, :around_create,
19
- :after_create, :before_update, :around_update, :after_update,
20
- :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
18
+ :before_save, :around_save, :after_save, :after_save_commit,
19
+ :before_create, :around_create, :after_create, :after_create_commit,
20
+ :before_update, :around_update, :after_update, :after_update_commit,
21
+ :before_destroy, :around_destroy, :after_destroy, :after_destroy_commit,
22
+ :after_commit, :after_rollback
21
23
  ]
22
24
 
23
25
  # Public: ActiveRecord model class.
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arca
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Hoyt
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2015-08-07 00:00:00.000000000 Z
@@ -79,6 +79,8 @@ files:
79
79
  - README.md
80
80
  - Rakefile
81
81
  - arca.gemspec
82
+ - examples/active_record_lint_test.rb
83
+ - examples/audit-callbacks.rb
82
84
  - gemfiles/Gemfile_activerecord-3.2
83
85
  - gemfiles/Gemfile_activerecord-4.2
84
86
  - lib/arca.rb
@@ -99,7 +101,7 @@ homepage: https://github.com/jonmagic/arca
99
101
  licenses:
100
102
  - MIT
101
103
  metadata: {}
102
- post_install_message:
104
+ post_install_message:
103
105
  rdoc_options: []
104
106
  require_paths:
105
107
  - lib
@@ -114,9 +116,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
116
  - !ruby/object:Gem::Version
115
117
  version: '0'
116
118
  requirements: []
117
- rubyforge_project:
118
- rubygems_version: 2.2.2
119
- signing_key:
119
+ rubygems_version: 3.5.5
120
+ signing_key:
120
121
  specification_version: 4
121
122
  summary: ActiveRecord callback analyzer
122
123
  test_files: