attribute-stats 0.2.0 → 0.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 +4 -4
 - data/README.md +27 -7
 - data/lib/attribute-stats/tasks/unused_attribute_references.rake +15 -0
 - data/lib/attribute-stats/version.rb +1 -1
 - data/lib/entities/attribute_info.rb +11 -2
 - data/lib/entities/table_data.rb +7 -3
 - data/lib/formatters/hash_formatter.rb +18 -0
 - data/lib/formatters/json_formatter.rb +4 -0
 - data/lib/formatters/tabular_formatter.rb +26 -1
 - data/lib/migration_generator/generate_migration.rb +1 -8
 - data/lib/migration_generator/migration_template_contents.rb +2 -10
 - data/lib/stats_generation/set_attribute_references.rb +105 -0
 - data/lib/stats_generation/stats_generator.rb +6 -0
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: d3eb42d4e6bfaa776c008a282bff30bc5a7c2d8b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: fdfc70d6b97178fef60d2591f5306f9c9c8de366
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 808e7afbeb002cfc3f895f054f476a82bf20a653d0a324a4aab0cef53af9088e870264c82a7ca232344bd32291a6dcb1298a7cc274d4bc0cea4a8959a5c0dc97
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 57253da7c993ea883cc6024b15c03f3e7e9d6f21689858dab24076df494ad6146650f8c19da7ef06587720c7a65c6db31a36aee013dc344c7f179be7458171f8
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -18,17 +18,26 @@ Add `gem 'attribute-stats'` to your Gemfile, bundle, and follow the Usage instru 
     | 
|
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
            You can use `AttributeStats` from within Rails (or a Rails console):
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                irb:1> stats = AttributeStats::StatsGenerator.new 
     | 
| 
      
 21 
     | 
    
         
            +
                irb:1> stats = AttributeStats::StatsGenerator.new
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
       22 
23 
     | 
    
         
             
                irb:2> stats.attribute_usage
         
     | 
| 
       23 
24 
     | 
    
         
             
                => {...} # a list of your attributes and what % of records have a value set
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       24 
26 
     | 
    
         
             
                irb:3> stats.unused_attributes
         
     | 
| 
       25 
27 
     | 
    
         
             
                => {...} # a list of your attributes which have no value set in the database
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                irb:4> stats.unused_attribute_references
         
     | 
| 
      
 30 
     | 
    
         
            +
                => [...] # a list counts of references to unused attributes in application code
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                irb:5> stats.dormant_tables
         
     | 
| 
       27 
33 
     | 
    
         
             
                => [...] # a list of your tables which have not been updated in awhile
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                irb:6> stats.migration
         
     | 
| 
       29 
36 
     | 
    
         
             
                => # sample migration up/down to remove your unused attributes
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                irb:7> stats. 
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                irb:7> stats.set_formatter :json
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                irb:8> stats.migration # returns json instead of a hash
         
     | 
| 
       32 
41 
     | 
    
         | 
| 
       33 
42 
     | 
    
         
             
            ### Rake Tasks
         
     | 
| 
       34 
43 
     | 
    
         | 
| 
         @@ -37,6 +46,7 @@ Rake tasks are available once you've installed the gem in your Gemfile and bundl 
     | 
|
| 
       37 
46 
     | 
    
         
             
            * rake db:stats:dormant_tables
         
     | 
| 
       38 
47 
     | 
    
         
             
            * rake db:stats:attribute_usage
         
     | 
| 
       39 
48 
     | 
    
         
             
            * rake db:stats:unused_attributes
         
     | 
| 
      
 49 
     | 
    
         
            +
            * rake db:stats:unused_attribute_references
         
     | 
| 
       40 
50 
     | 
    
         
             
            * rake attribute-stats:generate_migration
         
     | 
| 
       41 
51 
     | 
    
         | 
| 
       42 
52 
     | 
    
         
             
            Each allows you to change the output to JSON if you'd like to pipe it into another application.
         
     | 
