class Aam::Annotation

Constants

MAGIC_COMMENT_LINE

Attributes

counts[RW]
options[RW]

Public Class Methods

new(options = {}) click to toggle source
# File lib/aam/annotation.rb, line 11
def initialize(options = {})
  @options = {
    :root_dir => Rails.root,
    :dry_run => false,
    :skip_columns => [], # %w(id created_at updated_at),
    :models => ENV["MODEL"].presence || ENV["MODELS"].presence,
  }.merge(options)
  @counts = Hash.new(0)
  STDOUT.sync = true
end
run(options = {}) click to toggle source
# File lib/aam/annotation.rb, line 7
def self.run(options = {})
  new(options).run
end

Public Instance Methods

model_file_write_all() click to toggle source
# File lib/aam/annotation.rb, line 28
def model_file_write_all
  target_ar_klasses_from_model_filenames.each do |klass|
    begin
      model = Model.new(self, klass)
      model.write_to_relation_files
    rescue ActiveRecord::ActiveRecordError => error
      if @options[:debug]
        puts "--------------------------------------------------------------------------------"
        p error
        puts "--------------------------------------------------------------------------------"
      end
      @counts[:error] += 1
    end
  end
  puts
  puts "#{@counts[:success]} success, #{@counts[:skip]} skip, #{@counts[:error]} errors"
end
root_dir() click to toggle source
# File lib/aam/annotation.rb, line 61
def root_dir
  @root_dir ||= Pathname(@options[:root_dir].to_s).expand_path
end
run() click to toggle source
# File lib/aam/annotation.rb, line 22
def run
  schema_info_text_write
  puts
  model_file_write_all
end
schema_info_text_write() click to toggle source
# File lib/aam/annotation.rb, line 46
def schema_info_text_write
  @all = []
  target_ar_klasses_from_model_require_and_ar_subclasses.each do |klass|
    begin
      model = Model.new(self, klass)
      @all << model.schema_info
    rescue ActiveRecord::ActiveRecordError => error
    end
  end
  file = root_dir.join("db", "schema_info.txt")
  magic_comment = "-*- truncate-lines: t -*-"
  file.write("#{magic_comment}\n\n#{@all.join}")
  puts "output: #{file} (#{@all.size} counts)"
end

Private Instance Methods

target_ar_klasses() click to toggle source

テーブルを持っているクラスたち

# File lib/aam/annotation.rb, line 151
def target_ar_klasses
  target_ar_klasses_from_model_require_and_ar_subclasses
  # ActiveRecord::Base.subclasses
end
target_ar_klasses_from_model_filenames() click to toggle source

app/models/* のファイル名を constantize してみることでクラスを収集する

# File lib/aam/annotation.rb, line 175
def target_ar_klasses_from_model_filenames
  models = []
  target_model_files.each do |file|
    file = file.expand_path
    klass = nil

    md = file.to_s.match(/\A.*\/app\/models\/(.*)\.rb\z/)
    underscore_class_name = md.captures.first
    class_name = underscore_class_name.camelize # classify だと boss が bos になってしまう
    begin
      klass = class_name.constantize
    rescue LoadError => error # LoadError は rescue nil では捕捉できないため
      puts "#{class_name} に対応するファイルは見つかりませんでした : #{error}"
    rescue
    end

    # klass.class == Class を入れないと [] < ActiveRecord::Base のときにエラーになる
    if klass && klass.class == Class && klass < ActiveRecord::Base && !klass.abstract_class?
      # puts "#{file} は ActiveRecord::Base のサブクラスなので対象とします。"
      puts "model: #{file}"
      models << klass
    else
      # puts "#{file} (クラス名:#{class_name}) は ActiveRecord::Base のサブクラスではありませんでした。"
    end
  end
  models
end
target_ar_klasses_from_model_require_and_ar_subclasses() click to toggle source

すべての app/models/*/.rb を require したあと ActiveRecord::Base.subclasses を参照

# File lib/aam/annotation.rb, line 157
def target_ar_klasses_from_model_require_and_ar_subclasses
  target_model_files.each do |file|
    begin
      silence_warnings do
        require file
      end
      puts "require: #{file}"
    rescue Exception
    end
  end
  if defined?(ApplicationRecord)
    ApplicationRecord.subclasses
  else
    ActiveRecord::Base.subclasses
  end
end
target_model_files() click to toggle source

対象のモデルファイル

# File lib/aam/annotation.rb, line 206
def target_model_files
  files = []
  files += Pathname.glob("#{root_dir}/app/models/**/*.rb")
  files += Pathname.glob("#{root_dir}/vendor/plugins/*/app/models/**/*.rb")
  if @options[:models]
    @options[:models].split(",").collect { |m|
      files.find_all { |e|
        e.basename(".*").to_s.match(/#{m.camelize}|#{m.underscore}/i)
      }
    }.flatten.uniq
  else
    files
  end
end