Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions lib/active_record/annotate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,67 @@ module Annotate
class << self
def annotate
processed_models = []

models.each do |table_name, file_paths_and_classes|
annotation = Dumper.dump(table_name)

file_paths_and_classes.each do |path, klass|
file = File.new(path)
file.annotate_with(annotation.dup, configurator)

if file.changed?
file.write
processed_models << "#{klass} (#{file.relative_path})"
end
end
end

unless processed_models.empty?
puts 'Annotated models:'
processed_models.each do |model|
puts " * #{model}"
end
end
end

def models
files_mask = models_dir.join('**', '*.rb')

hash_with_arrays = Hash.new do |hash, key|
hash[key] = []
end

Dir.glob(files_mask).each_with_object(hash_with_arrays) do |path, models|
short_path = short_path_for(path)
next if short_path.starts_with?('concerns') # skip any app/models/concerns files

klass = class_name_for(short_path)
next unless klass < ActiveRecord::Base # collect only AR::Base descendants
next if klass.respond_to?(:abstract_class?) && klass.abstract_class?

models[klass.table_name] << [path, klass]
end
end

# .../app/models/car/hatchback.rb -> car/hatchback
def short_path_for(full_path)
full_path.sub(models_dir.to_s + '/', '').sub(/\.rb$/, '')
end

# car/hatchback -> Car::Hatchback
def class_name_for(short_path)
short_path.camelize.constantize
end

def configure(&block)
configurator.tap(&block)
end

private
def models_dir
Rails.root.join('app/models')
end

def configurator
@configurator ||= Configurator.new
end
Expand Down
12 changes: 8 additions & 4 deletions lib/active_record/annotate/configurator.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
module ActiveRecord
module Annotate
class Configurator
%w(yard).each do |setting|
BOOLEAN_ATTRIBUTES = %w(yard debug)

BOOLEAN_ATTRIBUTES.each do |setting|
attr_accessor setting
alias_method "#{setting}?", setting
end

def initialize
reset
end

private
def reset
@yard = false
BOOLEAN_ATTRIBUTES.each do |attr|
instance_variable_set("@#{attr}", false)
end
end
end
end
Expand Down
36 changes: 22 additions & 14 deletions lib/active_record/annotate/file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ module ActiveRecord
module Annotate
class File
attr_reader :path, :lines

def initialize(path)
@path = path
@content = ::File.read(path)
@lines = @content.split(?\n)
end

def annotate_with(annotation, configurator)
magic_comments = []

while @lines.first =~ /^\s*#.*(coding|frozen_string_literal|warn_indent)/i
magic_comments.push(@lines.shift)
end
Expand All @@ -19,39 +20,46 @@ def annotate_with(annotation, configurator)
# separate magic comments from the annotation with an empty line
magic_comments << nil
end

while @lines.first.start_with?('#') || @lines.first.blank?
# throw out comments and empty lines
# in the beginning of the file (old annotation)
@lines.shift
end

if configurator.yard?
backticks = '# ```'
annotation.unshift(backticks).push(backticks)

if annotation.first.start_with?("# create_table")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Morozzzko will this work for views, or we need something like annotation.first.start_with?("# create_table") || annotation.first.start_with?("# create_view")? Can you tell us how the views look like in your app's annotations?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check and tell you by Tuesday evening

Copy link
Contributor

@Morozzzko Morozzzko Feb 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I'm late. It says create_table even if it's a view

Probably because it's a materialized view, not sure

create_table :table_name id: false, force: :cascade do |t|

if configurator.yard?
backticks = '# ```'
annotation.unshift(backticks).push(backticks)
end

@lines.unshift(*annotation, nil)
elsif configurator.debug
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be

Suggested change
elsif configurator.debug
elsif configurator.debug?

### If debugging enabled print errors, Else squelch the error
puts annotation
end

@lines.unshift(*annotation, nil)

@lines.unshift(*magic_comments)

@lines.push(nil) # newline at the end of file
end

def write
new_file_content = @lines.join(?\n)
temp_path = "#{@path}.annotated"

::File.open(temp_path, 'w') do |temp_file|
temp_file.write(new_file_content)
end

::File.delete(@path)
::File.rename(temp_path, @path)
end

def changed?
@lines.join(?\n) != @content
end

def relative_path
path.sub(/^#{Rails.root}\//, '')
end
Expand Down
6 changes: 6 additions & 0 deletions spec/active_record/annotate/configurator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
describe "#initialize" do
it "resets all settings to their default values" do
expect(subject.yard).to be_falsy
expect(subject.debug).to be_falsy
end
end

Expand All @@ -13,6 +14,11 @@

subject.yard = true
expect(subject.yard).to be_truthy

expect(subject.debug).to be_falsy

subject.debug = true
expect(subject.debug).to be_truthy
end
end
end
21 changes: 20 additions & 1 deletion spec/active_record/annotate/file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ class User < ActiveRecord::Base
end

let(:file) { ActiveRecord::Annotate::File.new(file_path) }
let(:configurator) { ActiveRecord::Annotate::Configurator.new }
let(:configurator) {
c = ActiveRecord::Annotate::Configurator.new
c.debug = true
c
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified to ActiveRecord::Annotate::Configurator.new.tap { |c| c.debug = true }.

}

describe "#annotate_with" do
it "changes the lines adding the new annotation" do
Expand Down Expand Up @@ -149,4 +153,19 @@ class User < ActiveRecord::Base
expect(file.relative_path).to eq('namespace/path.rb')
end
end

describe "Annotation Errors" do
it "Removes Old Annotation" do
file.annotate_with(["error"], configurator)
expect(file).to be_changed

file.write
new_file = ActiveRecord::Annotate::File.new(file.path)

### Doesnt add new annotation to non-annotated file
new_file.annotate_with(["error"], configurator)
expect(new_file).not_to be_changed
end
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get the idea of this test. You are re-annotating the file with the same annotation and then checking that it didn't change :) Also the title assumes that old annotation should get removed which is not what happens here.

end

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant empty line.

end