| 
         @@ -55,6 +65,18 @@ i.e. `rake db:stats:unused_attributes[true,json,false]` 
     | 
|
| 
       55 
65 
     | 
    
         | 
| 
       56 
66 
     | 
    
         
             
            ---
         
     | 
| 
       57 
67 
     | 
    
         | 
| 
      
 68 
     | 
    
         
            +
            #### rake db:stats:unused_attribute_references
         
     | 
| 
      
 69 
     | 
    
         
            +
            For all unused attributes, outputs the number of times the attribute name is referenced in repo's app, views, config, and spec folders (except app/assets). This finds references which are symbols, wrapped in quotes, or accessed via dot notation. It is imprecise but gives you an idea of attributes may be used in the application code.
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            **Argument Options:**
         
     | 
| 
      
 72 
     | 
    
         
            +
            1. consider_defaults_unused: true or false (default: false). This option considers attributes set to the databse default value to be unused.
         
     | 
| 
      
 73 
     | 
    
         
            +
            2. format: tabular, json  (default: tabular)
         
     | 
| 
      
 74 
     | 
    
         
            +
            3. verbose: true, false (default: true)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            i.e. `rake db:stats:unused_attribute_references[true,json,false]`
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            ---
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
       58 
80 
     | 
    
         
             
            #### rake db:stats:attribute_usage
         
     | 
| 
       59 
81 
     | 
    
         
             
            Lists usage statistics for all attributes (count and percent which are unused). Note: this does a full scan of your tables, so it will be slow for tables with a lot of data.
         
     | 
| 
       60 
82 
     | 
    
         | 
| 
         @@ -96,8 +118,6 @@ The gem does not support: 
     | 
|
| 
       96 
118 
     | 
    
         | 
| 
       97 
119 
     | 
    
         
             
            The gem is tested and works with Rails version 4.2 through 5.2, with `mysql2`, `sqlite3`, and `postgresql` database adapters. You can view all tested dependency sets in [Appraisals](Appraisals)
         
     | 
| 
       98 
120 
     | 
    
         | 
| 
       99 
     | 
    
         
            -
            *Due to changes in ActiveRecord between 4.1 and 4.2, the gem breaks in versions below 4.2. In a future version of `attribute-stats`, I intend to add support to previous versions of Rails (at least back to 4.0).*
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
121 
     | 
    
         
             
            ## Testing the gem
         
     | 
| 
       102 
122 
     | 
    
         | 
| 
       103 
123 
     | 
    
         
             
            To test the gem against the current version of Rails (in [Gemfile.lock](Gemfile.lock)) and sqlite:
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'attribute-stats'
         
     | 
| 
      
 2 
     | 
    
         
            +
            namespace :db do
         
     | 
| 
      
 3 
     | 
    
         
            +
            	namespace :stats do
         
     | 
| 
      
 4 
     | 
    
         
            +
            		desc "Count source code references to unused attributes [options CONSIDER_DEFAULTS_UNUSED: false, FORMAT: json, tabular, VERBOSE: false]"
         
     | 
| 
      
 5 
     | 
    
         
            +
            		task :unused_attribute_references, [:consider_defaults_unused,:format,:verbose] => :environment do |task, args|
         
     | 
| 
      
 6 
     | 
    
         
            +
            			args.with_defaults(consider_defaults_unused: 'false', format: 'tabular', verbose: 'true')
         
     | 
| 
      
 7 
     | 
    
         
            +
                  options = {
         
     | 
| 
      
 8 
     | 
    
         
            +
                    consider_defaults_unused: args[:consider_defaults_unused].downcase != 'false',
         
     | 
| 
      
 9 
     | 
    
         
            +
                                   formatter: args[:format],
         
     | 
| 
      
 10 
     | 
    
         
            +
                                     verbose: args[:verbose].downcase != 'false',
         
     | 
| 
      
 11 
     | 
    
         
            +
                                      source: :cli }
         
     | 
