active_record-annotate 0.1.1 → 0.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.
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Guardfile +7 -0
- data/README.md +18 -6
- data/Rakefile +5 -0
- data/active_record-annotate.gemspec +5 -0
- data/lib/active_record/annotate.rb +40 -13
- data/lib/active_record/annotate/file.rb +50 -0
- data/lib/active_record/annotate/version.rb +1 -1
- data/lib/tasks/annotate.rake +6 -0
- data/spec/active_record/annotate/file_spec.rb +111 -0
- data/spec/active_record/annotate_spec.rb +21 -0
- data/spec/spec_helper.rb +4 -0
- metadata +100 -13
- checksums.yaml +0 -7
- data/lib/active_record/annotate/writer.rb +0 -38
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# ActiveRecord::Annotate
|
1
|
+
# ActiveRecord::Annotate [](https://travis-ci.org/7even/active_record-annotate) [](https://codeclimate.com/github/7even/active_record-annotate)
|
2
2
|
|
3
|
-
|
3
|
+
ActiveRecord::Annotate is a simple ActiveRecord plugin for annotating your rails models. It is based on `ActiveRecord::SchemaDumper` (a core ActiveRecord class responsible for creating `db/schema.rb`) so the annotation format is very close to what you write in your migrations.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -9,7 +9,8 @@ Trivial.
|
|
9
9
|
``` ruby
|
10
10
|
# Gemfile
|
11
11
|
group :development do
|
12
|
-
|
12
|
+
# you don't want to annotate your models in production, do you?
|
13
|
+
gem 'active_record-annotate', '~> 0.2'
|
13
14
|
end
|
14
15
|
```
|
15
16
|
|
@@ -19,9 +20,15 @@ $ bundle
|
|
19
20
|
|
20
21
|
## Usage
|
21
22
|
|
22
|
-
Gem adds a simple `db:annotate` rake task - it just writes the annotation to the top of each model file in a comment block
|
23
|
+
Gem adds a simple `db:annotate` rake task - it just writes the annotation to the top of each model file in a comment block (magic encoding comment is preserved).
|
23
24
|
|
24
|
-
|
25
|
+
Once you install the gem into your application it hooks `db:annotate` to run after each `db:migrate` / `db:rollback` to keep the annotations in sync with the DB schema, but if you added a new model without migrating (or just accidentally messed up with something) you can always run the annotation process by hand:
|
26
|
+
|
27
|
+
``` sh
|
28
|
+
$ rake db:annotate
|
29
|
+
```
|
30
|
+
|
31
|
+
This is what a common annotation looks like:
|
25
32
|
|
26
33
|
``` ruby
|
27
34
|
# create_table :documents, force: true do |t|
|
@@ -38,12 +45,17 @@ class Document < ActiveRecord::Base
|
|
38
45
|
# ...
|
39
46
|
```
|
40
47
|
|
48
|
+
## Changelog
|
49
|
+
|
50
|
+
* 0.1 Initial version with core functionality
|
51
|
+
* 0.1.1 Support for several models per table
|
52
|
+
* 0.2 Auto-annotation after `db:migrate` & `db:rollback`, basic output
|
53
|
+
|
41
54
|
## Roadmap
|
42
55
|
|
43
56
|
* Cover everything with tests
|
44
57
|
* Write YARD docs
|
45
58
|
* Add some means to configure the annotation process (annotation format, a place to put it)
|
46
|
-
* Try to add auto-annotation after `db:migrate`
|
47
59
|
|
48
60
|
## Contributing
|
49
61
|
|
data/Rakefile
CHANGED
@@ -22,4 +22,9 @@ Gem::Specification.new do |spec|
|
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
24
|
spec.add_development_dependency 'rake'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'guard-rspec'
|
27
|
+
spec.add_development_dependency 'terminal-notifier-guard'
|
28
|
+
spec.add_development_dependency 'pry'
|
29
|
+
spec.add_development_dependency 'awesome_print'
|
25
30
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'active_record/annotate/dumper'
|
2
|
-
require 'active_record/annotate/
|
2
|
+
require 'active_record/annotate/file'
|
3
3
|
require 'active_record/annotate/version'
|
4
4
|
require 'active_record/annotate/railtie'
|
5
5
|
|
@@ -7,17 +7,31 @@ module ActiveRecord
|
|
7
7
|
module Annotate
|
8
8
|
class << self
|
9
9
|
def annotate
|
10
|
-
|
10
|
+
processed_models = []
|
11
|
+
|
12
|
+
models.each do |table_name, file_paths_and_classes|
|
11
13
|
annotation = Dumper.dump(table_name)
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
file_paths_and_classes.each do |path, klass|
|
16
|
+
file = File.new(path)
|
17
|
+
file.annotate_with(annotation)
|
18
|
+
|
19
|
+
if file.changed?
|
20
|
+
file.write
|
21
|
+
processed_models << "#{klass} (#{file.relative_path})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
unless processed_models.empty?
|
27
|
+
puts 'Annotated models:'
|
28
|
+
processed_models.each do |model|
|
29
|
+
puts " * #{model}"
|
15
30
|
end
|
16
31
|
end
|
17
32
|
end
|
18
33
|
|
19
34
|
def models
|
20
|
-
models_dir = Rails.root.join('app/models')
|
21
35
|
files_mask = models_dir.join('**', '*.rb')
|
22
36
|
|
23
37
|
hash_with_arrays = Hash.new do |hash, key|
|
@@ -25,17 +39,30 @@ module ActiveRecord
|
|
25
39
|
end
|
26
40
|
|
27
41
|
Dir.glob(files_mask).each_with_object(hash_with_arrays) do |path, models|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
42
|
+
short_path = short_path_for(path)
|
43
|
+
next if short_path.starts_with?('concerns') # skip any app/models/concerns files
|
44
|
+
|
45
|
+
klass = class_name_for(short_path)
|
46
|
+
next unless klass < ActiveRecord::Base # collect only AR::Base descendants
|
32
47
|
|
33
|
-
|
34
|
-
klass = short_path.camelize.constantize
|
35
|
-
# collect only AR::Base descendants
|
36
|
-
models[klass.table_name] << path if klass < ActiveRecord::Base
|
48
|
+
models[klass.table_name] << [path, klass]
|
37
49
|
end
|
38
50
|
end
|
51
|
+
|
52
|
+
# .../app/models/car/hatchback.rb -> car/hatchback
|
53
|
+
def short_path_for(full_path)
|
54
|
+
full_path.sub(models_dir.to_s + '/', '').sub(/\.rb$/, '')
|
55
|
+
end
|
56
|
+
|
57
|
+
# car/hatchback -> Car::Hatchback
|
58
|
+
def class_name_for(short_path)
|
59
|
+
short_path.camelize.constantize
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def models_dir
|
64
|
+
Rails.root.join('app/models')
|
65
|
+
end
|
39
66
|
end
|
40
67
|
end
|
41
68
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Annotate
|
3
|
+
class File
|
4
|
+
attr_reader :path, :lines
|
5
|
+
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
8
|
+
@content = ::File.read(path)
|
9
|
+
@lines = @content.split(?\n)
|
10
|
+
end
|
11
|
+
|
12
|
+
def annotate_with(annotation)
|
13
|
+
if @lines.first =~ /^\s*#.*coding/
|
14
|
+
# encoding: utf-8 encountered on the first line
|
15
|
+
encoding_line = @lines.shift
|
16
|
+
end
|
17
|
+
|
18
|
+
while @lines.first.start_with?('#') || @lines.first.blank?
|
19
|
+
# throw out comments and empty lines
|
20
|
+
# in the beginning of the file (old annotation)
|
21
|
+
@lines.shift
|
22
|
+
end
|
23
|
+
|
24
|
+
@lines.unshift(*annotation, nil)
|
25
|
+
@lines.unshift(encoding_line) unless encoding_line.nil?
|
26
|
+
@lines.push(nil) # newline at the end of file
|
27
|
+
end
|
28
|
+
|
29
|
+
def write
|
30
|
+
new_file_content = @lines.join(?\n)
|
31
|
+
temp_path = "#{@path}.annotated"
|
32
|
+
|
33
|
+
::File.open(temp_path, 'w') do |temp_file|
|
34
|
+
temp_file.write(new_file_content)
|
35
|
+
end
|
36
|
+
|
37
|
+
::File.delete(@path)
|
38
|
+
::File.rename(temp_path, @path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def changed?
|
42
|
+
@lines.join(?\n) != @content
|
43
|
+
end
|
44
|
+
|
45
|
+
def relative_path
|
46
|
+
path.sub(/^#{Rails.root}\//, '')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/tasks/annotate.rake
CHANGED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRecord::Annotate::File do
|
4
|
+
let(:file_path) do
|
5
|
+
file = Tempfile.new('test_annotation')
|
6
|
+
File.open(file.path, 'w') do |tempfile|
|
7
|
+
tempfile.write(<<-FILE)
|
8
|
+
# encoding: utf-8
|
9
|
+
# create_table :users do |t|
|
10
|
+
# t.string :name
|
11
|
+
# t.integer :age
|
12
|
+
# end
|
13
|
+
|
14
|
+
class User < ActiveRecord::Base
|
15
|
+
has_many :posts
|
16
|
+
end
|
17
|
+
FILE
|
18
|
+
end
|
19
|
+
|
20
|
+
file.path
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:old_annotation) do
|
24
|
+
[
|
25
|
+
'# create_table :users do |t|',
|
26
|
+
'# t.string :name',
|
27
|
+
'# t.integer :age',
|
28
|
+
'# end'
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:new_annotation) do
|
33
|
+
[
|
34
|
+
'# create_table :users do |t|',
|
35
|
+
'# t.string :name',
|
36
|
+
'# t.integer :age, null: false, default: 0',
|
37
|
+
'# end'
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:expected_result) do
|
42
|
+
<<-FILE
|
43
|
+
# encoding: utf-8
|
44
|
+
# create_table :users do |t|
|
45
|
+
# t.string :name
|
46
|
+
# t.integer :age, null: false, default: 0
|
47
|
+
# end
|
48
|
+
|
49
|
+
class User < ActiveRecord::Base
|
50
|
+
has_many :posts
|
51
|
+
end
|
52
|
+
FILE
|
53
|
+
end
|
54
|
+
|
55
|
+
let(:file) { ActiveRecord::Annotate::File.new(file_path) }
|
56
|
+
|
57
|
+
describe "#annotate_with" do
|
58
|
+
it "changes the lines adding the new annotation" do
|
59
|
+
file.annotate_with(new_annotation)
|
60
|
+
|
61
|
+
processed_file_content = file.lines.join(?\n)
|
62
|
+
expect(processed_file_content).to eq(expected_result)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#changed?" do
|
67
|
+
context "with an old annotation" do
|
68
|
+
before(:each) do
|
69
|
+
file.annotate_with(old_annotation)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns false" do
|
73
|
+
expect(file).not_to be_changed
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "with a new annotation" do
|
78
|
+
before(:each) do
|
79
|
+
file.annotate_with(new_annotation)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "returns true" do
|
83
|
+
expect(file).to be_changed
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#write" do
|
89
|
+
before(:each) do
|
90
|
+
file.annotate_with(new_annotation)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "writes the new contents to file" do
|
94
|
+
file.write
|
95
|
+
|
96
|
+
new_file_contents = ::File.read(file.path)
|
97
|
+
expect(new_file_contents).to eq(expected_result)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#relative_path" do
|
102
|
+
before(:each) do
|
103
|
+
Rails.stub(:root).and_return('root')
|
104
|
+
file.stub(:path).and_return('root/namespace/path.rb')
|
105
|
+
end
|
106
|
+
|
107
|
+
it "returns a relative path" do
|
108
|
+
expect(file.relative_path).to eq('namespace/path.rb')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRecord::Annotate do
|
4
|
+
describe ".short_path_for" do
|
5
|
+
before(:each) do
|
6
|
+
subject.stub(:models_dir).and_return('dir')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "removes the root/app/models prefix and .rb suffix" do
|
10
|
+
short_path = subject.short_path_for('dir/namespace/model_name.rb')
|
11
|
+
expect(short_path).to eq('namespace/model_name')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ".class_name_for" do
|
16
|
+
it "finds the class by the short path" do
|
17
|
+
class_name = subject.class_name_for('active_record/annotate/file')
|
18
|
+
expect(class_name).to eq(ActiveRecord::Annotate::File)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,32 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record-annotate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Vsevolod Romashov
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
12
|
+
date: 2013-11-20 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: rails
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- - '>='
|
19
|
+
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: '3.2'
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- - '>='
|
27
|
+
- - ! '>='
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '3.2'
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: bundler
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,15 +46,81 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: rake
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
|
-
- - '>='
|
51
|
+
- - ! '>='
|
46
52
|
- !ruby/object:Gem::Version
|
47
53
|
version: '0'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
|
-
- - '>='
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: guard-rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: terminal-notifier-guard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: pry
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: awesome_print
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
53
124
|
- !ruby/object:Gem::Version
|
54
125
|
version: '0'
|
55
126
|
description: Adds a rake task which prepends each model file with an excerpt about
|
@@ -61,39 +132,55 @@ extensions: []
|
|
61
132
|
extra_rdoc_files: []
|
62
133
|
files:
|
63
134
|
- .gitignore
|
135
|
+
- .rspec
|
136
|
+
- .travis.yml
|
64
137
|
- Gemfile
|
138
|
+
- Guardfile
|
65
139
|
- LICENSE.txt
|
66
140
|
- README.md
|
67
141
|
- Rakefile
|
68
142
|
- active_record-annotate.gemspec
|
69
143
|
- lib/active_record/annotate.rb
|
70
144
|
- lib/active_record/annotate/dumper.rb
|
145
|
+
- lib/active_record/annotate/file.rb
|
71
146
|
- lib/active_record/annotate/railtie.rb
|
72
147
|
- lib/active_record/annotate/version.rb
|
73
|
-
- lib/active_record/annotate/writer.rb
|
74
148
|
- lib/tasks/annotate.rake
|
149
|
+
- spec/active_record/annotate/file_spec.rb
|
150
|
+
- spec/active_record/annotate_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
75
152
|
homepage: https://github.com/7even/active_record-annotate
|
76
153
|
licenses:
|
77
154
|
- MIT
|
78
|
-
metadata: {}
|
79
155
|
post_install_message:
|
80
156
|
rdoc_options: []
|
81
157
|
require_paths:
|
82
158
|
- lib
|
83
159
|
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
84
161
|
requirements:
|
85
|
-
- - '>='
|
162
|
+
- - ! '>='
|
86
163
|
- !ruby/object:Gem::Version
|
87
164
|
version: '0'
|
165
|
+
segments:
|
166
|
+
- 0
|
167
|
+
hash: 3616105738017822554
|
88
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
89
170
|
requirements:
|
90
|
-
- - '>='
|
171
|
+
- - ! '>='
|
91
172
|
- !ruby/object:Gem::Version
|
92
173
|
version: '0'
|
174
|
+
segments:
|
175
|
+
- 0
|
176
|
+
hash: 3616105738017822554
|
93
177
|
requirements: []
|
94
178
|
rubyforge_project:
|
95
|
-
rubygems_version:
|
179
|
+
rubygems_version: 1.8.23
|
96
180
|
signing_key:
|
97
|
-
specification_version:
|
181
|
+
specification_version: 3
|
98
182
|
summary: ActiveRecord models annotator based on rails' schema dumper
|
99
|
-
test_files:
|
183
|
+
test_files:
|
184
|
+
- spec/active_record/annotate/file_spec.rb
|
185
|
+
- spec/active_record/annotate_spec.rb
|
186
|
+
- spec/spec_helper.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 0d4d19dd9aa4aa53ab77fbb3e956de2a2ed0f400
|
4
|
-
data.tar.gz: 8ad179c14a5499aa39ae090b5d1a8e5ccaa6924e
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: b584d252701c53b7153e3977825e95722902edd654ef0eb1a5fd02a093ecdc00c2276b182b338252cba9f37727384ac7f0c8b0df128c3abacfaef9155862adaf
|
7
|
-
data.tar.gz: 1efd1c3364ae8dfe5f7758e6d7aba2d39b71f11e7a9fdb9544ab397260c35bbcaac90655d9dea94817bf848a9ce0d0f2835f885819a660cce503103280f12584
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Annotate
|
3
|
-
module Writer
|
4
|
-
class << self
|
5
|
-
def write(annotation, path)
|
6
|
-
new_file_content = assemble(annotation, path)
|
7
|
-
|
8
|
-
temp_path = "#{path}.annotated"
|
9
|
-
File.open(temp_path, 'w') do |temp_file|
|
10
|
-
temp_file.puts(new_file_content)
|
11
|
-
end
|
12
|
-
|
13
|
-
File.delete(path)
|
14
|
-
File.rename(temp_path, path)
|
15
|
-
end
|
16
|
-
|
17
|
-
def assemble(annotation, path)
|
18
|
-
lines = File.read(path).split("\n")
|
19
|
-
|
20
|
-
if lines.first =~ /^\s*#.*coding/
|
21
|
-
# encoding: utf-8 encountered on the first line
|
22
|
-
encoding_line = lines.shift
|
23
|
-
end
|
24
|
-
|
25
|
-
while lines.first.starts_with?('#') || lines.first.blank?
|
26
|
-
# throw out comments and empty lines in the beginning of the file (old annotation)
|
27
|
-
lines.shift
|
28
|
-
end
|
29
|
-
|
30
|
-
lines.unshift(*annotation, nil)
|
31
|
-
lines.unshift(encoding_line) unless encoding_line.nil?
|
32
|
-
|
33
|
-
lines.join("\n")
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|