| 
      
 12 
     | 
    
         
            +
                  AttributeStats::StatsGenerator.new(options).unused_attribute_references
         
     | 
| 
      
 13 
     | 
    
         
            +
            		end
         
     | 
| 
      
 14 
     | 
    
         
            +
            	end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,9 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module AttributeStats
         
     | 
| 
       2 
2 
     | 
    
         
             
              class AttributeInfo
         
     | 
| 
       3 
     | 
    
         
            -
                attr_reader :count, :usage_percent, :name, :empty
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :count, :usage_percent, :name, :empty, :references
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                def initialize(attribute_name)
         
     | 
| 
       6 
6 
     | 
    
         
             
                  @name = attribute_name
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @references = Hash.new(0)
         
     | 
| 
       7 
8 
     | 
    
         
             
                end
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
                def set_usage(record_count, table_total_record_count)
         
     | 
| 
         @@ -19,5 +20,13 @@ module AttributeStats 
     | 
|
| 
       19 
20 
     | 
    
         
             
                def empty?
         
     | 
| 
       20 
21 
     | 
    
         
             
                  @empty
         
     | 
| 
       21 
22 
     | 
    
         
             
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def set_reference(reference_type, count)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  references[reference_type] += count
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def total_references
         
     | 
| 
      
 29 
     | 
    
         
            +
                  references.values.sum
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
       22 
31 
     | 
    
         
             
              end
         
     | 
| 
       23 
     | 
    
         
            -
            end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/entities/table_data.rb
    CHANGED
    
    | 
         @@ -37,14 +37,18 @@ module AttributeStats 
     | 
|
| 
       37 
37 
     | 
    
         
             
                  attribute
         
     | 
| 
       38 
38 
     | 
    
         
             
                end
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                def  
     | 
| 
       41 
     | 
    
         
            -
                  @ 
     | 
| 
      
 40 
     | 
    
         
            +
                def unused_attribute_info
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @unused_attribute_info ||= begin
         
     | 
| 
       42 
42 
     | 
    
         
             
                    attrs = []
         
     | 
| 
       43 
43 
     | 
    
         
             
                    @attributes.each do |attribute|
         
     | 
| 
       44 
     | 
    
         
            -
                      attrs << attribute 
     | 
| 
      
 44 
     | 
    
         
            +
                      attrs << attribute if attribute.empty?
         
     | 
| 
       45 
45 
     | 
    
         
             
                    end
         
     | 
| 
       46 
46 
     | 
    
         
             
                    attrs
         
     | 
| 
       47 
47 
     | 
    
         
             
                  end
         
     | 
| 
       48 
48 
     | 
    
         
             
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def unused_attributes
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @unused_attributes ||= unused_attribute_info.map(&:name)
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
       49 
53 
     | 
    
         
             
              end
         
     | 
| 
       50 
54 
     | 
    
         
             
            end
         
     | 
| 
         @@ -5,6 +5,24 @@ module AttributeStats 
     | 
|
| 
       5 
5 
     | 
    
         
             
                  @options, @table_info, @migration = options, table_info, migration
         
     | 
| 
       6 
6 
     | 
    
         
             
                end
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
      
 8 
     | 
    
         
            +
                def output_attribute_references
         
     | 
| 
      
 9 
     | 
    
         
            +
                  output = []
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @table_info.each do |table_info|
         
     | 
| 
      
 11 
     | 
    
         
            +
                    table_info.attributes.each do |attribute|
         
     | 
| 
      
 12 
     | 
    
         
            +
                      next unless attribute.empty?
         
     | 
| 
      
 13 
     | 
    
         
            +
                      output << {
         
     | 
| 
      
 14 
     | 
    
         
            +
                                  model: table_info.name,
         
     | 
| 
      
 15 
     | 
    
         
            +
                              attribute: attribute.name,
         
     | 
| 
      
 16 
     | 
    
         
            +
                         all_references: attribute.total_references,
         
     | 
| 
      
 17 
     | 
    
         
            +
                        code_references: attribute.references['app'],
         
     | 
| 
      
 18 
     | 
    
         
            +
                        spec_references: attribute.references['spec'],
         
     | 
| 
      
 19 
     | 
    
         
            +
                        view_references: attribute.references['views']
         
     | 
| 
      
 20 
     | 
    
         
            +
                      } 
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  output.sort!{|a,b| a[:all_references] <=> b[:all_references]}
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       8 
26 
     | 
    
         
             
                def output_all_attributes
         
     | 
| 
       9 
27 
     | 
    
         
             
                  output = []
         
     | 
| 
       10 
28 
     | 
    
         
             
                  @table_info.each do |table_info|
         
     | 
| 
         @@ -28,6 +28,30 @@ module AttributeStats 
     | 
|
| 
       28 
28 
     | 
    
         
             
                  @buffer
         
     | 
| 
       29 
29 
     | 
    
         
             
                end
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
      
 31 
     | 
    
         
            +
                def output_attribute_references
         
     | 
| 
      
 32 
     | 
    
         
            +
                  output = []
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @table_info.each do |table_info|
         
     | 
| 
      
 34 
     | 
    
         
            +
                    table_info.attributes.each do |attribute|
         
     | 
| 
      
 35 
     | 
    
         
            +
                      next unless attribute.empty?
         
     | 
| 
      
 36 
     | 
    
         
            +
                      output << {
         
     | 
| 
      
 37 
     | 
    
         
            +
                                  model: table_info.name,
         
     | 
| 
      
 38 
     | 
    
         
            +
                         attribute_name: attribute.name,
         
     | 
| 
      
 39 
     | 
    
         
            +
                         all_references: attribute.total_references,
         
     | 
| 
      
 40 
     | 
    
         
            +
                                   code: attribute.references['app'],
         
     | 
| 
      
 41 
     | 
    
         
            +
                                  specs: attribute.references['spec'],
         
     | 
| 
      
 42 
     | 
    
         
            +
                                  views: attribute.references['views']
         
     | 
| 
      
 43 
     | 
    
         
            +
                      } 
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                  output.sort!{|a,b| a[:all_references] <=> b[:all_references]}
         
     | 
| 
      
 47 
     | 
    
         
            +
                  if output.empty?
         
     | 
| 
      
 48 
     | 
    
         
            +
                    puts "No unused attributes found"
         
     | 
| 
      
 49 
     | 
    
         
            +
                  else
         
     | 
| 
      
 50 
     | 
    
         
            +
                    print_table output, title: ['Attribute Code References', 'Mentions of the attribute name in app/ (except assets), lib/, config/, and spec/', '(symbol or dot notation, or wrapped in quotes)']
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @buffer
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       31 
55 
     | 
    
         
             
                def output_dormant_tables
         
     | 
| 
       32 
56 
     | 
    
         
             
                  output = []
         
     | 
| 
       33 
57 
     | 
    
         
             
                  @table_info.each do |table_info|
         
     | 
| 
         @@ -106,7 +130,8 @@ module AttributeStats 
     | 
|
| 
       106 
130 
     | 
    
         | 
| 
       107 
131 
     | 
    
         
             
                def header_order(column_names)
         
     | 
| 
       108 
132 
     | 
    
         
             
                  [:model, :table_name, :attribute_name,
         
     | 
| 
       109 
     | 
    
         
            -
                    :last_updated, :set_count, :set_percent 
     | 
| 
      
 133 
     | 
    
         
            +
                    :last_updated, :set_count, :set_percent,
         
     | 
| 
      
 134 
     | 
    
         
            +
                    :code, :views, :specs] & column_names
         
     | 
| 
       110 
135 
     | 
    
         
             
                end
         
     | 
| 
       111 
136 
     | 
    
         | 
| 
       112 
137 
     | 
    
         
             
                def formatted_headers(column_names)
         
     | 
| 
         @@ -1,8 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module AttributeStats
         
     | 
| 
       2 
2 
     | 
    
         
             
              class GenerateMigration
         
     | 
| 
       3 
     | 
    
         
            -
                def initialize(table_info:  
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(table_info: [], options: {})
         
     | 
| 
       4 
4 
     | 
    
         
             
                  @table_info, @options = table_info, options
         
     | 
| 
       5 
     | 
    
         
            -
                  @table_info || set_table_info
         
     | 
| 
       6 
5 
     | 
    
         
             
                end
         
     | 
| 
       7 
6 
     | 
    
         | 
| 
       8 
7 
     | 
    
         
             
                def output_migration
         
     | 
| 
         @@ -13,12 +12,6 @@ module AttributeStats 
     | 
|
| 
       13 
12 
     | 
    
         
             
                  migration_file_path
         
     | 
| 
       14 
13 
     | 
    
         
             
                end
         
     | 
| 
       15 
14 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                def set_table_info
         
     | 
| 
       17 
     | 
    
         
            -
                  stats_generator = AttributeStats::StatsGenerator.new(@options)
         
     | 
| 
       18 
     | 
    
         
            -
                  stats_generator.send(:fetch_empty_attributes)
         
     | 
| 
       19 
     | 
    
         
            -
                  @table_info = stats_generator.table_info
         
     | 
| 
       20 
     | 
    
         
            -
                end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
15 
     | 
    
         
             
                private
         
     | 
| 
       23 
16 
     | 
    
         | 
| 
       24 
17 
     | 
    
         
             
                def migration_file_path
         
     | 
| 
         @@ -1,9 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module AttributeStats
         
     | 
| 
       2 
2 
     | 
    
         
             
              class MigrationTemplateContents
         
     | 
| 
       3 
     | 
    
         
            -
                def initialize(table_info:  
     | 
| 
       4 
     | 
    
         
            -
                  @table_info = table_info
         
     | 
| 
       5 
     | 
    
         
            -
                  @table_info || set_table_info
         
     | 
| 
       6 
     | 
    
         
            -
                  @migration_class_suffix = migration_class_suffix
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(table_info: [], migration_class_suffix: nil)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @table_info, @migration_class_suffix = table_info, migration_class_suffix
         
     | 
| 
       7 
5 
     | 
    
         
             
                  @migration_buffer = ''
         
     | 
| 
       8 
6 
     | 
    
         
             
                  @table_info.each do |table_info|
         
     | 
| 
       9 
7 
     | 
    
         
             
                    add_migrations_for_table_to_buffer(table_info)
         
     | 
| 
         @@ -24,12 +22,6 @@ end 
     | 
|
| 
       24 
22 
     | 
    
         
             
                  output
         
     | 
| 
       25 
23 
     | 
    
         
             
                end
         
     | 
| 
       26 
24 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                def set_table_info
         
     | 
| 
       28 
     | 
    
         
            -
                  stats_generator = AttributeStats::StatsGenerator.new
         
     | 
| 
       29 
     | 
    
         
            -
                  stats_generator.send(:fetch_empty_attributes)
         
     | 
| 
       30 
     | 
    
         
            -
                  @table_info = stats_generator.table_info
         
     | 
| 
       31 
     | 
    
         
            -
                end
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
25 
     | 
    
         
             
                private
         
     | 
| 
       34 
26 
     | 
    
         | 
| 
       35 
27 
     | 
    
         
             
                # This is a modified version of the ActiveRecord::SchemaDumper#table method.
         
     | 
| 
         @@ -0,0 +1,105 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'terminal'
         
     | 
| 
      
 2 
     | 
    
         
            +
            module AttributeStats
         
     | 
| 
      
 3 
     | 
    
         
            +
              class SetAttributeReferences
         
     | 
| 
      
 4 
     | 
    
         
            +
                include Terminal
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :table_info
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(table_info: [], options: {})
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @table_info, @options = table_info, options
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def execute
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @executed ||= begin
         
     | 
| 
      
 13 
     | 
    
         
            +
                    lookup_and_set_attribute_counts
         
     | 
| 
      
 14 
     | 
    
         
            +
                    true
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                private
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def lookup_and_set_attribute_counts
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @table_info.each_with_index do |t,index|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @table_count = index
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @current_table = t
         
     | 
| 
      
 24 
     | 
    
         
            +
                    fetch_table_stats
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  erase_line if @options[:verbose]
         
     | 
| 
      
 27 
     | 
    
         
            +
                  true
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                private
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def fetch_table_stats
         
     | 
| 
      
 33 
     | 
    
         
            +
                  print("Finding Code References #{in_color(@current_table.name,@table_count)} ") if @options[:verbose]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  set_reference_counts
         
     | 
| 
      
 35 
     | 
    
         
            +
                  erase_line if @options[:verbose]
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def set_reference_counts
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @current_table.unused_attribute_info.each do |attribute_info|
         
     | 
| 
      
 40 
     | 
    
         
            +
                    count = set_attribute_reference_count(attribute_info)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    next unless @options[:verbose]
         
     | 
| 
      
 42 
     | 
    
         
            +
                    print count.zero? ? green('✓') : red('x')
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def set_attribute_reference_count(attribute_info)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  files = `grep -rcE "#{regexes(attribute_info).join('|')}" --exclude-dir={#{regex_exclude_paths.join(',')}} #{regex_target_paths.join(' ')}`
         
     | 
| 
      
 48 
     | 
    
         
            +
                  attribute_total = 0
         
     | 
| 
      
 49 
     | 
    
         
            +
                  files.scan(/(.*):(\d+)(?:\n|\z)/).each do |matches|
         
     | 
| 
      
 50 
     | 
    
         
            +
                    next if matches[0].nil?
         
     | 
| 
      
 51 
     | 
    
         
            +
                    filename, count = matches[0], matches[1].to_i
         
     | 
| 
      
 52 
     | 
    
         
            +
                    next if count == 0
         
     | 
| 
      
 53 
     | 
    
         
            +
                    attribute_total += count
         
     | 
| 
      
 54 
     | 
    
         
            +
                    attribute_info.set_reference section(filename), count
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  attribute_total
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def regexes(attribute_info)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  [
         
     | 
| 
      
 61 
     | 
    
         
            +
                    "\\\"#{attribute_info.name}\\\"",                # "my_attribute_name"
         
     | 
| 
      
 62 
     | 
    
         
            +
                    "'#{attribute_info.name}'",                      # 'my_attribute_name'
         
     | 
| 
      
 63 
     | 
    
         
            +
                    "\\:#{attribute_info.name}[^A-Za-z_]?",           # :my_attribute_name
         
     | 
| 
      
 64 
     | 
    
         
            +
                    "\\.#{attribute_info.name}[^A-Za-z_]?",           # .my_attribute_name
         
     | 
| 
      
 65 
     | 
    
         
            +
                    # "[^A-Za-z_]#{attribute_info.name}[^A-Za-z_]",  #  my_attribute_name (standalone word)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def regex_target_paths
         
     | 
| 
      
 70 
     | 
    
         
            +
                  directories = @options[:include_directories] || %w(app lib config spec)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  if regex_base_path
         
     | 
| 
      
 72 
     | 
    
         
            +
                    directories.map do |directory|
         
     | 
| 
      
 73 
     | 
    
         
            +
                      File.join regex_base_path, directory
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
                  else
         
     | 
| 
      
 76 
     | 
    
         
            +
                    directories
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def regex_exclude_paths
         
     | 
| 
      
 81 
     | 
    
         
            +
                  directories = @options[:exclude_directories] || %w(app/assets db public)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  if regex_base_path
         
     | 
| 
      
 83 
     | 
    
         
            +
                    directories.map do |directory|
         
     | 
| 
      
 84 
     | 
    
         
            +
                      File.join regex_base_path, directory
         
     | 
| 
      
 85 
     | 
    
         
            +
                    end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  else
         
     | 
| 
      
 87 
     | 
    
         
            +
                    directories
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                def section(filename)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  if filename =~ /\A#{regex_base_path}\/spec\//
         
     | 
| 
      
 93 
     | 
    
         
            +
                    'spec'
         
     | 
| 
      
 94 
     | 
    
         
            +
                  elsif filename =~ /\A#{regex_base_path}\/app\/views\//
         
     | 
| 
      
 95 
     | 
    
         
            +
                    'views'
         
     | 
| 
      
 96 
     | 
    
         
            +
                  else
         
     | 
| 
      
 97 
     | 
    
         
            +
                    'app'
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                def regex_base_path
         
     | 
| 
      
 102 
     | 
    
         
            +
                  @options[:rails_root]
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
              end
         
     | 
| 
      
 105 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -34,6 +34,12 @@ module AttributeStats 
     | 
|
| 
       34 
34 
     | 
    
         
             
                  GenerateMigration.new(table_info: table_info, options: options).output_migration
         
     | 
| 
       35 
35 
     | 
    
         
             
                end
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
      
 37 
     | 
    
         
            +
                def unused_attribute_references
         
     | 
| 
      
 38 
     | 
    
         
            +
                  fetch_empty_attributes
         
     | 
| 
      
 39 
     | 
    
         
            +
                  SetAttributeReferences.new(table_info: table_info, options: options).execute
         
     | 
| 
      
 40 
     | 
    
         
            +
                  output formatter.output_attribute_references
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       37 
43 
     | 
    
         
             
                def set_formatter(formatter_type)
         
     | 
| 
       38 
44 
     | 
    
         
             
                  formatter_was = options[:formatter]
         
     | 
| 
       39 
45 
     | 
    
         
             
                  case formatter_type.to_s.downcase
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: attribute-stats
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.3.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Steve Hodges
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2018-10- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2018-10-02 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rails
         
     | 
| 
         @@ -136,6 +136,7 @@ files: 
     | 
|
| 
       136 
136 
     | 
    
         
             
            - lib/attribute-stats/tasks/dormant.rake
         
     | 
| 
       137 
137 
     | 
    
         
             
            - lib/attribute-stats/tasks/list_models.rake
         
     | 
| 
       138 
138 
     | 
    
         
             
            - lib/attribute-stats/tasks/migration.rake
         
     | 
| 
      
 139 
     | 
    
         
            +
            - lib/attribute-stats/tasks/unused_attribute_references.rake
         
     | 
| 
       139 
140 
     | 
    
         
             
            - lib/attribute-stats/tasks/unused_attributes.rake
         
     | 
| 
       140 
141 
     | 
    
         
             
            - lib/attribute-stats/version.rb
         
     | 
| 
       141 
142 
     | 
    
         
             
            - lib/entities/attribute_info.rb
         
     | 
| 
         @@ -145,6 +146,7 @@ files: 
     | 
|
| 
       145 
146 
     | 
    
         
             
            - lib/formatters/tabular_formatter.rb
         
     | 
| 
       146 
147 
     | 
    
         
             
            - lib/migration_generator/generate_migration.rb
         
     | 
| 
       147 
148 
     | 
    
         
             
            - lib/migration_generator/migration_template_contents.rb
         
     | 
| 
      
 149 
     | 
    
         
            +
            - lib/stats_generation/set_attribute_references.rb
         
     | 
| 
       148 
150 
     | 
    
         
             
            - lib/stats_generation/set_attribute_stats.rb
         
     | 
| 
       149 
151 
     | 
    
         
             
            - lib/stats_generation/set_dormant_tables.rb
         
     | 
| 
       150 
152 
     | 
    
         
             
            - lib/stats_generation/stats_generator.rb
         
     |