The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .dockerignore
├── .document
├── .github
    ├── ISSUE_TEMPLATE.md
    ├── release-drafter.yml
    └── workflows
    │   ├── ci.yml
    │   ├── codeql-analysis.yml
    │   ├── release-drafter.yml
    │   └── release.yml
├── .gitignore
├── .overcommit.yml
├── .rbenv-gemsets
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── .tool-versions
├── .yardopts
├── AUTHORS.md
├── CHANGELOG.md
├── Gemfile
├── Guardfile
├── LICENSE.txt
├── README.md
├── RELEASE.md
├── Rakefile
├── annotate.gemspec
├── bin
    └── annotate
├── lib
    ├── annotate.rb
    ├── annotate
    │   ├── active_record_patch.rb
    │   ├── annotate_models.rb
    │   ├── annotate_models
    │   │   └── file_patterns.rb
    │   ├── annotate_routes.rb
    │   ├── annotate_routes
    │   │   ├── header_generator.rb
    │   │   └── helpers.rb
    │   ├── constants.rb
    │   ├── helpers.rb
    │   ├── parser.rb
    │   ├── tasks.rb
    │   └── version.rb
    ├── generators
    │   └── annotate
    │   │   ├── USAGE
    │   │   ├── install_generator.rb
    │   │   └── templates
    │   │       └── auto_annotate_models.rake
    └── tasks
    │   ├── annotate_models.rake
    │   ├── annotate_models_migrate.rake
    │   └── annotate_routes.rake
├── potato.md
└── spec
    ├── lib
        ├── annotate
        │   ├── annotate_models
        │   │   └── file_patterns_spec.rb
        │   ├── annotate_models_spec.rb
        │   ├── annotate_routes_spec.rb
        │   ├── helpers_spec.rb
        │   └── parser_spec.rb
        ├── annotate_spec.rb
        └── tasks
        │   ├── annotate_models_migrate_spec.rb
        │   └── annotate_models_spec.rb
    └── spec_helper.rb


/.dockerignore:
--------------------------------------------------------------------------------
1 | Dockerfile
2 | coverage
3 | 


--------------------------------------------------------------------------------
/.document:
--------------------------------------------------------------------------------
1 | spec/**/*.rb
2 | lib/**/*.rb
3 | -
4 | README.md
5 | CHANGELOG.md
6 | TODO.md
7 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
 1 | Describe your problem here.
 2 | 
 3 | ## Commands
 4 | 
 5 | ```
 6 | $ show your commands here.
 7 | ```
 8 | 
 9 | ## Version
10 | 
11 | - annotate version
12 | - rails version
13 | - ruby version
14 | 


--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | template: |
2 |   ## What's Changed
3 | 
4 |   $CHANGES
5 | 


--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
 1 | name: CI
 2 | on:
 3 |   pull_request:
 4 |     branches:
 5 |       - '*'
 6 | 
 7 |   push:
 8 |     branches:
 9 |       - '*'
10 | 
11 | jobs:
12 |   test:
13 |     runs-on: ubuntu-latest
14 |     strategy:
15 |       fail-fast: false
16 |       matrix:
17 |         ruby: ['2.7']
18 | 
19 |     steps:
20 |       - name: Checkout
21 |         uses: actions/checkout@v3
22 | 
23 |       - name: Setup Ruby
24 |         uses: ruby/setup-ruby@v1
25 |         with:
26 |           ruby-version: ${{ matrix.ruby }}
27 |           bundler-cache: true
28 | 
29 |       - name: Run Tests
30 |         run: bundle exec rspec
31 | 
32 |       - name: Rubocop
33 |         run: bundle exec rubocop
34 | 


--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
 1 | name: "CodeQL"
 2 | 
 3 | on:
 4 |   push:
 5 |     branches: [ "develop" ]
 6 |   pull_request:
 7 |     # The branches below must be a subset of the branches above
 8 |     branches: [ "develop" ]
 9 |   schedule:
10 |     - cron: '26 5 * * 4'
11 | 
12 | jobs:
13 |   analyze:
14 |     name: Analyze
15 |     runs-on: ubuntu-latest
16 |     permissions:
17 |       actions: read
18 |       contents: read
19 |       security-events: write
20 | 
21 |     strategy:
22 |       fail-fast: false
23 |       matrix:
24 |         language: [ 'ruby' ]
25 | 
26 |     steps:
27 |     - name: Checkout repository
28 |       uses: actions/checkout@v3
29 | 
30 |     # Initializes the CodeQL tools for scanning.
31 |     - name: Initialize CodeQL
32 |       uses: github/codeql-action/init@v2
33 |       with:
34 |         languages: ${{ matrix.language }}
35 |         # If you wish to specify custom queries, you can do so here or in a config file.
36 |         # By default, queries listed here will override any specified in a config file.
37 |         # Prefix the list here with "+" to use these queries and those in the config file.
38 | 
39 |         # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
40 |         # queries: security-extended,security-and-quality
41 | 
42 | 
43 |     # Autobuild attempts to build any compiled languages  (C/C++, C#, Go, or Java).
44 |     # If this step fails, then you should remove it and run the build manually (see below)
45 |     - name: Autobuild
46 |       uses: github/codeql-action/autobuild@v2
47 | 
48 |     # ℹ️ Command-line programs to run using the OS shell.
49 |     # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
50 | 
51 |     #   If the Autobuild fails above, remove it and uncomment the following three lines.
52 |     #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
53 | 
54 |     # - run: |
55 |     #     echo "Run, Build Application using script"
56 |     #     ./location_of_script_within_repo/buildscript.sh
57 | 
58 |     - name: Perform CodeQL Analysis
59 |       uses: github/codeql-action/analyze@v2
60 |       with:
61 |         category: "/language:${{matrix.language}}"
62 | 


--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
 1 | name: Release Drafter
 2 | 
 3 | on:
 4 |   push:
 5 |     branches:
 6 |       - develop
 7 | 
 8 | jobs:
 9 |   update_release_draft:
10 |     runs-on: ubuntu-latest
11 |     steps:
12 |       # Drafts your next Release notes as Pull Requests are merged into "develop"
13 |       - uses: release-drafter/release-drafter@v5
14 |         with:
15 |           config-name: release-drafter.yml
16 |         env:
17 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 | 


--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
 1 | name: Release
 2 | on:
 3 |   push:
 4 |     tags:
 5 |       - 'v*'
 6 |     branches:
 7 |       - 'release/*'
 8 | 
 9 | jobs:
10 |   release:
11 |     runs-on: ubuntu-latest
12 | 
13 |     steps:
14 |       - name: Checkout
15 |         uses: actions/checkout@v1
16 | 
17 |       - name: Setup Ruby
18 |         uses: ruby/setup-ruby@v1
19 |         with:
20 |           ruby-version: '2.6'
21 | 
22 |       - name: Bundle
23 |         run: |
24 |           gem update --system
25 |           gem update bundler
26 |           bundle install --jobs 4 --retry 3
27 | 
28 |       - name: Publish to RubyGems
29 |         run: |
30 |           mkdir -p $HOME/.gem
31 |           touch $HOME/.gem/credentials
32 |           chmod 0600 $HOME/.gem/credentials
33 |           printf -- "---\n:github: Bearer ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
34 |           gem build *.gemspec
35 |           gem push  *.gem
36 |         env:
37 |           GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }}
38 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | *.gem
 2 | .DS_Store
 3 | .bundle
 4 | .gems
 5 | .rbenv-version
 6 | .ruby-*
 7 | /.idea/
 8 | /.rbx
 9 | /.rvmrc
10 | /.yardoc/*
11 | /Gemfile.lock
12 | /coverage/*
13 | /dist
14 | /doc/*
15 | /pkg/*
16 | /spec/debug.log
17 | .byebug_history
18 | 


--------------------------------------------------------------------------------
/.overcommit.yml:
--------------------------------------------------------------------------------
 1 | # Use this file to configure the Overcommit hooks you wish to use. This will
 2 | # extend the default configuration defined in:
 3 | # https://github.com/brigade/overcommit/blob/master/config/default.yml
 4 | #
 5 | # At the topmost level of this YAML file is a key representing type of hook
 6 | # being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
 7 | # customize each hook, such as whether to only run it on certain files (via
 8 | # `include`), whether to only display output if it fails (via `quiet`), etc.
 9 | #
10 | # For a complete list of hooks, see:
11 | # https://github.com/brigade/overcommit/tree/master/lib/overcommit/hook
12 | #
13 | # For a complete list of options that you can use to customize hooks, see:
14 | # https://github.com/brigade/overcommit#configuration
15 | #
16 | # Uncomment the following lines to make the configuration take effect.
17 | 
18 | PreCommit:
19 |  RuboCop:
20 |    enabled: true
21 |    on_warn: fail # Treat all warnings as failures
22 | 
23 | PrePush:
24 |   RSpec:
25 |      enabled: true
26 |      on_warn: fail # Treat all warnings as failures
27 | #
28 | #  TrailingWhitespace:
29 | #    enabled: true
30 | #    exclude:
31 | #      - '**/db/structure.sql' # Ignore trailing whitespace in generated files
32 | #
33 | #PostCheckout:
34 | #  ALL: # Special hook name that customizes all hooks of this type
35 | #    quiet: true # Change all post-checkout hooks to only display output on failure
36 | #
37 | #  IndexTags:
38 | #    enabled: true # Generate a tags file with `ctags` each time HEAD changes
39 | 


--------------------------------------------------------------------------------
/.rbenv-gemsets:
--------------------------------------------------------------------------------
1 | .gems
2 | 


--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --colour
2 | --format documentation
3 | 


--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
 1 | inherit_from:
 2 |   - .rubocop_todo.yml
 3 | 
 4 | require:
 5 |   - rubocop-rake
 6 |   - rubocop-rspec
 7 | 
 8 | AllCops:
 9 |   Exclude:
10 |     - 'vendor/**/*'
11 |     - 'spec/fixtures/**/*'
12 |     - 'tmp/**/*'
13 |     - 'spec/integration/**/*'
14 |   NewCops: enable
15 | 
16 | Metrics/BlockLength:
17 |   Exclude:
18 |     - 'spec/**/*.rb'
19 | 


--------------------------------------------------------------------------------
/.rubocop_todo.yml:
--------------------------------------------------------------------------------
  1 | # This configuration was generated by
  2 | # `rubocop --auto-gen-config`
  3 | # on 2022-06-14 03:17:11 UTC using RuboCop version 1.12.1.
  4 | # The point is for the user to remove these configuration records
  5 | # one by one as the offenses are removed from the code base.
  6 | # Note that changes in the inspected code, or installation of new
  7 | # versions of RuboCop, may require this file to be generated again.
  8 | 
  9 | # Offense count: 1
 10 | # Cop supports --auto-correct.
 11 | # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
 12 | # Include: **/*.gemspec
 13 | Gemspec/OrderedDependencies:
 14 |   Exclude:
 15 |     - 'annotate.gemspec'
 16 | 
 17 | # Offense count: 1
 18 | # Configuration parameters: Include.
 19 | # Include: **/*.gemspec
 20 | Gemspec/RequiredRubyVersion:
 21 |   Exclude:
 22 |     - 'annotate.gemspec'
 23 | 
 24 | # Offense count: 1
 25 | # Cop supports --auto-correct.
 26 | # Configuration parameters: EnforcedStyleAlignWith.
 27 | # SupportedStylesAlignWith: either, start_of_block, start_of_line
 28 | Layout/BlockAlignment:
 29 |   Exclude:
 30 |     - 'lib/annotate/annotate_models.rb'
 31 | 
 32 | # Offense count: 9
 33 | # Cop supports --auto-correct.
 34 | Layout/EmptyLineAfterGuardClause:
 35 |   Exclude:
 36 |     - 'Rakefile'
 37 |     - 'lib/annotate.rb'
 38 |     - 'lib/annotate/annotate_models.rb'
 39 | 
 40 | # Offense count: 2
 41 | # Cop supports --auto-correct.
 42 | Layout/EmptyLineAfterMagicComment:
 43 |   Exclude:
 44 |     - 'annotate.gemspec'
 45 |     - 'spec/lib/annotate/annotate_models_spec.rb'
 46 | 
 47 | # Offense count: 3
 48 | # Cop supports --auto-correct.
 49 | # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
 50 | Layout/ExtraSpacing:
 51 |   Exclude:
 52 |     - 'Guardfile'
 53 |     - 'lib/annotate/annotate_models.rb'
 54 |     - 'lib/tasks/annotate_routes.rake'
 55 | 
 56 | # Offense count: 14
 57 | # Cop supports --auto-correct.
 58 | # Configuration parameters: IndentationWidth.
 59 | # SupportedStyles: special_inside_parentheses, consistent, align_brackets
 60 | Layout/FirstArrayElementIndentation:
 61 |   EnforcedStyle: consistent
 62 | 
 63 | # Offense count: 65
 64 | # Cop supports --auto-correct.
 65 | # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
 66 | # SupportedHashRocketStyles: key, separator, table
 67 | # SupportedColonStyles: key, separator, table
 68 | # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
 69 | Layout/HashAlignment:
 70 |   Exclude:
 71 |     - 'lib/generators/annotate/templates/auto_annotate_models.rake'
 72 |     - 'spec/lib/annotate/annotate_models_spec.rb'
 73 | 
 74 | # Offense count: 5
 75 | # Cop supports --auto-correct.
 76 | # Configuration parameters: EnforcedStyle, IndentationWidth.
 77 | # SupportedStyles: aligned, indented
 78 | Layout/MultilineOperationIndentation:
 79 |   Exclude:
 80 |     - 'lib/annotate/annotate_models.rb'
 81 | 
 82 | # Offense count: 1
 83 | # Cop supports --auto-correct.
 84 | # Configuration parameters: EnforcedStyle.
 85 | # SupportedStyles: space, no_space
 86 | Layout/SpaceAroundEqualsInParameterDefault:
 87 |   Exclude:
 88 |     - 'lib/annotate/annotate_routes.rb'
 89 | 
 90 | # Offense count: 4
 91 | # Cop supports --auto-correct.
 92 | # Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator.
 93 | # SupportedStylesForExponentOperator: space, no_space
 94 | Layout/SpaceAroundOperators:
 95 |   Exclude:
 96 |     - 'lib/annotate/annotate_models.rb'
 97 |     - 'lib/tasks/annotate_routes.rake'
 98 | 
 99 | # Offense count: 1
100 | # Cop supports --auto-correct.
101 | # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
102 | # SupportedStyles: space, no_space
103 | # SupportedStylesForEmptyBraces: space, no_space
104 | Layout/SpaceBeforeBlockBraces:
105 |   Exclude:
106 |     - 'lib/annotate/annotate_models.rb'
107 | 
108 | # Offense count: 1
109 | # Cop supports --auto-correct.
110 | Layout/SpaceBeforeComment:
111 |   Exclude:
112 |     - 'lib/annotate/annotate_models.rb'
113 | 
114 | # Offense count: 4
115 | # Cop supports --auto-correct.
116 | # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
117 | # SupportedStyles: space, no_space
118 | # SupportedStylesForEmptyBraces: space, no_space
119 | Layout/SpaceInsideBlockBraces:
120 |   Exclude:
121 |     - 'lib/annotate/annotate_models.rb'
122 | 
123 | # Offense count: 4
124 | # Cop supports --auto-correct.
125 | # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
126 | # SupportedStyles: space, no_space, compact
127 | # SupportedStylesForEmptyBraces: space, no_space
128 | Layout/SpaceInsideHashLiteralBraces:
129 |   Exclude:
130 |     - 'lib/tasks/annotate_models.rake'
131 | 
132 | # Offense count: 4
133 | # Cop supports --auto-correct.
134 | # Configuration parameters: EnforcedStyle.
135 | # SupportedStyles: space, no_space
136 | Layout/SpaceInsideParens:
137 |   Exclude:
138 |     - 'lib/annotate/annotate_models.rb'
139 | 
140 | # Offense count: 4
141 | # Cop supports --auto-correct.
142 | # Configuration parameters: EnforcedStyle.
143 | # SupportedStyles: space, no_space
144 | Layout/SpaceInsideStringInterpolation:
145 |   Exclude:
146 |     - 'lib/annotate/annotate_models.rb'
147 | 
148 | # Offense count: 2
149 | # Cop supports --auto-correct.
150 | # Configuration parameters: AllowInHeredoc.
151 | Layout/TrailingWhitespace:
152 |   Exclude:
153 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
154 | 
155 | # Offense count: 2
156 | # Configuration parameters: AllowSafeAssignment.
157 | Lint/AssignmentInCondition:
158 |   Exclude:
159 |     - 'lib/annotate/annotate_models.rb'
160 | 
161 | # Offense count: 7
162 | # Configuration parameters: AllowedMethods.
163 | # AllowedMethods: enums
164 | Lint/ConstantDefinitionInBlock:
165 |   Exclude:
166 |     - 'spec/lib/annotate/annotate_models_spec.rb'
167 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
168 | 
169 | # Offense count: 1
170 | # Cop supports --auto-correct.
171 | # Configuration parameters: EnforcedStyle.
172 | # SupportedStyles: runtime_error, standard_error
173 | Lint/InheritException:
174 |   Exclude:
175 |     - 'lib/annotate/annotate_models.rb'
176 | 
177 | # Offense count: 1
178 | # Configuration parameters: MaximumRangeSize.
179 | Lint/MissingCopEnableDirective:
180 |   Exclude:
181 |     - 'lib/annotate/annotate_models.rb'
182 | 
183 | # Offense count: 2
184 | Lint/RescueException:
185 |   Exclude:
186 |     - 'Rakefile'
187 | 
188 | # Offense count: 1
189 | Lint/ShadowingOuterLocalVariable:
190 |   Exclude:
191 |     - 'Rakefile'
192 | 
193 | # Offense count: 1
194 | # Configuration parameters: AllowComments, AllowNil.
195 | Lint/SuppressedException:
196 |   Exclude:
197 |     - 'bin/annotate'
198 | 
199 | # Offense count: 3
200 | # Cop supports --auto-correct.
201 | # Configuration parameters: EnforcedStyle.
202 | # SupportedStyles: strict, consistent
203 | Lint/SymbolConversion:
204 |   Exclude:
205 |     - 'lib/annotate/annotate_models.rb'
206 |     - 'spec/lib/annotate/annotate_models_spec.rb'
207 | 
208 | # Offense count: 20
209 | # Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
210 | Metrics/AbcSize:
211 |   Max: 155
212 | 
213 | # Offense count: 7
214 | # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
215 | # IgnoredMethods: refine
216 | Metrics/BlockLength:
217 |   Max: 53
218 | 
219 | # Offense count: 1
220 | # Configuration parameters: CountBlocks.
221 | Metrics/BlockNesting:
222 |   Max: 4
223 | 
224 | # Offense count: 16
225 | # Configuration parameters: IgnoredMethods.
226 | Metrics/CyclomaticComplexity:
227 |   Max: 30
228 | 
229 | # Offense count: 31
230 | # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
231 | Metrics/MethodLength:
232 |   Max: 40
233 | 
234 | # Offense count: 15
235 | # Configuration parameters: IgnoredMethods.
236 | Metrics/PerceivedComplexity:
237 |   Max: 33
238 | 
239 | # Offense count: 1
240 | Naming/AccessorMethodName:
241 |   Exclude:
242 |     - 'lib/annotate.rb'
243 | 
244 | # Offense count: 105
245 | # Configuration parameters: ForbiddenDelimiters.
246 | # ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$))
247 | Naming/HeredocDelimiterNaming:
248 |   Exclude:
249 |     - 'spec/lib/annotate/annotate_models_spec.rb'
250 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
251 | 
252 | # Offense count: 1
253 | # Configuration parameters: EnforcedStyleForLeadingUnderscores.
254 | # SupportedStylesForLeadingUnderscores: disallowed, required, optional
255 | Naming/MemoizedInstanceVariableName:
256 |   Exclude:
257 |     - 'lib/annotate/annotate_routes.rb'
258 | 
259 | # Offense count: 1
260 | # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
261 | # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to
262 | Naming/MethodParameterName:
263 |   Exclude:
264 |     - 'Rakefile'
265 | 
266 | # Offense count: 13
267 | # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers.
268 | # SupportedStyles: snake_case, normalcase, non_integer
269 | # AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339
270 | Naming/VariableNumber:
271 |   Exclude:
272 |     - 'spec/lib/annotate/annotate_models_spec.rb'
273 |     - 'spec/lib/annotate/helpers_spec.rb'
274 | 
275 | # Offense count: 1
276 | RSpec/BeforeAfterAll:
277 |   Exclude:
278 |     - 'spec/spec_helper.rb'
279 |     - 'spec/rails_helper.rb'
280 |     - 'spec/support/**/*.rb'
281 |     - 'spec/lib/annotate/annotate_models_spec.rb'
282 | 
283 | # Offense count: 46
284 | # Configuration parameters: Prefixes.
285 | # Prefixes: when, with, without
286 | RSpec/ContextWording:
287 |   Exclude:
288 |     - 'spec/lib/annotate/annotate_models_spec.rb'
289 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
290 |     - 'spec/lib/annotate/parser_spec.rb'
291 | 
292 | # Offense count: 1
293 | # Configuration parameters: IgnoredMetadata.
294 | RSpec/DescribeClass:
295 |   Exclude:
296 |     - 'spec/lib/tasks/annotate_models_migrate_spec.rb'
297 | 
298 | # Offense count: 149
299 | # Cop supports --auto-correct.
300 | # Configuration parameters: SkipBlocks, EnforcedStyle.
301 | # SupportedStyles: described_class, explicit
302 | RSpec/DescribedClass:
303 |   Exclude:
304 |     - 'spec/lib/annotate/annotate_models/file_patterns_spec.rb'
305 |     - 'spec/lib/annotate/annotate_models_spec.rb'
306 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
307 |     - 'spec/lib/annotate/parser_spec.rb'
308 |     - 'spec/lib/annotate_spec.rb'
309 | 
310 | # Offense count: 32
311 | # Cop supports --auto-correct.
312 | RSpec/EmptyLineAfterFinalLet:
313 |   Exclude:
314 |     - 'spec/lib/annotate/annotate_models_spec.rb'
315 |     - 'spec/lib/annotate/helpers_spec.rb'
316 |     - 'spec/lib/annotate/parser_spec.rb'
317 | 
318 | # Offense count: 1
319 | # Cop supports --auto-correct.
320 | RSpec/EmptyLineAfterSubject:
321 |   Exclude:
322 |     - 'spec/lib/annotate/helpers_spec.rb'
323 | 
324 | # Offense count: 14
325 | # Configuration parameters: Max.
326 | RSpec/ExampleLength:
327 |   Exclude:
328 |     - 'spec/lib/annotate/annotate_models/file_patterns_spec.rb'
329 |     - 'spec/lib/annotate/annotate_models_spec.rb'
330 |     - 'spec/lib/annotate/parser_spec.rb'
331 |     - 'spec/lib/tasks/annotate_models_migrate_spec.rb'
332 | 
333 | # Offense count: 22
334 | # Cop supports --auto-correct.
335 | # Configuration parameters: CustomTransform, IgnoredWords.
336 | RSpec/ExampleWording:
337 |   Exclude:
338 |     - 'spec/lib/annotate/annotate_models_spec.rb'
339 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
340 |     - 'spec/lib/tasks/annotate_models_migrate_spec.rb'
341 | 
342 | # Offense count: 9
343 | RSpec/ExpectInHook:
344 |   Exclude:
345 |     - 'spec/lib/annotate/annotate_models_spec.rb'
346 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
347 | 
348 | # Offense count: 10
349 | # Cop supports --auto-correct.
350 | # Configuration parameters: EnforcedStyle.
351 | # SupportedStyles: implicit, each, example
352 | RSpec/HookArgument:
353 |   Exclude:
354 |     - 'spec/lib/annotate/annotate_models_spec.rb'
355 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
356 |     - 'spec/lib/annotate/parser_spec.rb'
357 | 
358 | # Offense count: 1
359 | # Cop supports --auto-correct.
360 | RSpec/HooksBeforeExamples:
361 |   Exclude:
362 |     - 'spec/lib/annotate/annotate_models_spec.rb'
363 | 
364 | # Offense count: 78
365 | # Cop supports --auto-correct.
366 | # Configuration parameters: EnforcedStyle.
367 | # SupportedStyles: single_line_only, single_statement_only, disallow
368 | RSpec/ImplicitSubject:
369 |   Exclude:
370 |     - 'spec/lib/annotate/annotate_models/file_patterns_spec.rb'
371 |     - 'spec/lib/annotate/annotate_models_spec.rb'
372 |     - 'spec/lib/annotate/helpers_spec.rb'
373 | 
374 | # Offense count: 51
375 | # Configuration parameters: AssignmentOnly.
376 | RSpec/InstanceVariable:
377 |   Exclude:
378 |     - 'spec/lib/annotate/annotate_models_spec.rb'
379 | 
380 | # Offense count: 4
381 | # Cop supports --auto-correct.
382 | RSpec/LeadingSubject:
383 |   Exclude:
384 |     - 'spec/lib/annotate/annotate_models_spec.rb'
385 | 
386 | # Offense count: 9
387 | RSpec/LeakyConstantDeclaration:
388 |   Exclude:
389 |     - 'spec/lib/annotate/annotate_models_spec.rb'
390 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
391 | 
392 | # Offense count: 108
393 | # Configuration parameters: EnforcedStyle.
394 | # SupportedStyles: have_received, receive
395 | RSpec/MessageSpies:
396 |   Exclude:
397 |     - 'spec/lib/annotate/annotate_models_spec.rb'
398 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
399 |     - 'spec/lib/annotate/helpers_spec.rb'
400 |     - 'spec/lib/annotate/parser_spec.rb'
401 |     - 'spec/lib/tasks/annotate_models_migrate_spec.rb'
402 | 
403 | # Offense count: 36
404 | RSpec/MultipleExpectations:
405 |   Max: 4
406 | 
407 | # Offense count: 66
408 | # Configuration parameters: AllowSubject.
409 | RSpec/MultipleMemoizedHelpers:
410 |   Max: 9
411 | 
412 | # Offense count: 6
413 | # Configuration parameters: IgnoreSharedExamples.
414 | RSpec/NamedSubject:
415 |   Exclude:
416 |     - 'spec/lib/annotate/annotate_models_spec.rb'
417 |     - 'spec/lib/annotate/helpers_spec.rb'
418 |     - 'spec/lib/tasks/annotate_models_migrate_spec.rb'
419 | 
420 | # Offense count: 140
421 | RSpec/NestedGroups:
422 |   Max: 9
423 | 
424 | # Offense count: 2
425 | # Cop supports --auto-correct.
426 | # Configuration parameters: EnforcedStyle.
427 | # SupportedStyles: not_to, to_not
428 | RSpec/NotToNot:
429 |   Exclude:
430 |     - 'spec/lib/annotate/annotate_models_spec.rb'
431 |     - 'spec/lib/annotate/helpers_spec.rb'
432 | 
433 | # Offense count: 5
434 | RSpec/RepeatedExampleGroupBody:
435 |   Exclude:
436 |     - 'spec/lib/tasks/annotate_models_migrate_spec.rb'
437 | 
438 | # Offense count: 2
439 | RSpec/RepeatedExampleGroupDescription:
440 |   Exclude:
441 |     - 'spec/lib/annotate/annotate_models_spec.rb'
442 | 
443 | # Offense count: 3
444 | # Cop supports --auto-correct.
445 | # Configuration parameters: EnforcedStyle.
446 | # SupportedStyles: and_return, block
447 | RSpec/ReturnFromStub:
448 |   Exclude:
449 |     - 'spec/lib/annotate/annotate_models_spec.rb'
450 | 
451 | # Offense count: 7
452 | # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
453 | RSpec/VerifiedDoubles:
454 |   Exclude:
455 |     - 'spec/lib/annotate/annotate_models_spec.rb'
456 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
457 | 
458 | # Offense count: 16
459 | # Cop supports --auto-correct.
460 | Rake/Desc:
461 |   Exclude:
462 |     - 'Rakefile'
463 |     - 'lib/generators/annotate/templates/auto_annotate_models.rake'
464 |     - 'lib/tasks/annotate_models.rake'
465 |     - 'lib/tasks/annotate_routes.rake'
466 | 
467 | # Offense count: 6
468 | Rake/DuplicateTask:
469 |   Exclude:
470 |     - 'Rakefile'
471 |     - 'lib/tasks/annotate_models.rake'
472 |     - 'lib/tasks/annotate_routes.rake'
473 | 
474 | # Offense count: 3
475 | # Cop supports --auto-correct.
476 | # Configuration parameters: EnforcedStyle.
477 | # SupportedStyles: separated, grouped
478 | Style/AccessorGrouping:
479 |   Exclude:
480 |     - 'lib/annotate/annotate_models.rb'
481 | 
482 | # Offense count: 1
483 | # Cop supports --auto-correct.
484 | # Configuration parameters: AllowOnConstant.
485 | Style/CaseEquality:
486 |   Exclude:
487 |     - 'lib/annotate/annotate_models.rb'
488 | 
489 | # Offense count: 1
490 | # Cop supports --auto-correct.
491 | Style/CaseLikeIf:
492 |   Exclude:
493 |     - 'lib/annotate/annotate_routes.rb'
494 | 
495 | # Offense count: 2
496 | Style/ClassVars:
497 |   Exclude:
498 |     - 'lib/tasks/annotate_models_migrate.rake'
499 | 
500 | # Offense count: 1
501 | # Cop supports --auto-correct.
502 | # Configuration parameters: Keywords.
503 | # Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE
504 | Style/CommentAnnotation:
505 |   Exclude:
506 |     - 'lib/annotate/annotate_models.rb'
507 | 
508 | # Offense count: 1
509 | # Cop supports --auto-correct.
510 | Style/Dir:
511 |   Exclude:
512 |     - 'bin/annotate'
513 | 
514 | # Offense count: 10
515 | # Configuration parameters: AllowedConstants.
516 | Style/Documentation:
517 |   Exclude:
518 |     - 'spec/**/*'
519 |     - 'test/**/*'
520 |     - 'lib/annotate.rb'
521 |     - 'lib/annotate/active_record_patch.rb'
522 |     - 'lib/annotate/annotate_models.rb'
523 |     - 'lib/annotate/annotate_routes.rb'
524 |     - 'lib/annotate/annotate_routes/header_generator.rb'
525 |     - 'lib/annotate/annotate_routes/helpers.rb'
526 |     - 'lib/annotate/version.rb'
527 |     - 'lib/generators/annotate/install_generator.rb'
528 |     - 'lib/tasks/annotate_models_migrate.rake'
529 | 
530 | # Offense count: 2
531 | # Cop supports --auto-correct.
532 | Style/Encoding:
533 |   Exclude:
534 |     - 'annotate.gemspec'
535 |     - 'spec/lib/annotate/annotate_models_spec.rb'
536 | 
537 | # Offense count: 1
538 | # Cop supports --auto-correct.
539 | Style/ExpandPathArguments:
540 |   Exclude:
541 |     - 'annotate.gemspec'
542 | 
543 | # Offense count: 9
544 | # Cop supports --auto-correct.
545 | # Configuration parameters: EnforcedStyle.
546 | # SupportedStyles: format, sprintf, percent
547 | Style/FormatString:
548 |   Exclude:
549 |     - 'lib/annotate/annotate_models.rb'
550 | 
551 | # Offense count: 12
552 | # Configuration parameters: MaxUnannotatedPlaceholdersAllowed, IgnoredMethods.
553 | # SupportedStyles: annotated, template, unannotated
554 | Style/FormatStringToken:
555 |   EnforcedStyle: unannotated
556 | 
557 | # Offense count: 30
558 | # Cop supports --auto-correct.
559 | # Configuration parameters: EnforcedStyle.
560 | # SupportedStyles: always, always_true, never
561 | Style/FrozenStringLiteralComment:
562 |   Enabled: false
563 | 
564 | # Offense count: 1
565 | # Configuration parameters: MinBodyLength.
566 | Style/GuardClause:
567 |   Exclude:
568 |     - 'lib/tasks/annotate_models_migrate.rake'
569 | 
570 | # Offense count: 1
571 | # Cop supports --auto-correct.
572 | # Configuration parameters: AllowSplatArgument.
573 | Style/HashConversion:
574 |   Exclude:
575 |     - 'spec/lib/annotate/annotate_models_spec.rb'
576 | 
577 | # Offense count: 3
578 | # Cop supports --auto-correct.
579 | # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
580 | # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
581 | Style/HashSyntax:
582 |   Exclude:
583 |     - 'lib/tasks/annotate_routes.rake'
584 |     - 'spec/lib/annotate/annotate_models_spec.rb'
585 | 
586 | # Offense count: 7
587 | # Cop supports --auto-correct.
588 | Style/IfUnlessModifier:
589 |   Exclude:
590 |     - 'Rakefile'
591 |     - 'bin/annotate'
592 |     - 'lib/annotate/annotate_models.rb'
593 | 
594 | # Offense count: 1
595 | # Cop supports --auto-correct.
596 | # Configuration parameters: InverseMethods, InverseBlocks.
597 | Style/InverseMethods:
598 |   Exclude:
599 |     - 'Rakefile'
600 | 
601 | # Offense count: 1
602 | Style/MissingRespondToMissing:
603 |   Exclude:
604 |     - 'lib/annotate/active_record_patch.rb'
605 | 
606 | # Offense count: 1
607 | Style/MixinUsage:
608 |   Exclude:
609 |     - 'Rakefile'
610 | 
611 | # Offense count: 2
612 | Style/MultilineBlockChain:
613 |   Exclude:
614 |     - 'Rakefile'
615 |     - 'lib/annotate/annotate_models.rb'
616 | 
617 | # Offense count: 2
618 | # Cop supports --auto-correct.
619 | Style/MultilineIfModifier:
620 |   Exclude:
621 |     - 'spec/lib/annotate/annotate_models_spec.rb'
622 |     - 'spec/lib/annotate/annotate_routes_spec.rb'
623 | 
624 | # Offense count: 2
625 | # Cop supports --auto-correct.
626 | Style/NegatedIfElseCondition:
627 |   Exclude:
628 |     - 'lib/annotate.rb'
629 | 
630 | # Offense count: 1
631 | # Cop supports --auto-correct.
632 | # Configuration parameters: AllowedMethods.
633 | # AllowedMethods: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with
634 | Style/NestedParenthesizedCalls:
635 |   Exclude:
636 |     - 'bin/annotate'
637 | 
638 | # Offense count: 3
639 | # Cop supports --auto-correct.
640 | # Configuration parameters: EnforcedStyle, IgnoredMethods.
641 | # SupportedStyles: predicate, comparison
642 | Style/NumericPredicate:
643 |   Exclude:
644 |     - 'spec/**/*'
645 |     - 'lib/annotate.rb'
646 |     - 'lib/annotate/annotate_models.rb'
647 | 
648 | # Offense count: 13
649 | # Cop supports --auto-correct.
650 | # Configuration parameters: PreferredDelimiters.
651 | Style/PercentLiteralDelimiters:
652 |   Exclude:
653 |     - 'annotate.gemspec'
654 |     - 'lib/annotate/annotate_models.rb'
655 |     - 'lib/annotate/annotate_routes.rb'
656 |     - 'lib/tasks/annotate_models_migrate.rake'
657 |     - 'spec/lib/annotate/annotate_models_spec.rb'
658 |     - 'spec/lib/tasks/annotate_models_migrate_spec.rb'
659 | 
660 | # Offense count: 1
661 | # Cop supports --auto-correct.
662 | # Configuration parameters: EnforcedStyle, AllowedCompactTypes.
663 | # SupportedStyles: compact, exploded
664 | Style/RaiseArgs:
665 |   Exclude:
666 |     - 'lib/annotate/annotate_models.rb'
667 | 
668 | # Offense count: 2
669 | # Cop supports --auto-correct.
670 | # Configuration parameters: Methods.
671 | Style/RedundantArgument:
672 |   Exclude:
673 |     - 'lib/annotate/annotate_routes/header_generator.rb'
674 | 
675 | # Offense count: 3
676 | # Cop supports --auto-correct.
677 | Style/RedundantBegin:
678 |   Exclude:
679 |     - 'lib/annotate/annotate_models.rb'
680 |     - 'spec/lib/annotate/annotate_models_spec.rb'
681 | 
682 | # Offense count: 1
683 | # Cop supports --auto-correct.
684 | Style/RedundantParentheses:
685 |   Exclude:
686 |     - 'lib/annotate/annotate_models.rb'
687 | 
688 | # Offense count: 2
689 | # Cop supports --auto-correct.
690 | Style/RedundantPercentQ:
691 |   Exclude:
692 |     - 'annotate.gemspec'
693 | 
694 | # Offense count: 3
695 | # Cop supports --auto-correct.
696 | Style/RedundantRegexpCharacterClass:
697 |   Exclude:
698 |     - 'lib/annotate/annotate_models.rb'
699 | 
700 | # Offense count: 3
701 | # Cop supports --auto-correct.
702 | Style/RedundantRegexpEscape:
703 |   Exclude:
704 |     - 'lib/annotate/annotate_models.rb'
705 |     - 'lib/annotate/annotate_routes/header_generator.rb'
706 | 
707 | # Offense count: 1
708 | # Cop supports --auto-correct.
709 | # Configuration parameters: AllowMultipleReturnValues.
710 | Style/RedundantReturn:
711 |   Exclude:
712 |     - 'lib/annotate/annotate_routes/helpers.rb'
713 | 
714 | # Offense count: 2
715 | # Cop supports --auto-correct.
716 | Style/RedundantSelf:
717 |   Exclude:
718 |     - 'lib/tasks/annotate_models_migrate.rake'
719 | 
720 | # Offense count: 12
721 | # Cop supports --auto-correct.
722 | # Configuration parameters: EnforcedStyle, AllowInnerSlashes.
723 | # SupportedStyles: slashes, percent_r, mixed
724 | Style/RegexpLiteral:
725 |   Exclude:
726 |     - 'Rakefile'
727 |     - 'lib/annotate/annotate_models.rb'
728 | 
729 | # Offense count: 1
730 | # Cop supports --auto-correct.
731 | Style/RescueModifier:
732 |   Exclude:
733 |     - 'lib/annotate/annotate_models.rb'
734 | 
735 | # Offense count: 1
736 | # Cop supports --auto-correct.
737 | # Configuration parameters: EnforcedStyle.
738 | # SupportedStyles: implicit, explicit
739 | Style/RescueStandardError:
740 |   Exclude:
741 |     - 'lib/annotate.rb'
742 | 
743 | # Offense count: 2
744 | # Cop supports --auto-correct.
745 | # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods.
746 | # AllowedMethods: present?, blank?, presence, try, try!
747 | Style/SafeNavigation:
748 |   Exclude:
749 |     - 'lib/annotate/annotate_models.rb'
750 | 
751 | # Offense count: 3
752 | # Cop supports --auto-correct.
753 | Style/SlicingWithRange:
754 |   Exclude:
755 |     - 'lib/annotate/annotate_models.rb'
756 |     - 'lib/annotate/annotate_routes/header_generator.rb'
757 | 
758 | # Offense count: 15
759 | # Cop supports --auto-correct.
760 | Style/StderrPuts:
761 |   Exclude:
762 |     - 'Rakefile'
763 |     - 'lib/annotate.rb'
764 |     - 'lib/annotate/annotate_models.rb'
765 | 
766 | # Offense count: 13
767 | # Cop supports --auto-correct.
768 | Style/StringConcatenation:
769 |   Exclude:
770 |     - 'lib/annotate/annotate_models.rb'
771 | 
772 | # Offense count: 57
773 | # Cop supports --auto-correct.
774 | # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
775 | # SupportedStyles: single_quotes, double_quotes
776 | Style/StringLiterals:
777 |   Exclude:
778 |     - 'annotate.gemspec'
779 |     - 'lib/annotate/annotate_models.rb'
780 |     - 'lib/annotate/parser.rb'
781 |     - 'lib/tasks/annotate_models_migrate.rake'
782 |     - 'lib/tasks/annotate_routes.rake'
783 |     - 'spec/lib/annotate/annotate_models_spec.rb'
784 |     - 'spec/lib/annotate/parser_spec.rb'
785 | 
786 | # Offense count: 2
787 | # Cop supports --auto-correct.
788 | # Configuration parameters: EnforcedStyle.
789 | # SupportedStyles: single_quotes, double_quotes
790 | Style/StringLiteralsInInterpolation:
791 |   Exclude:
792 |     - 'lib/annotate/annotate_models.rb'
793 | 
794 | # Offense count: 8
795 | # Cop supports --auto-correct.
796 | # Configuration parameters: MinSize.
797 | # SupportedStyles: percent, brackets
798 | Style/SymbolArray:
799 |   EnforcedStyle: brackets
800 | 
801 | # Offense count: 1
802 | # Cop supports --auto-correct.
803 | Style/SymbolLiteral:
804 |   Exclude:
805 |     - 'spec/lib/annotate/annotate_models_spec.rb'
806 | 
807 | # Offense count: 3
808 | # Cop supports --auto-correct.
809 | # Configuration parameters: EnforcedStyleForMultiline.
810 | # SupportedStylesForMultiline: comma, consistent_comma, no_comma
811 | Style/TrailingCommaInArrayLiteral:
812 |   Exclude:
813 |     - 'spec/lib/annotate/annotate_models_spec.rb'
814 | 
815 | # Offense count: 52
816 | # Cop supports --auto-correct.
817 | # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
818 | # URISchemes: http, https
819 | Layout/LineLength:
820 |   Max: 264
821 | 


--------------------------------------------------------------------------------
/.tool-versions:
--------------------------------------------------------------------------------
1 | ruby 2.7.3
2 | 


--------------------------------------------------------------------------------
/.yardopts:
--------------------------------------------------------------------------------
1 | --no-private
2 | 


--------------------------------------------------------------------------------
/AUTHORS.md:
--------------------------------------------------------------------------------
 1 | ## Authors
 2 | 
 3 | - Original code by: Dave Thomas -- Pragmatic Programmers, LLC <http://agilewebdevelopment.com/plugins/annotate_models>
 4 | - Overhauled by: Alex Chaffee <http://alexch.github.com> alex@stinky.com
 5 | - Gemmed by: Cuong Tran <http://github.com/ctran> ctran@pragmaquest.com
 6 | - Maintained by: Alex Chaffee and Cuong Tran
 7 | - Homepage: http://github.com/ctran/annotate_models
 8 | 
 9 | ### With help from:
10 | 
11 | - Jack Danger - http://github.com/JackDanger
12 | - Michael Bumann - http://github.com/bumi
13 | - Henrik Nyh - http://github.com/henrik
14 | - Marcos Piccinini - http://github.com/nofxx
15 | - Neal Clark - http://github.com/nclark
16 | - Jacqui Maher - http://github.com/jacqui
17 | - Nick Plante - http://github.com/zapnap - http://blog.zerosum.org
18 | - Pedro Visintin - http://github.com/peterpunk - http://www.pedrovisintin.com
19 | - Bob Potter - http://github.com/bpot
20 | - Gavin Montague - http://github.com/govan
21 | - Alexander Semyonov - http://github.com/rotuka
22 | - Nathan Brazil - http://github.com/bitaxis
23 | - Ian Duggan http://github.com/ijcd
24 | - Jon Frisby http://github.com/mrjoy
25 | - Tsutomu Kuroda
26 | - Kevin Moore
27 | - Philip Hallstrom
28 | - Brent Greeff
29 | - Paul Alexander
30 | - Dmitry Lihachev
31 | - qichunren
32 | - Guillermo Guerrero - http://github.com/ryanfox1985
33 | 
34 | and many others that I may have forgotten to add.
35 | 


--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
  1 | Please see https://github.com/ctran/annotate_models/releases for changes between releases.
  2 | 
  3 | ## 3.1.1
  4 | Changes
  5 | - Bump required ruby version to >= 2.4 [#772](https://github.com/ctran/annotate_models/pull/772)
  6 | - [Revert #677] Fix column default annotations [#768](https://github.com/ctran/annotate_models/pull/768)
  7 | 
  8 | Project Improvements
  9 | - Refactor by adding AnnotateRoutes::Helpers [#770](https://github.com/ctran/annotate_models/pull/770) 
 10 | - Bump puma from 4.3.1 to 4.3.3 in /spec/integration/rails_6.0.2.1 [#771](https://github.com/ctran/annotate_models/pull/771)
 11 | - Bump puma from 3.12.2 to 4.3.3 in /spec/integration/rails_5.2.4.1 [#769](https://github.com/ctran/annotate_models/pull/769)
 12 | - Bump nokogiri from 1.10.7 to 1.10.8 in /spec/integration/rails_5.2.4.1 [#766](https://github.com/ctran/annotate_models/pull/766)
 13 | - Bump nokogiri from 1.10.7 to 1.10.8 in /spec/integration/rails_6.0.2.1 [#765](https://github.com/ctran/annotate_models/pull/765)
 14 | - Refactor test cases of AnnotateRoutes [#760](https://github.com/ctran/annotate_models/pull/760)
 15 | - Rename FactoryGirl -> FactoryBot comment [#759](https://github.com/ctran/annotate_models/pull/759)
 16 | 
 17 | ## 3.1.0
 18 | Changes
 19 | - Fix new lines after comments for rubocop compatibility [#757](https://github.com/ctran/annotate_models/pull/757)
 20 | - Fix messages from AnnotateRoutes [#737](https://github.com/ctran/annotate_models/pull/737)
 21 | - Support YARD notation [#724](https://github.com/ctran/annotate_models/pull/724)
 22 | - Refactor AnnotateRoutes.routes_file_exist? [#716](https://github.com/ctran/annotate_models/pull/716)
 23 | - Refactor namespace Annotate [#719](https://github.com/ctran/annotate_models/pull/719)
 24 | - Add columns managed by Globalize gem [#602](https://github.com/ctran/annotate_models/pull/602)
 25 | 
 26 | Bug Fixes
 27 | - Fix additional_file_patterns parsing [#756](https://github.com/ctran/annotate_models/pull/756)
 28 | - Fix typo in README [#752](https://github.com/ctran/annotate_models/pull/752)
 29 | - Fix bin/annotate NoMethodError [#745](https://github.com/ctran/annotate_models/pull/745)
 30 | - Fix README for YARD format [#740](https://github.com/ctran/annotate_models/pull/740)
 31 | - Fix constant names that were not renamed in #721 [#739](https://github.com/ctran/annotate_models/pull/739)
 32 | - Replace soft-deprecated constant `HashWithIndifferentAccess` to `ActiveSupport::HashWithIndifferentAccess` [#699](https://github.com/ctran/annotate_models/pull/699)
 33 | - [Fix #570](https://github.com/ctran/annotate_models/issues/570) Change of foreign key should be considered as a column change
 34 | - [Fix #430](https://github.com/ctran/annotate_models/issues/430) Handle columns from activerecord-postgis-adapter [#694](https://github.com/ctran/annotate_models/pull/694)
 35 | - Add ActiveAdmin option to template [#693](https://github.com/ctran/annotate_models/pull/693)
 36 | - Fix foreign key issue with Rails 6 and Sqlite3 [#695](https://github.com/ctran/annotate_models/pull/695)
 37 | - Fix Serializers Test Directory [#625](https://github.com/ctran/annotate_models/pull/625)
 38 | - [Fix #624](https://github.com/ctran/annotate_models/issues/624) Correct default values for columns when ActiveRecord::Enum is used [#677](https://github.com/ctran/annotate_models/pull/677)
 39 | - [Fix #675](https://github.com/ctran/annotate_models/issues/675) Correct indentation for double-byte characters [#676](https://github.com/ctran/annotate_models/pull/676)
 40 | - FIX: Ensure only one line is around the annotation [#669](https://github.com/ctran/annotate_models/pull/669)
 41 | - Fix shifted when format_markdown option enabled and used non-ascii [#650](https://github.com/ctran/annotate_models/pull/650)
 42 | 
 43 | Project improvements
 44 | - Refactor RSpec for AnnotateModels - structuralize test cases [#755](https://github.com/ctran/annotate_models/pull/755)
 45 | - Refactor test cases of AnnotateRoutes as for Rake versions [#754](https://github.com/ctran/annotate_models/pull/754)
 46 | - Add integration tests to project [#747](https://github.com/ctran/annotate_models/pull/747)
 47 | - Refactor test cases for AnnotateRoutes.remove_annotations [#748](https://github.com/ctran/annotate_models/pull/748)
 48 | - Refactor RSpec for AnnotateModels - with Globalize gem [#749](https://github.com/ctran/annotate_models/pull/749)
 49 | - Fixed CHANGELOG.md to add link to each PR [#751](https://github.com/ctran/annotate_models/pull/751)
 50 | - Delete integration test fixtures [#746](https://github.com/ctran/annotate_models/pull/746)
 51 | - Remove remaining integration test files [#744](https://github.com/ctran/annotate_models/pull/744)
 52 | - Remove unworking integration tests [#725](https://github.com/ctran/annotate_models/pull/725)
 53 | - Refactor Annotate::Parser [#742](https://github.com/ctran/annotate_models/pull/742)
 54 | - Refactor RSpec for AnnotateModels (4) - AnnotateModels.get_schema_info (without custom options) [#735](https://github.com/ctran/annotate_models/pull/735)
 55 | - Refactor RSpec for AnnotateRoutes (1) [#736](https://github.com/ctran/annotate_models/pull/736)
 56 | - Refactor AnnotateRoutes.rewrite_contents [#734](https://github.com/ctran/annotate_models/pull/734)
 57 | - AnnotateModels.get_schema_info (with custom options) [#732](https://github.com/ctran/annotate_models/pull/732)
 58 | - Fix typo in RSpec of AnnotateModels [#731](https://github.com/ctran/annotate_models/pull/731)
 59 | - Remove AnnotateRoutes.rewrite_contents_with_header [#730](https://github.com/ctran/annotate_models/pull/730)
 60 | - Refactor AnnotateRoutes.annotate_routes and .rewrite_contents_with_header [#729](https://github.com/ctran/annotate_models/pull/729)
 61 | - Refactor AnnotateModels::Parser [#728](https://github.com/ctran/annotate_models/pull/728)
 62 | - Remove invalid document of AnnotateRoutes.rewrite_contents [#727](https://github.com/ctran/annotate_models/pull/727)
 63 | - Refactor RSpec for AnnotateModels (1) [#726](https://github.com/ctran/annotate_models/pull/726)
 64 | - Refactor AnnotateModels::Helpers [#723](https://github.com/ctran/annotate_models/pull/723)
 65 | - Refactor AnnotateRoutes.remove_annotations [#715](https://github.com/ctran/annotate_models/pull/715)
 66 | - Fix AnnotateRoutes.extract_magic_comments_from_array [#712](https://github.com/ctran/annotate_models/pull/712)
 67 | - Rename FactoryGirl to FactoryBot [#721](https://github.com/ctran/annotate_models/pull/721)
 68 | - Refactor AnnotateRoutes.header [#714](https://github.com/ctran/annotate_models/pull/714)
 69 | - Freeze constant AnnotateRoutes::HEADER_ROW [#713](https://github.com/ctran/annotate_models/pull/713)
 70 | - Add constants MAGIC_COMMENT_MATCHER [#711](https://github.com/ctran/annotate_models/pull/711)
 71 | - Rename method and variable of AnnotateRoutes for readability [#709](https://github.com/ctran/annotate_models/pull/709)
 72 | - Refactor lib/annotate.rb [#707](https://github.com/ctran/annotate_models/pull/707)
 73 | - Delete TODO.md [#700](https://github.com/ctran/annotate_models/pull/700)
 74 | - Tidy README [#701](https://github.com/ctran/annotate_models/pull/701)
 75 | - Convert documentation files to Markdown [#697](https://github.com/ctran/annotate_models/pull/697)
 76 | - Upgrade and fix CI [#698](https://github.com/ctran/annotate_models/pull/698)
 77 | - Add upgrade instructions to README [#687](https://github.com/ctran/annotate_models/pull/687)
 78 | - Fix Github release action [#682](https://github.com/ctran/annotate_models/pull/682)
 79 | 
 80 | ## 3.0.3
 81 | - Use a less error-prone way of specifying gem files [#662](https://github.com/ctran/annotate_models/pull/662)
 82 | - Update rake requirement from `>= 10.4, < 13.0` to `>= 10.4, < 14.0` [#659](https://github.com/ctran/annotate_models/pull/659)
 83 | - Bump nokogiri from 1.6.6.2 to 1.10.4 in /spec/integration/rails_4.2.0 [#655](https://github.com/ctran/annotate_models/pull/655)
 84 | - Default annotate models to true in config generated by `rails g annotate:install` [#671](https://github.com/ctran/annotate_models/pull/671)
 85 | - Bump loofah from 2.3.0 to 2.3.1 in /spec/integration/rails_4.2.0 [#681](https://github.com/ctran/annotate_models/pull/681)
 86 | 
 87 | ## 3.0.2
 88 | - Fixes `LoadError` due to gemspec not referencing `parser.rb`, issue [#657](https://github.com/ctran/annotate_models/issues/657) [#660](https://github.com/ctran/annotate_models/pull/660)
 89 | - Changes `--additional_file_patterns` to use dashes `--additional-file-patterns` for consistency [#649](https://github.com/ctran/annotate_models/pull/649)
 90 | - Refactor: moving constants into `constants.rb` [#653](https://github.com/ctran/annotate_models/pull/653)
 91 | 
 92 | ## 3.0.1
 93 | - Skipped as an official release, used the 3.0.1 patch for setting up Github Actions [#619](https://github.com/ctran/annotate_models/pull/619)
 94 | 
 95 | ## 3.0.0
 96 | - **Breaking:** when option `models` is not set - models will not be annotated by default.
 97 | 
 98 |   Add `'models'=>'true'` to your config manually or use `--models` option if using CLI.
 99 | 
100 | - Added `--models` CLI option fixing issue [#563](https://github.com/ctran/annotate_models/issues/563) [#647](https://github.com/ctran/annotate_models/pull/647)
101 | - Added `--additional_file_patterns` option for additional file patterns [#633](https://github.com/ctran/annotate_models/pull/633) [#636](https://github.com/ctran/annotate_models/pull/636) [#637](https://github.com/ctran/annotate_models/pull/637)
102 | - Refactored CLI parser [#646](https://github.com/ctran/annotate_models/pull/646)
103 | - Fixed `BigDecimal.new` deprecation warning [#634](https://github.com/ctran/annotate_models/pull/634)
104 | - Fixed annotations for columns with long data types [#622](https://github.com/ctran/annotate_models/pull/622)
105 | - Made methods private in AnnotateRoutes [#598](https://github.com/ctran/annotate_models/pull/598)
106 | 
107 | See https://github.com/ctran/annotate_models/releases/tag/v3.0.0
108 | 
109 | ## 2.7.5
110 | See https://github.com/ctran/annotate_models/releases/tag/v2.7.5
111 | 
112 | ## 2.7.3
113 | See https://github.com/ctran/annotate_models/releases/tag/v2.7.3
114 | 
115 | ## 2.7.2
116 | See https://github.com/ctran/annotate_models/releases/tag/v2.7.2
117 | 
118 | ## 2.7.1
119 | See https://github.com/ctran/annotate_models/releases/tag/v2.7.1
120 | 
121 | ## 2.7.0
122 | See https://github.com/ctran/annotate_models/releases/tag/v2.7.0
123 | 
124 | ## 2.6.9
125 | - Support foreigh key [#241](https://github.com/ctran/annotate_models/pull/241)
126 | - Check if model has skip tag in annotate_model_file [#167](https://github.com/ctran/annotate_models/pull/167)
127 | - Fix issue where serializer-related flags weren't being honored [#246](https://github.com/ctran/annotate_models/issues/246)
128 | - Prefer SQL column type over normalized AR type [#231](https://github.com/ctran/annotate_models/issues/231)
129 | 
130 | ## 2.6.8
131 | - Nothing annotated unless `options[:model_dir]` is specified, [#234](https://github.com/ctran/annotate_models/pull/234)
132 | 
133 | ## 2.6.7
134 | - Nothing annotated unless `options[:model_dir]` is specified, [#234](https://github.com/ctran/annotate_models/pull/234)
135 | 
136 | ## 2.6.6
137 | - Makes it possible to wrap annotations, [#225](https://github.com/ctran/annotate_models/pull/225)
138 | - Fix single model generation, [#214](https://github.com/ctran/annotate_models/pull/214)
139 | - Fix default value for Rails 4.2, [#212](https://github.com/ctran/annotate_models/issues/212)
140 | - Don't crash on inherited models in subdirectories, [#232](https://github.com/ctran/annotate_models/issues/232)
141 | - Process model_dir in rake task, [#197](https://github.com/ctran/annotate_models/pull/197)
142 | 
143 | ## 2.6.4
144 | - Skip "models/concerns", [#194](https://github.com/ctran/annotate_models/pull/194)
145 | - Fix [#173](https://github.com/ctran/annotate_models/issues/173) where annotate says "Nothing to annotate" in rails 4.2
146 | - Display an error message if not run from the root of the project, [#186](https://github.com/ctran/annotate_models/pull/186)
147 | - Support rails 4.0 new default test directory, [#182](https://github.com/ctran/annotate_models/issues/182)
148 | - Add an option to show timestamp in routes "-timestamp", [#136](https://github.com/ctran/annotate_models/issues/136)
149 | - Skip plain ruby objects if they have the same class name as an ActiveRecord object, [#121](https://github.com/ctran/annotate_models/issues/121)
150 | 
151 | ## 2.6.3
152 | - Fix bug of annotate position in routes [#158](https://github.com/ctran/annotate_models/issues/158)
153 | 
154 | ## 2.6.2
155 | - Retain the current annotate block unless --force is specified
156 | - Always load models, since they may not be autoloaded by Rails
157 | - The pg array type is now detected (see [#158](https://github.com/ctran/annotate_models/pull/158))
158 | 
159 | ## 2.6.0.beta2
160 | - support for composite_primary_keys (garysweaver)
161 | - bug fix for annotate_one_file (vlado)
162 | 
163 | 
164 | ## 2.6.0.beta1
165 | 
166 | - It's now possible to use Annotate in standalone ActiveRecord (non-Rails) projects again.
167 | - Adding note that Markdown is actually MultiMarkdown, and recommending the use
168 |   of the `kramdown` engine for parsing it.
169 | - Improved Markdown formatting considerably.
170 | - Bugfix: Needed to use inline-code tag for column and table names,
171 |     otherwise underscores would cause havok with the formatting.
172 | - Bugfix: Markdown syntax was incorrect
173 |     (can't have trailing spaces before the closing marker for an emphasis tag).
174 | - Bugfix: Remove-annotations wasn't properly finding test/spec files,
175 |     and wasn't even looking for FactoryGirl factories under the new naming convention.
176 | - Bugfix: Load the Rakefile from the current directory, not the first
177 |     Rakefile in our load path.
178 | - Added support for new FactoryGirl naming convention.
179 | - Fix behavior of route annotations in newer versions of Rake that don't
180 |     spit out the CWD as their first line of output.
181 | - Overhauled integration testing system to be much easier to work with,
182 |     better compartmentalized, and so forth -- at the cost that you must be
183 |     using RVM to utilize it.  (It'll spit out appropriate pending messages if
184 |     you don't.) Also includes a mode for "tinkering" by hand with a scenario,
185 |     and won't let you run it through rspect if the repo is in a dirty state. 
186 |     Added appropriate rake tasks to help with all of this.
187 | - Routes can now be appended, pre-pended, or removed -- and do sane things in all cases.
188 | - Expose all `position_*` variables as CLI params.
189 | - Make `ENV ['position']` work as a default for all the `ENV ['position_*']` variables.
190 | - Make rake tasks more resilient to unusual circumstances / code loading behavior.
191 | - Resolve annotate vs. annotate_models ambiguity once and for all by
192 |   settling on `annotate_models` *and* `annotate_routes`.  This avoids a name
193 |   collision with RMagick while not needlessly overloading the term.
194 | - Fixed that schema kept prepending additional newlines
195 | - Updates to make annotate smarter about when to touch a model
196 | - Recognize column+type, and don't change a file unless the column+type
197 |   combination of the new schema are different than that of the old (i.e.,
198 |   don't regenerate if columns happen to be in a different order. That's just
199 |   how life is sometimes)
200 | - Change annotate to use options hash instead of ENV.
201 | 
202 | 
203 | ## 2.5.0
204 | 
205 | - Works better with Rails 3
206 | - Bugfix: schema kept prepending additional newlines
207 | - Updates to make annotate smarter about when to touch a model
208 | - Recognize column+type, and don't change a file unless the column+type
209 |   combination of the new schema are different than that of the old (i.e.,
210 |   don't regenerate if columns happen to be in a different order. That's just
211 |   how life is sometimes.)
212 | - Grab old specification even if it has `\r\n` as line endings rather than pure `\n`s
213 | - Various warning and specification fixes
214 | - Fix "no such file to load -- annotate/annotate_models (MissingSourceFile)"
215 |   error (require statements in tasks now use full path to lib files)
216 | - warn about macros, to mitigate when we're included during a production
217 |   run, not just a rakefile run -- possibly at the expense of too much noise
218 | - Adding rake as a runtime dependency
219 | - If the schema is already in the model file, it will be replaced into the same location.
220 |   If it didn't previously exist, it'll be placed according to the "position", as before.
221 | - Allow task loading from Rakefile for gems (plugin installation already auto-detects).
222 | - Add skip_on_db_migrate option as well for people that don't want it
223 | - Fix options parsing to convert strings to proper booleans
224 | - Add support for Fabrication fabricators
225 | - Leave magic encoding comment intact
226 | - Fix issue #14 - RuntimeError: Already memoized
227 | - Count a model as 'annotated' if any of its tests/fixtures are annotated
228 | - Support FactoryGirl
229 | - Support :change migrations (Rails 3.1)
230 | - Allow models with non-standard capitalization
231 | - Widen type column so we can handle longtexts with chopping things off.
232 | - Skip trying to get list of models from commandline when running via Rake
233 |   (was preventing the use of multiple rake tasks in one command if one of them was `db:migrate`).
234 | - Add ability to skip annotations for a model by adding
235 |   `# -*- SkipSchemaAnnotations` anywhere in the file.
236 | - Don't show column limits for integer and boolean types.
237 | - Add sorting for columns and indexes.
238 |   (Helpful for out-of-order migration execution.  Use `--sort` if you want this.)
239 | - Annotate unit tests in subfolders.
240 | - Add generator to install rakefile that automatically annotates on `db:migrate`.
241 | - Correct Gemfile to clarify which environments need which gems.
242 | - Add an .rvmrc to facilitate clean development.
243 | - Refactor out ActiveRecord monkey-patch to permit extending without side-effects.
244 | - Use ObjectSpace to locate models to facilitate handling of models with
245 |   non-standard capitalization.
246 |   Note that this still requires that the inflector be configured to understand
247 |   the special case.
248 | - Shore up test cases a bit.
249 | - Merge against many of the older branches on Github whose functionality is
250 |   already reflected to reduce confusion about what is and is not implemented here.
251 | - Accept String or Symbol for :position (et al) options.
252 | - Add RDoc output formatting as an option.
253 | - Add Markdown output formatting as an option.
254 | - Add option to force annotation regeneration.
255 | - Add new configuration option for controlling where info is placed in
256 |   fixtures/factories.
257 | - Fix for models without tables.
258 | - Fix gemspec generation now that Jeweler looks at Gemfile.
259 | - Fix warning: `NOTE: Gem::Specification#default_executable= is deprecated
260 |   with no replacement. It will be removed on or after 2011-10-01.`
261 | - Fix handling of files with no trailing newline when putting annotations at
262 |   the end of the file.
263 | - Now works on tables with no primary key.
264 | - `--format=markdown` option
265 | - `--trace` option to help debug "Unable to annotate" errors
266 | - "Table name" annotation (if table name is different from model name)
267 | - "Human name" annotation (enabling translation to non-English locales)
268 | - Fix JRuby ObjectSpace compatibility bug (https://github.com/ctran/annotate_models/pull/85)
269 | - Fix FactoryGirl compatibility bug (https://github.com/ctran/annotate_models/pull/82)
270 | 
271 | 
272 | ## 2.4.2 2009-11-21
273 | - Annotates `(spec|test)/factories/<model>_factory.rb` files
274 | 
275 | ## 2.4.1 2009-11-20
276 | 
277 | - Annotates thoughtbot's factory_girl factories (`test/factories/<model>_factory.rb`)
278 | - Move default annotation position back to top
279 | 
280 | 
281 | ## 2.4.0 2009-12-13
282 | - Incorporated lots of patches from the Github community,
283 |   including support for Blueprints fixtures
284 | - Several bug fixes
285 | 
286 | ## 2.1 2009-10-18
287 | 
288 | - New options
289 |     - `-R` to require additional files before loading the models
290 |     - `-i` to show database indexes in annotations
291 |     - `-e` to exclude annotating tests or fixtures
292 |     - `-m` to include the migration version number in the annotation
293 |     - `--model-dir` to annotate model files stored a different place than `app/models`
294 | 
295 | - Ignore unknown macros ('acts_as_whatever')
296 | 
297 | 
298 | ## 2.0 2009-02-03
299 | 
300 | - Add annotate_models plugin fork additions
301 |     - Annotates Rspec and Test Unit models
302 |     - Annotates Object Daddy exemplars
303 |     - Annotates geometrical columns
304 | 
305 | - Add AnnotateRoutes rake task
306 | - Up gem structure to newgem defaults
307 | 
308 | 
309 | ## 1.0.4 2008-09-04
310 | 
311 | - Only update modified models since last run, thanks to sant0sk1
312 | 
313 | ## 1.0.3 2008-05-02
314 | 
315 | - Add misc changes from Dustin Sallings and Henrik N
316 |     - Remove trailing whitespace
317 |     - More intuitive info messages
318 |     - Update README file with update-to-date example
319 | 
320 | ## 1.0.2 2008-03-22
321 | 
322 | - Add contributions from Michael Bumann (http://github.com/bumi)
323 |     - added an option "position" to choose to put the annotation,
324 |     - spec/fixtures now also get annotated
325 |     - added a task to remove the annotations
326 |     - these options can be specified from command line as `-d` and `-p [before|after]`
327 | 
328 | 
329 | 


--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
 1 | source 'https://rubygems.org'
 2 | 
 3 | ruby '>= 2.4.0'
 4 | 
 5 | gem 'activerecord', '>= 4.2.5', '< 6', require: false
 6 | gem 'rake', require: false
 7 | 
 8 | group :development do
 9 |   gem 'bump'
10 |   gem 'mg', require: false
11 |   gem 'travis', require: false
12 |   platforms :mri, :mingw do
13 |     gem 'yard', require: false
14 |   end
15 | end
16 | 
17 | group :development, :test do
18 |   gem 'byebug'
19 |   gem 'guard-rspec', require: false
20 |   gem 'rspec', require: false
21 | 
22 |   gem 'rubocop', '~> 1.12.0', require: false
23 |   gem 'rubocop-rake', require: false
24 |   gem 'rubocop-rspec', '~> 2.2.0', require: false
25 |   gem 'simplecov', require: false
26 |   gem 'terminal-notifier-guard', require: false
27 | 
28 |   gem 'codeclimate-test-reporter'
29 |   gem 'coveralls'
30 | 
31 |   gem 'overcommit'
32 |   gem 'ruby_dep', '1.5.0'
33 | 
34 |   platforms :mri, :mingw do
35 |     gem 'pry', require: false
36 |     gem 'pry-byebug', require: false
37 |   end
38 | end
39 | 
40 | group :test do
41 |   gem 'files', require: false
42 |   gem 'git', require: false
43 | end
44 | 


--------------------------------------------------------------------------------
/Guardfile:
--------------------------------------------------------------------------------
 1 | # NOTE: The cmd option is now required due to the increasing number of ways
 2 | #       rspec may be run, below are examples of the most common uses.
 3 | #  * bundler: 'bundle exec rspec'
 4 | #  * bundler binstubs: 'bin/rspec'
 5 | #  * spring: 'bin/rsspec' (This will use spring if running and you have
 6 | #                          installed the spring binstubs per the docs)
 7 | #  * zeus: 'zeus rspec' (requires the server to be started separetly)
 8 | #  * 'just' rspec: 'rspec'
 9 | guard :rspec, cmd: 'bundle exec rspec' do
10 |   watch(%r{^spec/.+_spec\.rb$})
11 |   watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
12 |   watch('spec/spec_helper.rb')  { 'spec' }
13 | 
14 |   # Rails example
15 |   watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
16 |   watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$})          { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
17 |   watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
18 |   watch(%r{^spec/support/(.+)\.rb$})                  { 'spec' }
19 |   watch('config/routes.rb')                           { 'spec/routing' }
20 |   watch('app/controllers/application_controller.rb')  { 'spec/controllers' }
21 |   watch('spec/rails_helper.rb')                       { 'spec' }
22 | 
23 |   # Capybara features specs
24 |   watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$})     { |m| "spec/features/#{m[1]}_spec.rb" }
25 | 
26 |   # Turnip features and steps
27 |   watch(%r{^spec/acceptance/(.+)\.feature$})
28 |   watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$})   { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
29 | end
30 | 


--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
 1 | You can redistribute it and/or modify it under either the terms of the
 2 | 2-clause BSDL (see the file BSDL), or the conditions below:
 3 | 
 4 |   1. You may make and give away verbatim copies of the source form of the
 5 |      software without restriction, provided that you duplicate all of the
 6 |      original copyright notices and associated disclaimers.
 7 | 
 8 |   2. You may modify your copy of the software in any way, provided that
 9 |      you do at least ONE of the following:
10 | 
11 |        a) place your modifications in the Public Domain or otherwise
12 |           make them Freely Available, such as by posting said
13 | 	  modifications to Usenet or an equivalent medium, or by allowing
14 | 	  the author to include your modifications in the software.
15 | 
16 |        b) use the modified software only within your corporation or
17 |           organization.
18 | 
19 |        c) give non-standard binaries non-standard names, with
20 |           instructions on where to get the original software distribution.
21 | 
22 |        d) make other distribution arrangements with the author.
23 | 
24 |   3. You may distribute the software in object code or binary form,
25 |      provided that you do at least ONE of the following:
26 | 
27 |        a) distribute the binaries and library files of the software,
28 | 	  together with instructions (in the manual page or equivalent)
29 | 	  on where to get the original distribution.
30 | 
31 |        b) accompany the distribution with the machine-readable source of
32 | 	  the software.
33 | 
34 |        c) give non-standard binaries non-standard names, with
35 |           instructions on where to get the original software distribution.
36 | 
37 |        d) make other distribution arrangements with the author.
38 | 
39 |   4. You may modify and include the part of the software into any other
40 |      software (possibly commercial).  But some files in the distribution
41 |      are not written by the author, so that they are not under these terms.
42 | 
43 |      For the list of those files and their copying conditions, see the
44 |      file LEGAL.
45 | 
46 |   5. The scripts and library files supplied as input to or produced as 
47 |      output from the software do not automatically fall under the
48 |      copyright of the software, but belong to whomever generated them, 
49 |      and may be sold commercially, and may be aggregated with this
50 |      software.
51 | 
52 |   6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
53 |      IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
54 |      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55 |      PURPOSE.


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | ## Annotate (aka AnnotateModels)
  2 | 
  3 | [![Gem Version](https://badge.fury.io/rb/annotate.svg)](http://badge.fury.io/rb/annotate)
  4 | [![Downloads count](https://img.shields.io/gem/dt/annotate.svg?style=flat)](https://rubygems.org/gems/annotate)
  5 | [![CI Status](https://github.com/ctran/annotate_models/workflows/CI/badge.svg)](https://github.com/ctran/annotate_models/actions?workflow=CI)
  6 | [![Coveralls](https://coveralls.io/repos/ctran/annotate_models/badge.svg?branch=develop)](https://coveralls.io/r/ctran/annotate_models?branch=develop)
  7 | [![Maintenability](https://codeclimate.com/github/ctran/annotate_models/badges/gpa.svg)](https://codeclimate.com/github/ctran/annotate_models)
  8 | 
  9 | Add a comment summarizing the current schema to the top or bottom of each of your...
 10 | 
 11 | - ActiveRecord models
 12 | - Fixture files
 13 | - Tests and Specs
 14 | - Object Daddy exemplars
 15 | - Machinist blueprints
 16 | - Fabrication fabricators
 17 | - Thoughtbot's factory_bot factories, i.e. the `(spec|test)/factories/<model>_factory.rb` files
 18 | - `routes.rb` file (for Rails projects)
 19 | 
 20 | 
 21 | The schema comment looks like this:
 22 | 
 23 | ```ruby
 24 | # == Schema Info
 25 | #
 26 | # Table name: line_items
 27 | #
 28 | #  id                  :integer(11)    not null, primary key
 29 | #  quantity            :integer(11)    not null
 30 | #  product_id          :integer(11)    not null
 31 | #  unit_price          :float
 32 | #  order_id            :integer(11)
 33 | #
 34 | 
 35 | class LineItem < ActiveRecord::Base
 36 |   belongs_to :product
 37 |   . . .
 38 | ```
 39 | 
 40 | It also annotates geometrical columns, `geom` type and `srid`,
 41 | when using `SpatialAdapter`, `PostgisAdapter` or `PostGISAdapter`:
 42 | 
 43 | ```ruby
 44 | # == Schema Info
 45 | #
 46 | # Table name: trips
 47 | #
 48 | #  local           :geometry        point, 4326
 49 | #  path            :geometry        line_string, 4326
 50 | ```
 51 | 
 52 | Also, if you pass the `-r` option, it'll annotate `routes.rb` with the output of `rake routes`.
 53 | 
 54 | 
 55 | ## Upgrading to 3.X and annotate models not working?
 56 | 
 57 | In versions 2.7.X the annotate gem defaulted to annotating models if no arguments were passed in.
 58 | The annotate gem by default would not allow for routes and models to be annotated together.
 59 | A [change was added in #647](https://github.com/ctran/annotate_models/pull/647).
 60 | You [can read more here](https://github.com/ctran/annotate_models/issues/663).
 61 | 
 62 | There are a few ways of fixing this:
 63 | 
 64 | - If using CLI explicitly pass in models flag using `--models`
 65 | 
 66 | OR
 67 | 
 68 | a) Running `rails g annotate:install` will overwrite your defaults with the annotating `models` option set to `'true'`.
 69 | 
 70 | b) In `lib/tasks/auto_annotate_models.rake` add the `models` key-value option:
 71 | 
 72 | ```ruby
 73 |     Annotate.set_defaults(
 74 |       ...
 75 |       'models'                      => 'true',
 76 |       ...
 77 | ```
 78 | 
 79 | ## Install
 80 | 
 81 | Into Gemfile from rubygems.org:
 82 | 
 83 | ```ruby
 84 | group :development do
 85 |   gem 'annotate'
 86 | end
 87 | ```
 88 | 
 89 | Into Gemfile from Github:
 90 | 
 91 | ```ruby
 92 | group :development do
 93 |   gem 'annotate', git: 'https://github.com/ctran/annotate_models.git'
 94 | end
 95 | ```
 96 | 
 97 | Into environment gems from rubygems.org:
 98 | 
 99 |     gem install annotate
100 | 
101 | Into environment gems from Github checkout:
102 | 
103 |     git clone https://github.com/ctran/annotate_models.git annotate_models
104 |     cd annotate_models
105 |     rake gem
106 |     gem install dist/annotate-*.gem
107 | 
108 | ## Usage
109 | 
110 | (If you used the Gemfile install, prefix the below commands with `bundle exec`.)
111 | 
112 | ### Usage in Rails
113 | 
114 | To annotate all your models, tests, fixtures, and factories:
115 | 
116 |     cd /path/to/app
117 |     annotate
118 | 
119 | To annotate just your models, tests, and factories:
120 | 
121 |     annotate --models --exclude fixtures
122 | 
123 | To annotate just your models:
124 | 
125 |     annotate --models
126 | 
127 | To annotate routes.rb:
128 | 
129 |     annotate --routes
130 | 
131 | To remove model/test/fixture/factory/serializer annotations:
132 | 
133 |     annotate --delete
134 | 
135 | To remove routes.rb annotations:
136 | 
137 |     annotate --routes --delete
138 | 
139 | To automatically annotate every time you run `db:migrate`,
140 | either run `rails g annotate:install`
141 | or add `Annotate.load_tasks` to your `Rakefile`.
142 | 
143 | See the [configuration in Rails](#configuration-in-rails) section for more info.
144 | 
145 | ### Usage Outside of Rails
146 | 
147 | Everything above applies, except that `--routes` is not meaningful,
148 | and you will probably need to explicitly set one or more `--require` option(s), and/or one or more `--model-dir` options
149 | to inform `annotate` about the structure of your project and help it bootstrap and load the relevant code.
150 | 
151 | ## Configuration
152 | 
153 | If you want to always skip annotations on a particular model, add this string
154 | anywhere in the file:
155 | 
156 |     # -*- SkipSchemaAnnotations
157 | 
158 | ### Configuration in Rails
159 | 
160 | To generate a configuration file (in the form of a `.rake` file), to set
161 | default options:
162 | 
163 |     rails g annotate:install
164 | 
165 | Edit this file to control things like output format, where annotations are
166 | added (top or bottom of file), and in which artifacts.
167 | 
168 | The generated rakefile `lib/tasks/auto_annotate_models.rake` also contains
169 | `Annotate.load_tasks`. This adds a few rake tasks which duplicate command-line
170 | functionality:
171 | 
172 |     rake annotate_models                          # Add schema information (as comments) to model and fixture files
173 |     rake annotate_routes                          # Adds the route map to routes.rb
174 |     rake remove_annotation                        # Remove schema information from model and fixture files
175 | 
176 | By default, once you've generated a configuration file, annotate will be
177 | executed whenever you run `rake db:migrate` (but only in development mode).
178 | If you want to disable this behavior permanently,
179 | edit the `.rake` file and change:
180 | 
181 | ```ruby
182 |     'skip_on_db_migrate'   => 'false',
183 | ```
184 | 
185 | To:
186 | 
187 | ```ruby
188 |     'skip_on_db_migrate'   => 'true',
189 | ```
190 | 
191 | If you want to run `rake db:migrate` as a one-off without running annotate,
192 | you can do so with a simple environment variable, instead of editing the
193 | `.rake` file:
194 | 
195 |     ANNOTATE_SKIP_ON_DB_MIGRATE=1 rake db:migrate
196 | 
197 | ## Options
198 | 
199 |     Usage: annotate [options] [model_file]*
200 |             --additional-file-patterns   Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`)
201 |         -d, --delete                     Remove annotations from all model files or the routes.rb file
202 |         -p [before|top|after|bottom],    Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)
203 |             --position
204 |             --pc, --position-in-class [before|top|after|bottom]
205 |                                          Place the annotations at the top (before) or the bottom (after) of the model file
206 |             --pf, --position-in-factory [before|top|after|bottom]
207 |                                          Place the annotations at the top (before) or the bottom (after) of any factory files
208 |             --px, --position-in-fixture [before|top|after|bottom]
209 |                                          Place the annotations at the top (before) or the bottom (after) of any fixture files
210 |             --pt, --position-in-test [before|top|after|bottom]
211 |                                          Place the annotations at the top (before) or the bottom (after) of any test files
212 |             --pr, --position-in-routes [before|top|after|bottom]
213 |                                          Place the annotations at the top (before) or the bottom (after) of the routes.rb file
214 |             --ps, --position-in-serializer [before|top|after|bottom]
215 |                                          Place the annotations at the top (before) or the bottom (after) of the serializer files
216 |             --w, --wrapper STR           Wrap annotation with the text passed as parameter.
217 |                                          If --w option is used, the same text will be used as opening and closing
218 |             --wo, --wrapper-open STR     Annotation wrapper opening.
219 |             --wc, --wrapper-close STR    Annotation wrapper closing
220 |         -r, --routes                     Annotate routes.rb with the output of 'rake routes'
221 |             --models                     Annotate ActiveRecord models
222 |         -a, --active-admin               Annotate active_admin models
223 |         -v, --version                    Show the current version of this gem
224 |         -m, --show-migration             Include the migration version number in the annotation
225 |         -c, --show-check-constraints     List the table's check constraints in the annotation
226 |         -k, --show-foreign-keys          List the table's foreign key constraints in the annotation
227 |             --ck, --complete-foreign-keys
228 |                                          Complete foreign key names in the annotation
229 |         -i, --show-indexes               List the table's database indexes in the annotation
230 |         -s, --simple-indexes             Concat the column's related indexes in the annotation
231 |             --model-dir dir              Annotate model files stored in dir rather than app/models, separate multiple dirs with commas
232 |             --root-dir dir               Annotate files stored within root dir projects, separate multiple dirs with commas
233 |             --ignore-model-subdirects    Ignore subdirectories of the models directory
234 |             --sort                       Sort columns alphabetically, rather than in creation order
235 |             --classified-sort            Sort columns alphabetically, but first goes id, then the rest columns, then the timestamp columns and then the association columns
236 |         -R, --require path               Additional file to require before loading models, may be used multiple times
237 |         -e [tests,fixtures,factories,serializers],
238 |             --exclude                    Do not annotate fixtures, test files, factories, and/or serializers
239 |         -f [bare|rdoc|yard|markdown],    Render Schema Infomation as plain/RDoc/YARD/Markdown
240 |             --format
241 |             --force                      Force new annotations even if there are no changes.
242 |             --frozen                     Do not allow to change annotations. Exits non-zero if there are going to be changes to files.
243 |             --timestamp                  Include timestamp in (routes) annotation
244 |             --trace                      If unable to annotate a file, print the full stack trace, not just the exception message.
245 |         -I, --ignore-columns REGEX       don't annotate columns that match a given REGEX (e.g. `annotate -I '^(id|updated_at|created_at)'`)
246 |             --ignore-routes REGEX        don't annotate routes that match a given REGEX (e.g. `annotate -I '(mobile|resque|pghero)'`)_
247 |             --hide-limit-column-types VALUES
248 |                                          don't show limit for given column types, separated by commas (e.g. `integer,boolean,text`)
249 |             --hide-default-column-types VALUES
250 |                                          don't show default for given column types, separated by commas (e.g. `json,jsonb,hstore`)
251 |             --ignore-unknown-models      don't display warnings for bad model files
252 |             --with-comment               include database comments in model annotations
253 |             --with-comment-column        include database comments in model annotations, as its own column, after all others
254 | 
255 | ### Option: `additional_file_patterns`
256 | 
257 | CLI: `--additional-file-patterns`<br>
258 | Ruby: `:additional_file_patterns`
259 | 
260 | Provide additional paths for the gem to annotate.  These paths can include
261 | globs. It is recommended to use absolute paths.  Here are some examples:
262 | 
263 | *   `/app/lib/decorates/%MODEL_NAME%/*.rb`
264 | *   `/app/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb`
265 | *   `/app/lib/forms/%TABLE_NAME%/*.rb`
266 | 
267 | 
268 | The appropriate model will be inferred using the `%*%` syntax, annotating any
269 | matching files. It works with existing filename resolutions (options for which
270 | can be found in the `resolve_filename` method of `annotate_models.rb`).
271 | 
272 | When using in a Rails config, you can use the following:
273 | 
274 | `File.join(Rails.application.root,
275 | 'app/lib/forms/%PLURALIZED_MODEL_NAME%/***/**.rb')`
276 | 
277 | ## Sorting
278 | 
279 | By default, columns will be sorted in database order (i.e. the order in which
280 | migrations were run).
281 | 
282 | If you prefer to sort alphabetically so that the results of annotation are
283 | consistent regardless of what order migrations are executed in, use `--sort`.
284 | 
285 | ## Markdown
286 | 
287 | The format produced is actually MultiMarkdown, making use of the syntax
288 | extension for tables.  It's recommended you use `kramdown` as your parser if
289 | you want to use this format.  If you're using `yard` to generate
290 | documentation, specify a format of markdown with `kramdown` as the provider by
291 | adding this to your `.yardopts` file:
292 | 
293 |     --markup markdown
294 |     --markup-provider kramdown
295 | 
296 | Be sure to add this to your `Gemfile` as well:
297 | 
298 |     gem 'kramdown', groups => [:development], require => false
299 | 
300 | ## WARNING
301 | 
302 | **Don't add text after an automatically-created comment block.** This tool
303 | will blow away the initial/final comment block in your models if it looks like
304 | it was previously added by this gem.
305 | 
306 | Be sure to check the changes that this tool makes! If you are using Git, you
307 | may simply check your project's status after running `annotate`:
308 | 
309 |     $ git status
310 | 
311 | If you are not using a VCS (like Git, Subversion or similar), please tread
312 | extra carefully, and consider using one.
313 | 
314 | ## Links
315 | 
316 | *   Factory Bot: http://github.com/thoughtbot/factory_bot
317 | *   Object Daddy: http://github.com/flogic/object_daddy
318 | *   Machinist: http://github.com/notahat/machinist
319 | *   Fabrication: http://github.com/paulelliott/fabrication
320 | *   SpatialAdapter: http://github.com/pdeffendol/spatial_adapter
321 | *   PostgisAdapter: http://github.com/nofxx/postgis_adapter
322 | *   PostGISAdapter: https://github.com/dazuma/activerecord-postgis-adapter
323 | 
324 | 
325 | ## License
326 | 
327 | Released under the same license as Ruby. No Support. No Warranty.
328 | 
329 | ## Authors
330 | 
331 | [See AUTHORS.md](AUTHORS.md).
332 | 


--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
 1 | ## Prerequisite 
 2 | 
 3 | - Install "git-flow" (`brew install git-flow`)
 4 | - Install "bump" gem (`gem install bump`)
 5 | 
 6 | 
 7 | ## Perform a release
 8 | 
 9 | - `git flow release start <release>`
10 | - Update the `CHANGELOG.md` file
11 | - `bump current`
12 | - `bump patch`
13 | - `rm -rf dist`
14 | - `rake spec`
15 | - `rake gem`
16 | - `git flow release finish <release>`
17 | 
18 | - `rake gem:publish`
19 | 
20 | 


--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
  1 | def exit_exception(e)
  2 |   $stderr.puts e.message
  3 |   exit e.status_code
  4 | end
  5 | 
  6 | # NOTE: this causes annoying psych warnings under Ruby 1.9.2-p180; to fix, upgrade to 1.9.3
  7 | begin
  8 |   require 'bundler'
  9 |   Bundler.setup(:default, :development)
 10 | rescue Bundler::BundlerError => e
 11 |   $stderr.puts 'Run `bundle install` to install missing gems'
 12 |   exit_exception(e)
 13 | end
 14 | 
 15 | using_dsl = false
 16 | begin
 17 |   require 'rake/dsl_definition'
 18 |   using_dsl = true
 19 | rescue Exception => e
 20 |   # We might just be on an old version of Rake...
 21 |   exit_exception(e)
 22 | end
 23 | require 'rake'
 24 | include Rake::DSL if using_dsl
 25 | 
 26 | require './lib/annotate'
 27 | require 'mg'
 28 | begin
 29 |   MG.new('annotate.gemspec')
 30 | rescue Exception
 31 |   $stderr.puts("WARNING: Couldn't read gemspec.  As such, a number of tasks may be unavailable to you until you run 'rake gem:gemspec' to correct the issue.")
 32 |   # Gemspec is probably in a broken state, so let's give ourselves a chance to
 33 |   # build a new one...
 34 | end
 35 | DEVELOPMENT_GROUPS = [:development, :test].freeze
 36 | RUNTIME_GROUPS = Bundler.definition.groups - DEVELOPMENT_GROUPS
 37 | namespace :gem do
 38 |   task :gemspec do
 39 |     spec = Gem::Specification.new do |gem|
 40 |       # See http://docs.rubygems.org/read/chapter/20
 41 |       # for more options.
 42 |       gem.version = Annotate.version
 43 |       gem.name = 'annotate'
 44 |       gem.homepage = 'http://github.com/ctran/annotate_models'
 45 |       gem.rubyforge_project = 'annotate'
 46 |       gem.license = 'Ruby'
 47 |       gem.summary = 'Annotates Rails Models, routes, fixtures, and others based on the database schema.'
 48 |       gem.description = 'Annotates Rails/ActiveRecord Models, routes, fixtures, and others based on the database schema.'
 49 |       gem.email = ['alex@stinky.com', 'cuong@gmail.com', 'x@nofxx.com', 'turadg@aleahmad.net', 'jon@cloudability.com']
 50 |       gem.authors = ['Alex Chaffee', 'Cuong Tran', 'Marcos Piccinini', 'Turadg Aleahmad', 'Jon Frisby']
 51 |       gem.require_paths = ['lib']
 52 |       # gem.rdoc_options = ["--charset=UTF-8"]
 53 |       # gem.required_ruby_version = "> 1.9.2"
 54 | 
 55 |       Bundler.load.dependencies_for(*RUNTIME_GROUPS).each do |dep|
 56 |         runtime_resolved = Bundler.definition.specs_for(RUNTIME_GROUPS).find { |spec| spec.name == dep.name }
 57 |         unless runtime_resolved.nil?
 58 |           gem.add_dependency(dep.name, dep.requirement)
 59 |         end
 60 |       end
 61 | 
 62 |       gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
 63 |       gem.extra_rdoc_files = ['README.md', 'CHANGELOG.md', 'TODO.md']
 64 | 
 65 |       gem.files = `git ls-files -- .`.split("\n").reject do |fn|
 66 |         fn =~ /^Gemfile.*/ ||
 67 |           fn =~ /^Rakefile/ ||
 68 |           fn =~ /^\.rvmrc/ ||
 69 |           fn =~ /^\.gitignore/ ||
 70 |           fn =~ /^\.rspec/ ||
 71 |           fn =~ /^\.document/ ||
 72 |           fn =~ /^\.yardopts/ ||
 73 |           fn =~ /^pkg/ ||
 74 |           fn =~ /^spec/ ||
 75 |           fn =~ /^doc/ ||
 76 |           fn =~ /^vendor\/cache/
 77 |       end.sort
 78 |     end
 79 |     File.open('annotate.gemspec', 'wb') do |fh|
 80 |       fh.write("# This file is auto-generated!\n")
 81 |       fh.write("# DO NOT EDIT THIS FILE DIRECTLY!\n")
 82 |       fh.write("# Instead, edit the Rakefile and run 'rake gems:gemspec'.")
 83 |       fh.write(spec.to_ruby)
 84 |     end
 85 |   end
 86 | end
 87 | 
 88 | namespace :jeweler do
 89 |   task :clobber do
 90 |     FileUtils.rm_f('pkg')
 91 |   end
 92 | end
 93 | task clobber: :'jeweler:clobber'
 94 | 
 95 | require 'rspec/core/rake_task' # RSpec 2.0
 96 | RSpec::Core::RakeTask.new(:spec) do |t|
 97 |   t.pattern = ['spec/*_spec.rb', 'spec/**/*_spec.rb']
 98 |   t.rspec_opts = ['--backtrace', '--format d']
 99 | end
100 | 
101 | # Placeholder for running bin/* in development...
102 | task :environment
103 | 
104 | task :integration_environment do
105 |   require './spec/spec_helper'
106 | end
107 | 
108 | namespace :gemsets do
109 |   desc "Completely empty any gemsets used by scenarios, so they'll be perfectly clean on the next run."
110 |   task empty: [:integration_environment] do
111 |     Annotate::Integration::SCENARIOS.each do |test_rig, _base_dir, _test_name|
112 |       Annotate::Integration.empty_gemset(test_rig)
113 |     end
114 |   end
115 | end
116 | task clobber: :'gemsets:empty'
117 | 
118 | namespace :integration do
119 |   desc "Remove any cruft generated by manual debugging runs which is .gitignore'd."
120 |   task clean: :integration_environment do
121 |     Annotate::Integration.nuke_all_cruft
122 |   end
123 | 
124 |   desc 'Reset any changed files, and remove any untracked files in spec/integration/*/, plus run integration:clean.'
125 |   task clobber: [:integration_environment, :'integration:clean'] do
126 |     Annotate::Integration.reset_dirty_files
127 |     Annotate::Integration.clear_untracked_files
128 |   end
129 | 
130 |   task symlink: [:integration_environment] do
131 |     require 'digest/md5'
132 | 
133 |     integration_dir = File.expand_path(File.join(File.dirname(__FILE__), 'spec', 'integration'))
134 |     # fixture_dir = File.expand_path(File.join(File.dirname(__FILE__), 'spec', 'fixtures'))
135 |     target_dir = File.expand_path(ENV['TARGET']) if ENV['TARGET']
136 |     raise 'Must specify TARGET=x, where x is an integration test scenario!' unless target_dir && Dir.exist?(target_dir)
137 |     raise 'TARGET directory must be within spec/integration/!' unless target_dir.start_with?(integration_dir)
138 |     candidates = {}
139 |     FileList[
140 |       "#{target_dir}/.rvmrc",
141 |       "#{target_dir}/**/*"
142 |     ].select { |fname| !(File.symlink?(fname) || File.directory?(fname)) }
143 |       .map { |fname| fname.sub(integration_dir, '') }
144 |       .reject do |fname|
145 |         fname =~ /\/\.gitkeep$/ ||
146 |           fname =~ /\/app\/models\// ||
147 |           fname =~ /\/routes\.rb$/ ||
148 |           fname =~ /\/fixtures\// ||
149 |           fname =~ /\/factories\// ||
150 |           fname =~ /\.sqlite3$/ ||
151 |           (fname =~ /\/test\// && fname !~ /_helper\.rb$/) ||
152 |           (fname =~ /\/spec\// && fname !~ /_helper\.rb$/)
153 |       end
154 |       .map { |fname| "#{integration_dir}#{fname}" }
155 |       .each do |fname|
156 |         digest = Digest::MD5.hexdigest(File.read(fname))
157 |         candidates[digest] ||= []
158 |         candidates[digest] << fname
159 |       end
160 |     fixtures = {}
161 |     FileList['spec/fixtures/**/*'].each do |fname|
162 |       fixtures[Digest::MD5.hexdigest(File.read(fname))] = File.expand_path(fname)
163 |     end
164 | 
165 |     candidates.each_key do |digest|
166 |       next unless fixtures.key?(digest)
167 |       candidates[digest].each do |fname|
168 |         # Double-check contents in case of hash collision...
169 |         next unless FileUtils.identical?(fname, fixtures[digest])
170 |         destination_dir = Pathname.new(File.dirname(fname))
171 |         relative_target = Pathname.new(fixtures[digest]).relative_path_from(destination_dir)
172 |         Dir.chdir(destination_dir) do
173 |           sh('ln', '-sfn', relative_target.to_s, File.basename(fname))
174 |         end
175 |       end
176 |     end
177 |   end
178 | end
179 | task clobber: :'integration:clobber'
180 | 
181 | require 'yard'
182 | YARD::Rake::YardocTask.new do |t|
183 |   # t.files   = ['features/**/*.feature', 'features/**/*.rb', 'lib/**/*.rb']
184 |   # t.options = ['--any', '--extra', '--opts'] # optional
185 | end
186 | 
187 | namespace :yard do
188 |   task :clobber do
189 |     FileUtils.rm_f('.yardoc')
190 |     FileUtils.rm_f('doc')
191 |   end
192 | end
193 | task clobber: :'yard:clobber'
194 | 
195 | namespace :rubinius do
196 |   task :clobber do
197 |     FileList['**/*.rbc'].each { |fname| FileUtils.rm_f(fname) }
198 |     FileList['.rbx/**/*'].each { |fname| FileUtils.rm_f(fname) }
199 |   end
200 | end
201 | task clobber: :'rubinius:clobber'
202 | 
203 | # want other tests/tasks run by default? Add them to the list
204 | task default: [:spec]
205 | 


--------------------------------------------------------------------------------
/annotate.gemspec:
--------------------------------------------------------------------------------
 1 | # -*- encoding: utf-8 -*-
 2 | lib = File.expand_path('../lib', __FILE__)
 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
 4 | require 'annotate/version'
 5 | 
 6 | Gem::Specification.new do |s|
 7 |   s.name = 'annotate'
 8 |   s.version = Annotate.version
 9 | 
10 |   s.required_ruby_version = '>= 2.4.0'
11 |   s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
12 |   s.authors = ['Alex Chaffee', 'Cuong Tran', 'Marcos Piccinini', 'Turadg Aleahmad', 'Jon Frisby']
13 |   s.description = 'Annotates Rails/ActiveRecord Models, routes, fixtures, and others based on the database schema.'
14 |   s.email = ['alex@stinky.com', 'cuong.tran@gmail.com', 'x@nofxx.com', 'turadg@aleahmad.net', 'jon@cloudability.com']
15 |   s.executables = ['annotate']
16 |   s.extra_rdoc_files = ['README.md', 'CHANGELOG.md']
17 |   s.files = `git ls-files -z LICENSE.txt *.md *.gemspec bin lib`.split("\x0")
18 |   s.homepage = 'https://github.com/ctran/annotate_models'
19 |   s.licenses = ['Ruby']
20 |   s.require_paths = ['lib']
21 |   s.rubygems_version = '2.1.11'
22 |   s.summary = 'Annotates Rails Models, routes, fixtures, and others based on the database schema.'
23 | 
24 |   s.specification_version = 4 if s.respond_to? :specification_version
25 |   s.add_runtime_dependency(%q<rake>, '>= 10.4', '< 14.0')
26 |   s.add_runtime_dependency(%q<activerecord>, ['>= 3.2', '< 8.0'])
27 | 
28 |   s.metadata = {
29 |     "bug_tracker_uri" => "https://github.com/ctran/annotate_models/issues/",
30 |     "source_code_uri" => "https://github.com/ctran/annotate_models.git"
31 |   }
32 | end
33 | 


--------------------------------------------------------------------------------
/bin/annotate:
--------------------------------------------------------------------------------
 1 | #!/usr/bin/env ruby
 2 | 
 3 | unless File.exist?('./Rakefile') || File.exist?('./Gemfile')
 4 |   abort 'Please run annotate from the root of the project.'
 5 | end
 6 | 
 7 | require 'rubygems'
 8 | begin
 9 |   require 'bundler'
10 |   Bundler.setup
11 | rescue StandardError
12 | end
13 | 
14 | here = File.expand_path(File.dirname __FILE__)
15 | $LOAD_PATH << "#{here}/../lib"
16 | 
17 | require 'annotate'
18 | require 'annotate/parser'
19 | 
20 | Annotate.bootstrap_rake
21 | 
22 | options_result = Annotate::Parser.parse(ARGV)
23 | 
24 | exit if options_result[:exit]
25 | 
26 | options = Annotate.setup_options(
27 |   is_rake: ENV['is_rake'] && !ENV['is_rake'].empty?
28 | )
29 | Annotate.eager_load(options) if Annotate::Helpers.include_models?
30 | 
31 | AnnotateModels.send(options_result[:target_action], options) if Annotate::Helpers.include_models?
32 | AnnotateRoutes.send(options_result[:target_action], options) if Annotate::Helpers.include_routes?
33 | 


--------------------------------------------------------------------------------
/lib/annotate.rb:
--------------------------------------------------------------------------------
  1 | $LOAD_PATH.unshift(File.dirname(__FILE__))
  2 | require 'annotate/version'
  3 | require 'annotate/annotate_models'
  4 | require 'annotate/annotate_routes'
  5 | require 'annotate/constants'
  6 | require 'annotate/helpers'
  7 | 
  8 | begin
  9 |   # ActiveSupport 3.x...
 10 |   require 'active_support/hash_with_indifferent_access'
 11 |   require 'active_support/core_ext/object/blank'
 12 | rescue StandardError
 13 |   # ActiveSupport 2.x...
 14 |   require 'active_support/core_ext/hash/indifferent_access'
 15 |   require 'active_support/core_ext/blank'
 16 | end
 17 | 
 18 | module Annotate
 19 |   ##
 20 |   # Set default values that can be overridden via environment variables.
 21 |   #
 22 |   def self.set_defaults(options = {})
 23 |     return if @has_set_defaults
 24 |     @has_set_defaults = true
 25 | 
 26 |     options = ActiveSupport::HashWithIndifferentAccess.new(options)
 27 | 
 28 |     Constants::ALL_ANNOTATE_OPTIONS.flatten.each do |key|
 29 |       if options.key?(key)
 30 |         default_value = if options[key].is_a?(Array)
 31 |                           options[key].join(',')
 32 |                         else
 33 |                           options[key]
 34 |                         end
 35 |       end
 36 | 
 37 |       default_value = ENV[key.to_s] unless ENV[key.to_s].blank?
 38 |       ENV[key.to_s] = default_value.nil? ? nil : default_value.to_s
 39 |     end
 40 |   end
 41 | 
 42 |   ##
 43 |   # TODO: what is the difference between this and set_defaults?
 44 |   #
 45 |   def self.setup_options(options = {})
 46 |     Constants::POSITION_OPTIONS.each do |key|
 47 |       options[key] = Annotate::Helpers.fallback(ENV[key.to_s], ENV['position'], 'before')
 48 |     end
 49 |     Constants::FLAG_OPTIONS.each do |key|
 50 |       options[key] = Annotate::Helpers.true?(ENV[key.to_s])
 51 |     end
 52 |     Constants::OTHER_OPTIONS.each do |key|
 53 |       options[key] = !ENV[key.to_s].blank? ? ENV[key.to_s] : nil
 54 |     end
 55 |     Constants::PATH_OPTIONS.each do |key|
 56 |       options[key] = !ENV[key.to_s].blank? ? ENV[key.to_s].split(',') : []
 57 |     end
 58 | 
 59 |     options[:additional_file_patterns] ||= []
 60 |     options[:additional_file_patterns] = options[:additional_file_patterns].split(',') if options[:additional_file_patterns].is_a?(String)
 61 |     options[:model_dir] = ['app/models'] if options[:model_dir].empty?
 62 | 
 63 |     options[:wrapper_open] ||= options[:wrapper]
 64 |     options[:wrapper_close] ||= options[:wrapper]
 65 | 
 66 |     # These were added in 2.7.0 but so this is to revert to old behavior by default
 67 |     options[:exclude_scaffolds] = Annotate::Helpers.true?(ENV.fetch('exclude_scaffolds', 'true'))
 68 |     options[:exclude_controllers] = Annotate::Helpers.true?(ENV.fetch('exclude_controllers', 'true'))
 69 |     options[:exclude_helpers] = Annotate::Helpers.true?(ENV.fetch('exclude_helpers', 'true'))
 70 | 
 71 |     options
 72 |   end
 73 | 
 74 |   def self.load_tasks
 75 |     return if @tasks_loaded
 76 | 
 77 |     Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each do |rake|
 78 |       load rake
 79 |     end
 80 | 
 81 |     @tasks_loaded = true
 82 |   end
 83 | 
 84 |   def self.eager_load(options)
 85 |     load_requires(options)
 86 |     require 'annotate/active_record_patch'
 87 | 
 88 |     if defined?(Rails::Application)
 89 |       if Rails.version.split('.').first.to_i < 3
 90 |         Rails.configuration.eager_load_paths.each do |load_path|
 91 |           matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
 92 |           Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
 93 |             require_dependency file.sub(matcher, '\1')
 94 |           end
 95 |         end
 96 |       else
 97 |         klass = Rails::Application.send(:subclasses).first
 98 |         klass.eager_load!
 99 |       end
100 |     else
101 |       options[:model_dir].each do |dir|
102 |         FileList["#{dir}/**/*.rb"].each do |fname|
103 |           require File.expand_path(fname)
104 |         end
105 |       end
106 |     end
107 |   end
108 | 
109 |   def self.bootstrap_rake
110 |     begin
111 |       require 'rake/dsl_definition'
112 |     rescue StandardError => e
113 |       # We might just be on an old version of Rake...
114 |       $stderr.puts e.message
115 |       exit e.status_code
116 |     end
117 |     require 'rake'
118 | 
119 |     load './Rakefile' if File.exist?('./Rakefile')
120 |     begin
121 |       Rake::Task[:environment].invoke
122 |     rescue
123 |       nil
124 |     end
125 |     unless defined?(Rails)
126 |       # Not in a Rails project, so time to load up the parts of
127 |       # ActiveSupport we need.
128 |       require 'active_support'
129 |       require 'active_support/core_ext/class/subclasses'
130 |       require 'active_support/core_ext/string/inflections'
131 |     end
132 | 
133 |     load_tasks
134 |     Rake::Task[:set_annotation_options].invoke
135 |   end
136 | 
137 |   class << self
138 |     private
139 | 
140 |     def load_requires(options)
141 |       options[:require].count > 0 &&
142 |         options[:require].each { |path| require path }
143 |     end
144 |   end
145 | end
146 | 


--------------------------------------------------------------------------------
/lib/annotate/active_record_patch.rb:
--------------------------------------------------------------------------------
 1 | # monkey patches
 2 | 
 3 | module ::ActiveRecord
 4 |   class Base
 5 |     def self.method_missing(_name, *_args)
 6 |       # ignore this, so unknown/unloaded macros won't cause parsing to fail
 7 |     end
 8 |   end
 9 | end
10 | 


--------------------------------------------------------------------------------
/lib/annotate/annotate_models/file_patterns.rb:
--------------------------------------------------------------------------------
  1 | module AnnotateModels
  2 |   # This module provides module method to get file paths.
  3 |   module FilePatterns
  4 |     # Controller files
  5 |     CONTROLLER_DIR       = File.join('app', 'controllers')
  6 | 
  7 |     # Active admin registry files
  8 |     ACTIVEADMIN_DIR      = File.join('app', 'admin')
  9 | 
 10 |     # Helper files
 11 |     HELPER_DIR           = File.join('app', 'helpers')
 12 | 
 13 |     # File.join for windows reverse bar compat?
 14 |     # I dont use windows, can`t test
 15 |     UNIT_TEST_DIR        = File.join('test', 'unit')
 16 |     MODEL_TEST_DIR       = File.join('test', 'models') # since rails 4.0
 17 |     SPEC_MODEL_DIR       = File.join('spec', 'models')
 18 | 
 19 |     FIXTURE_TEST_DIR     = File.join('test', 'fixtures')
 20 |     FIXTURE_SPEC_DIR     = File.join('spec', 'fixtures')
 21 | 
 22 |     # Other test files
 23 |     CONTROLLER_TEST_DIR  = File.join('test', 'controllers')
 24 |     CONTROLLER_SPEC_DIR  = File.join('spec', 'controllers')
 25 |     REQUEST_SPEC_DIR     = File.join('spec', 'requests')
 26 |     ROUTING_SPEC_DIR     = File.join('spec', 'routing')
 27 | 
 28 |     # Object Daddy http://github.com/flogic/object_daddy/tree/master
 29 |     EXEMPLARS_TEST_DIR   = File.join('test', 'exemplars')
 30 |     EXEMPLARS_SPEC_DIR   = File.join('spec', 'exemplars')
 31 | 
 32 |     # Machinist http://github.com/notahat/machinist
 33 |     BLUEPRINTS_TEST_DIR  = File.join('test', 'blueprints')
 34 |     BLUEPRINTS_SPEC_DIR  = File.join('spec', 'blueprints')
 35 | 
 36 |     # Factory Bot https://github.com/thoughtbot/factory_bot
 37 |     FACTORY_BOT_TEST_DIR = File.join('test', 'factories')
 38 |     FACTORY_BOT_SPEC_DIR = File.join('spec', 'factories')
 39 | 
 40 |     # Fabrication https://github.com/paulelliott/fabrication.git
 41 |     FABRICATORS_TEST_DIR = File.join('test', 'fabricators')
 42 |     FABRICATORS_SPEC_DIR = File.join('spec', 'fabricators')
 43 | 
 44 |     # Serializers https://github.com/rails-api/active_model_serializers
 45 |     SERIALIZERS_DIR      = File.join('app',  'serializers')
 46 |     SERIALIZERS_TEST_DIR = File.join('test', 'serializers')
 47 |     SERIALIZERS_SPEC_DIR = File.join('spec', 'serializers')
 48 | 
 49 |     class << self
 50 |       def generate(root_directory, pattern_type, options)
 51 |         case pattern_type
 52 |         when 'test'       then test_files(root_directory)
 53 |         when 'fixture'    then fixture_files(root_directory)
 54 |         when 'scaffold'   then scaffold_files(root_directory)
 55 |         when 'factory'    then factory_files(root_directory)
 56 |         when 'serializer' then serialize_files(root_directory)
 57 |         when 'additional_file_patterns'
 58 |           [options[:additional_file_patterns] || []].flatten
 59 |         when 'controller'
 60 |           [File.join(root_directory, CONTROLLER_DIR, '%PLURALIZED_MODEL_NAME%_controller.rb')]
 61 |         when 'admin'
 62 |           [
 63 |             File.join(root_directory, ACTIVEADMIN_DIR, '%MODEL_NAME%.rb'),
 64 |             File.join(root_directory, ACTIVEADMIN_DIR, '%PLURALIZED_MODEL_NAME%.rb')
 65 |           ]
 66 |         when 'helper'
 67 |           [File.join(root_directory, HELPER_DIR, '%PLURALIZED_MODEL_NAME%_helper.rb')]
 68 |         else
 69 |           []
 70 |         end
 71 |       end
 72 | 
 73 |       private
 74 | 
 75 |       def test_files(root_directory)
 76 |         [
 77 |           File.join(root_directory, UNIT_TEST_DIR,  '%MODEL_NAME%_test.rb'),
 78 |           File.join(root_directory, MODEL_TEST_DIR, '%MODEL_NAME%_test.rb'),
 79 |           File.join(root_directory, SPEC_MODEL_DIR, '%MODEL_NAME%_spec.rb')
 80 |         ]
 81 |       end
 82 | 
 83 |       def fixture_files(root_directory)
 84 |         [
 85 |           File.join(root_directory, FIXTURE_TEST_DIR, '%TABLE_NAME%.yml'),
 86 |           File.join(root_directory, FIXTURE_SPEC_DIR, '%TABLE_NAME%.yml'),
 87 |           File.join(root_directory, FIXTURE_TEST_DIR, '%PLURALIZED_MODEL_NAME%.yml'),
 88 |           File.join(root_directory, FIXTURE_SPEC_DIR, '%PLURALIZED_MODEL_NAME%.yml')
 89 |         ]
 90 |       end
 91 | 
 92 |       def scaffold_files(root_directory)
 93 |         [
 94 |           File.join(root_directory, CONTROLLER_TEST_DIR, '%PLURALIZED_MODEL_NAME%_controller_test.rb'),
 95 |           File.join(root_directory, CONTROLLER_SPEC_DIR, '%PLURALIZED_MODEL_NAME%_controller_spec.rb'),
 96 |           File.join(root_directory, REQUEST_SPEC_DIR,    '%PLURALIZED_MODEL_NAME%_spec.rb'),
 97 |           File.join(root_directory, ROUTING_SPEC_DIR,    '%PLURALIZED_MODEL_NAME%_routing_spec.rb')
 98 |         ]
 99 |       end
100 | 
101 |       def factory_files(root_directory)
102 |         [
103 |           File.join(root_directory, EXEMPLARS_TEST_DIR,   '%MODEL_NAME%_exemplar.rb'),
104 |           File.join(root_directory, EXEMPLARS_SPEC_DIR,   '%MODEL_NAME%_exemplar.rb'),
105 |           File.join(root_directory, BLUEPRINTS_TEST_DIR,  '%MODEL_NAME%_blueprint.rb'),
106 |           File.join(root_directory, BLUEPRINTS_SPEC_DIR,  '%MODEL_NAME%_blueprint.rb'),
107 |           File.join(root_directory, FACTORY_BOT_TEST_DIR, '%MODEL_NAME%_factory.rb'),    # (old style)
108 |           File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%MODEL_NAME%_factory.rb'),    # (old style)
109 |           File.join(root_directory, FACTORY_BOT_TEST_DIR, '%TABLE_NAME%.rb'),            # (new style)
110 |           File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%TABLE_NAME%.rb'),            # (new style)
111 |           File.join(root_directory, FACTORY_BOT_TEST_DIR, '%PLURALIZED_MODEL_NAME%.rb'), # (new style)
112 |           File.join(root_directory, FACTORY_BOT_SPEC_DIR, '%PLURALIZED_MODEL_NAME%.rb'), # (new style)
113 |           File.join(root_directory, FABRICATORS_TEST_DIR, '%MODEL_NAME%_fabricator.rb'),
114 |           File.join(root_directory, FABRICATORS_SPEC_DIR, '%MODEL_NAME%_fabricator.rb')
115 |         ]
116 |       end
117 | 
118 |       def serialize_files(root_directory)
119 |         [
120 |           File.join(root_directory, SERIALIZERS_DIR,      '%MODEL_NAME%_serializer.rb'),
121 |           File.join(root_directory, SERIALIZERS_TEST_DIR, '%MODEL_NAME%_serializer_test.rb'),
122 |           File.join(root_directory, SERIALIZERS_SPEC_DIR, '%MODEL_NAME%_serializer_spec.rb')
123 |         ]
124 |       end
125 |     end
126 |   end
127 | end
128 | 


--------------------------------------------------------------------------------
/lib/annotate/annotate_routes.rb:
--------------------------------------------------------------------------------
  1 | # == Annotate Routes
  2 | #
  3 | # Based on:
  4 | #
  5 | #
  6 | #
  7 | # Prepends the output of "rake routes" to the top of your routes.rb file.
  8 | # Yes, it's simple but I'm thick and often need a reminder of what my routes
  9 | # mean.
 10 | #
 11 | # Running this task will replace any existing route comment generated by the
 12 | # task. Best to back up your routes file before running:
 13 | #
 14 | # Author:
 15 | #  Gavin Montague
 16 | #  gavin@leftbrained.co.uk
 17 | #
 18 | # Released under the same license as Ruby. No Support. No Warranty.
 19 | #
 20 | 
 21 | require_relative './annotate_routes/helpers'
 22 | require_relative './annotate_routes/header_generator'
 23 | 
 24 | module AnnotateRoutes
 25 |   class << self
 26 |     def do_annotations(options = {})
 27 |       if routes_file_exist?
 28 |         existing_text = File.read(routes_file)
 29 |         content, header_position = Helpers.strip_annotations(existing_text)
 30 |         new_content = annotate_routes(HeaderGenerator.generate(options), content, header_position, options)
 31 |         new_text = new_content.join("\n")
 32 |         if rewrite_contents(existing_text, new_text, options[:frozen])
 33 |           puts "#{routes_file} was annotated."
 34 |         else
 35 |           puts "#{routes_file} was not changed."
 36 |         end
 37 |       else
 38 |         puts "#{routes_file} could not be found."
 39 |       end
 40 |     end
 41 | 
 42 |     def remove_annotations(options={})
 43 |       if routes_file_exist?
 44 |         existing_text = File.read(routes_file)
 45 |         content, header_position = Helpers.strip_annotations(existing_text)
 46 |         new_content = strip_on_removal(content, header_position)
 47 |         new_text = new_content.join("\n")
 48 |         if rewrite_contents(existing_text, new_text, options[:frozen])
 49 |           puts "Annotations were removed from #{routes_file}."
 50 |         else
 51 |           puts "#{routes_file} was not changed (Annotation did not exist)."
 52 |         end
 53 |       else
 54 |         puts "#{routes_file} could not be found."
 55 |       end
 56 |     end
 57 | 
 58 |     private
 59 | 
 60 |     def routes_file_exist?
 61 |       File.exist?(routes_file)
 62 |     end
 63 | 
 64 |     def routes_file
 65 |       @routes_rb ||= File.join('config', 'routes.rb')
 66 |     end
 67 | 
 68 |     def strip_on_removal(content, header_position)
 69 |       if header_position == :before
 70 |         content.shift while content.first == ''
 71 |       elsif header_position == :after
 72 |         content.pop while content.last == ''
 73 |       end
 74 | 
 75 |       # Make sure we end on a trailing newline.
 76 |       content << '' unless content.last == ''
 77 | 
 78 |       # TODO: If the user buried it in the middle, we should probably see about
 79 |       # TODO: preserving a single line of space between the content above and
 80 |       # TODO: below...
 81 |       content
 82 |     end
 83 | 
 84 |     def rewrite_contents(existing_text, new_text, frozen)
 85 |       content_changed = (existing_text != new_text)
 86 | 
 87 |       if content_changed
 88 |         abort "annotate error. #{routes_file} needs to be updated, but annotate was run with `--frozen`." if frozen
 89 |         File.open(routes_file, 'wb') { |f| f.puts(new_text) }
 90 |       end
 91 | 
 92 |       content_changed
 93 |     end
 94 | 
 95 |     def annotate_routes(header, content, header_position, options = {})
 96 |       magic_comments_map, content = Helpers.extract_magic_comments_from_array(content)
 97 |       if %w(before top).include?(options[:position_in_routes])
 98 |         header = header << '' if content.first != ''
 99 |         magic_comments_map << '' if magic_comments_map.any?
100 |         new_content = magic_comments_map + header + content
101 |       else
102 |         # Ensure we have adequate trailing newlines at the end of the file to
103 |         # ensure a blank line separating the content from the annotation.
104 |         content << '' unless content.last == ''
105 | 
106 |         # We're moving something from the top of the file to the bottom, so ditch
107 |         # the spacer we put in the first time around.
108 |         content.shift if header_position == :before && content.first == ''
109 | 
110 |         new_content = magic_comments_map + content + header
111 |       end
112 | 
113 |       # Make sure we end on a trailing newline.
114 |       new_content << '' unless new_content.last == ''
115 | 
116 |       new_content
117 |     end
118 |   end
119 | end
120 | 


--------------------------------------------------------------------------------
/lib/annotate/annotate_routes/header_generator.rb:
--------------------------------------------------------------------------------
  1 | require_relative './helpers'
  2 | 
  3 | module AnnotateRoutes
  4 |   class HeaderGenerator
  5 |     PREFIX = '== Route Map'.freeze
  6 |     PREFIX_MD = '## Route Map'.freeze
  7 |     HEADER_ROW = ['Prefix', 'Verb', 'URI Pattern', 'Controller#Action'].freeze
  8 | 
  9 |     class << self
 10 |       def generate(options = {})
 11 |         new(options, routes_map(options)).generate
 12 |       end
 13 | 
 14 |       private :new
 15 | 
 16 |       private
 17 | 
 18 |       def routes_map(options)
 19 |         result = `rake routes`.chomp("\n").split(/\n/, -1)
 20 | 
 21 |         # In old versions of Rake, the first line of output was the cwd.  Not so
 22 |         # much in newer ones.  We ditch that line if it exists, and if not, we
 23 |         # keep the line around.
 24 |         result.shift if result.first =~ %r{^\(in \/}
 25 | 
 26 |         ignore_routes = options[:ignore_routes]
 27 |         regexp_for_ignoring_routes = ignore_routes ? /#{ignore_routes}/ : nil
 28 | 
 29 |         # Skip routes which match given regex
 30 |         # Note: it matches the complete line (route_name, path, controller/action)
 31 |         if regexp_for_ignoring_routes
 32 |           result.reject { |line| line =~ regexp_for_ignoring_routes }
 33 |         else
 34 |           result
 35 |         end
 36 |       end
 37 |     end
 38 | 
 39 |     def initialize(options, routes_map)
 40 |       @options = options
 41 |       @routes_map = routes_map
 42 |     end
 43 | 
 44 |     def generate
 45 |       magic_comments_map, contents_without_magic_comments = Helpers.extract_magic_comments_from_array(routes_map)
 46 | 
 47 |       out = []
 48 | 
 49 |       magic_comments_map.each do |magic_comment|
 50 |         out << magic_comment
 51 |       end
 52 |       out << '' if magic_comments_map.any?
 53 | 
 54 |       out << comment(options[:wrapper_open]) if options[:wrapper_open]
 55 | 
 56 |       out << comment(markdown? ? PREFIX_MD : PREFIX) + timestamp_if_required
 57 |       out << comment
 58 |       return out if contents_without_magic_comments.size.zero?
 59 | 
 60 |       maxs = [HEADER_ROW.map(&:size)] + contents_without_magic_comments[1..-1].map { |line| line.split.map(&:size) }
 61 | 
 62 |       if markdown?
 63 |         max = maxs.map(&:max).compact.max
 64 | 
 65 |         out << comment(content(HEADER_ROW, maxs))
 66 |         out << comment(content(['-' * max, '-' * max, '-' * max, '-' * max], maxs))
 67 |       else
 68 |         out << comment(content(contents_without_magic_comments[0], maxs))
 69 |       end
 70 | 
 71 |       out += contents_without_magic_comments[1..-1].map { |line| comment(content(markdown? ? line.split(' ') : line, maxs)) }
 72 |       out << comment(options[:wrapper_close]) if options[:wrapper_close]
 73 | 
 74 |       out
 75 |     end
 76 | 
 77 |     private
 78 | 
 79 |     attr_reader :options, :routes_map
 80 | 
 81 |     def comment(row = '')
 82 |       if row == ''
 83 |         '#'
 84 |       else
 85 |         "# #{row}"
 86 |       end
 87 |     end
 88 | 
 89 |     def content(line, maxs)
 90 |       return line.rstrip unless markdown?
 91 | 
 92 |       line.each_with_index.map { |elem, index| format_line_element(elem, maxs, index) }.join(' | ')
 93 |     end
 94 | 
 95 |     def format_line_element(elem, maxs, index)
 96 |       min_length = maxs.map { |arr| arr[index] }.max || 0
 97 |       format("%-#{min_length}.#{min_length}s", elem.tr('|', '-'))
 98 |     end
 99 | 
100 |     def markdown?
101 |       options[:format_markdown]
102 |     end
103 | 
104 |     def timestamp_if_required(time = Time.now)
105 |       if options[:timestamp]
106 |         time_formatted = time.strftime('%Y-%m-%d %H:%M')
107 |         " (Updated #{time_formatted})"
108 |       else
109 |         ''
110 |       end
111 |     end
112 |   end
113 | end
114 | 


--------------------------------------------------------------------------------
/lib/annotate/annotate_routes/helpers.rb:
--------------------------------------------------------------------------------
 1 | module AnnotateRoutes
 2 |   module Helpers
 3 |     MAGIC_COMMENT_MATCHER = Regexp.new(/(^#\s*encoding:.*)|(^# coding:.*)|(^# -\*- coding:.*)|(^# -\*- encoding\s?:.*)|(^#\s*frozen_string_literal:.+)|(^# -\*- frozen_string_literal\s*:.+-\*-)/).freeze
 4 | 
 5 |     class << self
 6 |       # TODO: write the method doc using ruby rdoc formats
 7 |       # This method returns an array of 'real_content' and 'header_position'.
 8 |       # 'header_position' will either be :before, :after, or
 9 |       # a number.  If the number is > 0, the
10 |       # annotation was found somewhere in the
11 |       # middle of the file.  If the number is
12 |       # zero, no annotation was found.
13 |       def strip_annotations(content)
14 |         real_content = []
15 |         mode = :content
16 |         header_position = 0
17 | 
18 |         content.split(/\n/, -1).each_with_index do |line, line_number|
19 |           if mode == :header && line !~ /\s*#/
20 |             mode = :content
21 |             real_content << line unless line.blank?
22 |           elsif mode == :content
23 |             if line =~ /^\s*#\s*== Route.*$/
24 |               header_position = line_number + 1 # index start's at 0
25 |               mode = :header
26 |             else
27 |               real_content << line
28 |             end
29 |           end
30 |         end
31 | 
32 |         real_content_and_header_position(real_content, header_position)
33 |       end
34 | 
35 |       # @param [Array<String>] content
36 |       # @return [Array<String>] all found magic comments
37 |       # @return [Array<String>] content without magic comments
38 |       def extract_magic_comments_from_array(content_array)
39 |         magic_comments = []
40 |         new_content = []
41 | 
42 |         content_array.each do |row|
43 |           if row =~ MAGIC_COMMENT_MATCHER
44 |             magic_comments << row.strip
45 |           else
46 |             new_content << row
47 |           end
48 |         end
49 | 
50 |         [magic_comments, new_content]
51 |       end
52 | 
53 |       private
54 | 
55 |       def real_content_and_header_position(real_content, header_position)
56 |         # By default assume the annotation was found in the middle of the file
57 | 
58 |         # ... unless we have evidence it was at the beginning ...
59 |         return real_content, :before if header_position == 1
60 | 
61 |         # ... or that it was at the end.
62 |         return real_content, :after if header_position >= real_content.count
63 | 
64 |         # and the default
65 |         return real_content, header_position
66 |       end
67 |     end
68 |   end
69 | end
70 | 


--------------------------------------------------------------------------------
/lib/annotate/constants.rb:
--------------------------------------------------------------------------------
 1 | module Annotate
 2 |   module Constants
 3 |     TRUE_RE = /^(true|t|yes|y|1)$/i.freeze
 4 | 
 5 |     ##
 6 |     # The set of available options to customize the behavior of Annotate.
 7 |     #
 8 |     POSITION_OPTIONS = [
 9 |       :position_in_routes, :position_in_class, :position_in_test,
10 |       :position_in_fixture, :position_in_factory, :position,
11 |       :position_in_serializer
12 |     ].freeze
13 | 
14 |     FLAG_OPTIONS = [
15 |       :show_indexes, :simple_indexes, :include_version, :exclude_tests,
16 |       :exclude_fixtures, :exclude_factories, :ignore_model_sub_dir,
17 |       :format_bare, :format_rdoc, :format_yard, :format_markdown, :sort, :force, :frozen,
18 |       :trace, :timestamp, :exclude_serializers, :classified_sort,
19 |       :show_foreign_keys, :show_complete_foreign_keys,
20 |       :exclude_scaffolds, :exclude_controllers, :exclude_helpers,
21 |       :exclude_sti_subclasses, :ignore_unknown_models, :with_comment, :with_comment_column,
22 |       :show_check_constraints
23 |     ].freeze
24 | 
25 |     OTHER_OPTIONS = [
26 |       :additional_file_patterns, :ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close,
27 |       :wrapper, :routes, :models, :hide_limit_column_types, :hide_default_column_types,
28 |       :ignore_routes, :active_admin
29 |     ].freeze
30 | 
31 |     PATH_OPTIONS = [
32 |       :require, :model_dir, :root_dir
33 |     ].freeze
34 | 
35 |     ALL_ANNOTATE_OPTIONS = [
36 |       POSITION_OPTIONS, FLAG_OPTIONS, OTHER_OPTIONS, PATH_OPTIONS
37 |     ].freeze
38 |   end
39 | end
40 | 


--------------------------------------------------------------------------------
/lib/annotate/helpers.rb:
--------------------------------------------------------------------------------
 1 | module Annotate
 2 |   # Class for holding helper methods. Done to make lib/annotate.rb less bloated.
 3 |   class Helpers
 4 |     class << self
 5 |       def skip_on_migration?
 6 |         ENV['ANNOTATE_SKIP_ON_DB_MIGRATE'] =~ Constants::TRUE_RE || ENV['skip_on_db_migrate'] =~ Constants::TRUE_RE
 7 |       end
 8 | 
 9 |       def include_routes?
10 |         ENV['routes'] =~ Constants::TRUE_RE
11 |       end
12 | 
13 |       def include_models?
14 |         ENV['models'] =~ Constants::TRUE_RE
15 |       end
16 | 
17 |       def true?(val)
18 |         val.present? && Constants::TRUE_RE.match?(val)
19 |       end
20 | 
21 |       def fallback(*args)
22 |         args.detect(&:present?)
23 |       end
24 | 
25 |       def reset_options(options)
26 |         options.flatten.each { |key| ENV[key.to_s] = nil }
27 |       end
28 |     end
29 |   end
30 | end
31 | 


--------------------------------------------------------------------------------
/lib/annotate/parser.rb:
--------------------------------------------------------------------------------
  1 | require 'optparse'
  2 | 
  3 | module Annotate
  4 |   # Class for handling command line arguments
  5 |   class Parser # rubocop:disable Metrics/ClassLength
  6 |     def self.parse(args, env = {})
  7 |       new(args, env).parse
  8 |     end
  9 | 
 10 |     attr_reader :args, :options, :env
 11 | 
 12 |     DEFAULT_OPTIONS = {
 13 |       target_action: :do_annotations,
 14 |       exit: false
 15 |     }.freeze
 16 | 
 17 |     ANNOTATION_POSITIONS = %w[before top after bottom].freeze
 18 |     FILE_TYPE_POSITIONS = %w[position_in_class position_in_factory position_in_fixture position_in_test position_in_routes position_in_serializer].freeze
 19 |     EXCLUSION_LIST = %w[tests fixtures factories serializers].freeze
 20 |     FORMAT_TYPES = %w[bare rdoc yard markdown].freeze
 21 | 
 22 |     def initialize(args, env)
 23 |       @args = args
 24 |       @options = DEFAULT_OPTIONS.dup
 25 |       @env = env
 26 |     end
 27 | 
 28 |     def parse
 29 |       # To split up because right now this method parses and commits
 30 |       parser.parse!(args)
 31 | 
 32 |       commit
 33 | 
 34 |       options
 35 |     end
 36 | 
 37 |     private
 38 | 
 39 |     def parser
 40 |       OptionParser.new do |option_parser|
 41 |         add_options_to_parser(option_parser)
 42 |       end
 43 |     end
 44 | 
 45 |     def commit
 46 |       env.each_pair do |key, value|
 47 |         ENV[key] = value
 48 |       end
 49 |     end
 50 | 
 51 |     def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
 52 |       has_set_position = {}
 53 | 
 54 |       option_parser.banner = 'Usage: annotate [options] [model_file]*'
 55 | 
 56 |       option_parser.on('--additional-file-patterns path1,path2,path3',
 57 |                        Array,
 58 |                        "Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`)") do |additional_file_patterns|
 59 |         ENV['additional_file_patterns'] = additional_file_patterns
 60 |       end
 61 | 
 62 |       option_parser.on('-d',
 63 |                        '--delete',
 64 |                        'Remove annotations from all model files or the routes.rb file') do
 65 |         @options[:target_action] = :remove_annotations
 66 |       end
 67 | 
 68 |       option_parser.on('-p',
 69 |                        '--position [before|top|after|bottom]',
 70 |                        ANNOTATION_POSITIONS,
 71 |                        'Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)') do |position|
 72 |         env['position'] = position
 73 | 
 74 |         FILE_TYPE_POSITIONS.each do |key|
 75 |           env[key] = position unless has_set_position[key]
 76 |         end
 77 |       end
 78 | 
 79 |       option_parser.on('--pc',
 80 |                        '--position-in-class [before|top|after|bottom]',
 81 |                        ANNOTATION_POSITIONS,
 82 |                        'Place the annotations at the top (before) or the bottom (after) of the model file') do |position_in_class|
 83 |         env['position_in_class'] = position_in_class
 84 |         has_set_position['position_in_class'] = true
 85 |       end
 86 | 
 87 |       option_parser.on('--pf',
 88 |                        '--position-in-factory [before|top|after|bottom]',
 89 |                        ANNOTATION_POSITIONS,
 90 |                        'Place the annotations at the top (before) or the bottom (after) of any factory files') do |position_in_factory|
 91 |         env['position_in_factory'] = position_in_factory
 92 |         has_set_position['position_in_factory'] = true
 93 |       end
 94 | 
 95 |       option_parser.on('--px',
 96 |                        '--position-in-fixture [before|top|after|bottom]',
 97 |                        ANNOTATION_POSITIONS,
 98 |                        'Place the annotations at the top (before) or the bottom (after) of any fixture files') do |position_in_fixture|
 99 |         env['position_in_fixture'] = position_in_fixture
100 |         has_set_position['position_in_fixture'] = true
101 |       end
102 | 
103 |       option_parser.on('--pt',
104 |                        '--position-in-test [before|top|after|bottom]',
105 |                        ANNOTATION_POSITIONS,
106 |                        'Place the annotations at the top (before) or the bottom (after) of any test files') do |position_in_test|
107 |         env['position_in_test'] = position_in_test
108 |         has_set_position['position_in_test'] = true
109 |       end
110 | 
111 |       option_parser.on('--pr',
112 |                        '--position-in-routes [before|top|after|bottom]',
113 |                        ANNOTATION_POSITIONS,
114 |                        'Place the annotations at the top (before) or the bottom (after) of the routes.rb file') do |position_in_routes|
115 |         env['position_in_routes'] = position_in_routes
116 |         has_set_position['position_in_routes'] = true
117 |       end
118 | 
119 |       option_parser.on('--ps',
120 |                        '--position-in-serializer [before|top|after|bottom]',
121 |                        ANNOTATION_POSITIONS,
122 |                        'Place the annotations at the top (before) or the bottom (after) of the serializer files') do |position_in_serializer|
123 |         env['position_in_serializer'] = position_in_serializer
124 |         has_set_position['position_in_serializer'] = true
125 |       end
126 | 
127 |       option_parser.on('--w',
128 |                        '--wrapper STR',
129 |                        'Wrap annotation with the text passed as parameter.',
130 |                        'If --w option is used, the same text will be used as opening and closing') do |wrapper|
131 |         env['wrapper'] = wrapper
132 |       end
133 | 
134 |       option_parser.on('--wo',
135 |                        '--wrapper-open STR',
136 |                        'Annotation wrapper opening.') do |wrapper_open|
137 |         env['wrapper_open'] = wrapper_open
138 |       end
139 | 
140 |       option_parser.on('--wc',
141 |                        '--wrapper-close STR',
142 |                        'Annotation wrapper closing') do |wrapper_close|
143 |         env['wrapper_close'] = wrapper_close
144 |       end
145 | 
146 |       option_parser.on('-r',
147 |                        '--routes',
148 |                        "Annotate routes.rb with the output of 'rake routes'") do
149 |         env['routes'] = 'true'
150 |       end
151 | 
152 |       option_parser.on('--models',
153 |                        "Annotate ActiveRecord models") do
154 |         env['models'] = 'true'
155 |       end
156 | 
157 |       option_parser.on('-a',
158 |                        '--active-admin',
159 |                        'Annotate active_admin models') do
160 |         env['active_admin'] = 'true'
161 |       end
162 | 
163 |       option_parser.on('-v',
164 |                        '--version',
165 |                        'Show the current version of this gem') do
166 |         puts "annotate v#{Annotate.version}"
167 |         @options[:exit] = true
168 |       end
169 | 
170 |       option_parser.on('-m',
171 |                        '--show-migration',
172 |                        'Include the migration version number in the annotation') do
173 |         env['include_version'] = 'yes'
174 |       end
175 | 
176 |       option_parser.on('-c',
177 |                        '--show-check-constraints',
178 |                        "List the table's check constraints in the annotation") do
179 |         env['show_check_constraints'] = 'yes'
180 |       end
181 | 
182 |       option_parser.on('-k',
183 |                        '--show-foreign-keys',
184 |                        "List the table's foreign key constraints in the annotation") do
185 |         env['show_foreign_keys'] = 'yes'
186 |       end
187 | 
188 |       option_parser.on('--ck',
189 |                        '--complete-foreign-keys',
190 |                        'Complete foreign key names in the annotation') do
191 |         env['show_foreign_keys'] = 'yes'
192 |         env['show_complete_foreign_keys'] = 'yes'
193 |       end
194 | 
195 |       option_parser.on('-i',
196 |                        '--show-indexes',
197 |                        "List the table's database indexes in the annotation") do
198 |         env['show_indexes'] = 'yes'
199 |       end
200 | 
201 |       option_parser.on('-s',
202 |                        '--simple-indexes',
203 |                        "Concat the column's related indexes in the annotation") do
204 |         env['simple_indexes'] = 'yes'
205 |       end
206 | 
207 |       option_parser.on('--model-dir dir',
208 |                        "Annotate model files stored in dir rather than app/models, separate multiple dirs with commas") do |dir|
209 |         env['model_dir'] = dir
210 |       end
211 | 
212 |       option_parser.on('--root-dir dir',
213 |                        "Annotate files stored within root dir projects, separate multiple dirs with commas") do |dir|
214 |         env['root_dir'] = dir
215 |       end
216 | 
217 |       option_parser.on('--ignore-model-subdirects',
218 |                        "Ignore subdirectories of the models directory") do
219 |         env['ignore_model_sub_dir'] = 'yes'
220 |       end
221 | 
222 |       option_parser.on('--sort',
223 |                        "Sort columns alphabetically, rather than in creation order") do
224 |         env['sort'] = 'yes'
225 |       end
226 | 
227 |       option_parser.on('--classified-sort',
228 |                        "Sort columns alphabetically, but first goes id, then the rest columns, then the timestamp columns and then the association columns") do
229 |         env['classified_sort'] = 'yes'
230 |       end
231 | 
232 |       option_parser.on('-R',
233 |                        '--require path',
234 |                        "Additional file to require before loading models, may be used multiple times") do |path|
235 |         env['require'] = if env['require'].present?
236 |                            "#{env['require']},#{path}"
237 |                          else
238 |                            path
239 |                          end
240 |       end
241 | 
242 |       option_parser.on('-e',
243 |                        '--exclude [tests,fixtures,factories,serializers]',
244 |                        Array,
245 |                        "Do not annotate fixtures, test files, factories, and/or serializers") do |exclusions|
246 |         exclusions ||= EXCLUSION_LIST
247 |         exclusions.each { |exclusion| env["exclude_#{exclusion}"] = 'yes' }
248 |       end
249 | 
250 |       option_parser.on('-f',
251 |                        '--format [bare|rdoc|yard|markdown]',
252 |                        FORMAT_TYPES,
253 |                        'Render Schema Infomation as plain/RDoc/Yard/Markdown') do |format_type|
254 |         env["format_#{format_type}"] = 'yes'
255 |       end
256 | 
257 |       option_parser.on('--force',
258 |                        'Force new annotations even if there are no changes.') do
259 |         env['force'] = 'yes'
260 |       end
261 | 
262 |       option_parser.on('--frozen',
263 |                        'Do not allow to change annotations. Exits non-zero if there are going to be changes to files.') do
264 |         env['frozen'] = 'yes'
265 |       end
266 | 
267 |       option_parser.on('--timestamp',
268 |                        'Include timestamp in (routes) annotation') do
269 |         env['timestamp'] = 'true'
270 |       end
271 | 
272 |       option_parser.on('--trace',
273 |                        'If unable to annotate a file, print the full stack trace, not just the exception message.') do
274 |         env['trace'] = 'yes'
275 |       end
276 | 
277 |       option_parser.on('-I',
278 |                        '--ignore-columns REGEX',
279 |                        "don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`") do |regex|
280 |         env['ignore_columns'] = regex
281 |       end
282 | 
283 |       option_parser.on('--ignore-routes REGEX',
284 |                        "don't annotate routes that match a given REGEX (i.e., `annotate -I '(mobile|resque|pghero)'`") do |regex|
285 |         env['ignore_routes'] = regex
286 |       end
287 | 
288 |       option_parser.on('--hide-limit-column-types VALUES',
289 |                        "don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)") do |values|
290 |         env['hide_limit_column_types'] = values.to_s
291 |       end
292 | 
293 |       option_parser.on('--hide-default-column-types VALUES',
294 |                        "don't show default for given column types, separated by commas (i.e., `json,jsonb,hstore`)") do |values|
295 |         env['hide_default_column_types'] = values.to_s
296 |       end
297 | 
298 |       option_parser.on('--ignore-unknown-models',
299 |                        "don't display warnings for bad model files") do
300 |         env['ignore_unknown_models'] = 'true'
301 |       end
302 | 
303 |       option_parser.on('--with-comment',
304 |                        "include database comments in model annotations") do
305 |         env['with_comment'] = 'true'
306 |       end
307 | 
308 |       option_parser.on('--with-comment-column',
309 |                        "include database comments in model annotations, as its own column, after all others") do
310 |         env['with_comment_column'] = 'true'
311 |       end
312 |     end
313 |   end
314 | end
315 | 


--------------------------------------------------------------------------------
/lib/annotate/tasks.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'rake'
3 | 
4 | # Make tasks visible for Rails also when used as gem.
5 | Dir[File.join(File.dirname(__FILE__), '..', 'tasks', '**/*.rake')].each { |rake| load rake }
6 | Dir[File.join(File.dirname(__FILE__), '..', '..', 'tasks', '**/*.rake')].each { |rake| load rake }
7 | 


--------------------------------------------------------------------------------
/lib/annotate/version.rb:
--------------------------------------------------------------------------------
1 | module Annotate
2 |   def self.version
3 |     '3.2.0'
4 |   end
5 | end
6 | 


--------------------------------------------------------------------------------
/lib/generators/annotate/USAGE:
--------------------------------------------------------------------------------
1 | Add a .rake file that automatically annotates models when you do a db:migrate
2 | in development mode:
3 | 
4 |     rails generate annotate:install
5 | 


--------------------------------------------------------------------------------
/lib/generators/annotate/install_generator.rb:
--------------------------------------------------------------------------------
 1 | require 'annotate'
 2 | 
 3 | module Annotate
 4 |   module Generators
 5 |     class InstallGenerator < Rails::Generators::Base
 6 |       desc 'Copy annotate_models rakefiles for automatic annotation'
 7 |       source_root File.expand_path('templates', __dir__)
 8 | 
 9 |       # copy rake tasks
10 |       def copy_tasks
11 |         template 'auto_annotate_models.rake', 'lib/tasks/auto_annotate_models.rake'
12 |       end
13 |     end
14 |   end
15 | end
16 | 


--------------------------------------------------------------------------------
/lib/generators/annotate/templates/auto_annotate_models.rake:
--------------------------------------------------------------------------------
 1 | # NOTE: only doing this in development as some production environments (Heroku)
 2 | # NOTE: are sensitive to local FS writes, and besides -- it's just not proper
 3 | # NOTE: to have a dev-mode tool do its thing in production.
 4 | if Rails.env.development?
 5 |   require 'annotate'
 6 |   task :set_annotation_options do
 7 |     # You can override any of these by setting an environment variable of the
 8 |     # same name.
 9 |     Annotate.set_defaults(
10 |       'active_admin'                => 'false',
11 |       'additional_file_patterns'    => [],
12 |       'routes'                      => 'false',
13 |       'models'                      => 'true',
14 |       'position_in_routes'          => 'before',
15 |       'position_in_class'           => 'before',
16 |       'position_in_test'            => 'before',
17 |       'position_in_fixture'         => 'before',
18 |       'position_in_factory'         => 'before',
19 |       'position_in_serializer'      => 'before',
20 |       'show_check_constraints'      => 'false',
21 |       'show_foreign_keys'           => 'true',
22 |       'show_complete_foreign_keys'  => 'false',
23 |       'show_indexes'                => 'true',
24 |       'simple_indexes'              => 'false',
25 |       'model_dir'                   => 'app/models',
26 |       'root_dir'                    => '',
27 |       'include_version'             => 'false',
28 |       'require'                     => '',
29 |       'exclude_tests'               => 'false',
30 |       'exclude_fixtures'            => 'false',
31 |       'exclude_factories'           => 'false',
32 |       'exclude_serializers'         => 'false',
33 |       'exclude_scaffolds'           => 'true',
34 |       'exclude_controllers'         => 'true',
35 |       'exclude_helpers'             => 'true',
36 |       'exclude_sti_subclasses'      => 'false',
37 |       'ignore_model_sub_dir'        => 'false',
38 |       'ignore_columns'              => nil,
39 |       'ignore_routes'               => nil,
40 |       'ignore_unknown_models'       => 'false',
41 |       'hide_limit_column_types'     => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(",") %>',
42 |       'hide_default_column_types'   => '<%= AnnotateModels::NO_DEFAULT_COL_TYPES.join(",") %>',
43 |       'skip_on_db_migrate'          => 'false',
44 |       'format_bare'                 => 'true',
45 |       'format_rdoc'                 => 'false',
46 |       'format_yard'                 => 'false',
47 |       'format_markdown'             => 'false',
48 |       'sort'                        => 'false',
49 |       'force'                       => 'false',
50 |       'frozen'                      => 'false',
51 |       'classified_sort'             => 'true',
52 |       'trace'                       => 'false',
53 |       'wrapper_open'                => nil,
54 |       'wrapper_close'               => nil,
55 |       'with_comment'                => 'true',
56 |       'with_comment_column'         => 'false'
57 |     )
58 |   end
59 | 
60 |   Annotate.load_tasks
61 | end
62 | 


--------------------------------------------------------------------------------
/lib/tasks/annotate_models.rake:
--------------------------------------------------------------------------------
 1 | annotate_lib = File.expand_path(File.dirname(File.dirname(__FILE__)))
 2 | 
 3 | unless ENV['is_cli']
 4 |   task :set_annotation_options
 5 |   task annotate_models: :set_annotation_options
 6 | end
 7 | 
 8 | desc 'Add schema information (as comments) to model and fixture files'
 9 | task annotate_models: :environment do
10 |   require "#{annotate_lib}/annotate/annotate_models"
11 |   require "#{annotate_lib}/annotate/active_record_patch"
12 | 
13 |   options = {is_rake: true}
14 |   ENV['position'] = options[:position] = Annotate::Helpers.fallback(ENV['position'], 'before')
15 |   options[:additional_file_patterns] = ENV['additional_file_patterns'] ? ENV['additional_file_patterns'].split(',') : []
16 |   options[:position_in_class] = Annotate::Helpers.fallback(ENV['position_in_class'], ENV['position'])
17 |   options[:position_in_fixture] = Annotate::Helpers.fallback(ENV['position_in_fixture'], ENV['position'])
18 |   options[:position_in_factory] = Annotate::Helpers.fallback(ENV['position_in_factory'], ENV['position'])
19 |   options[:position_in_test] = Annotate::Helpers.fallback(ENV['position_in_test'], ENV['position'])
20 |   options[:position_in_serializer] = Annotate::Helpers.fallback(ENV['position_in_serializer'], ENV['position'])
21 |   options[:show_check_constraints] = Annotate::Helpers.true?(ENV['show_check_constraints'])
22 |   options[:show_foreign_keys] = Annotate::Helpers.true?(ENV['show_foreign_keys'])
23 |   options[:show_complete_foreign_keys] = Annotate::Helpers.true?(ENV['show_complete_foreign_keys'])
24 |   options[:show_indexes] = Annotate::Helpers.true?(ENV['show_indexes'])
25 |   options[:simple_indexes] = Annotate::Helpers.true?(ENV['simple_indexes'])
26 |   options[:model_dir] = ENV['model_dir'] ? ENV['model_dir'].split(',') : ['app/models']
27 |   options[:root_dir] = ENV['root_dir']
28 |   options[:include_version] = Annotate::Helpers.true?(ENV['include_version'])
29 |   options[:require] = ENV['require'] ? ENV['require'].split(',') : []
30 |   options[:exclude_tests] = Annotate::Helpers.true?(ENV['exclude_tests'])
31 |   options[:exclude_factories] = Annotate::Helpers.true?(ENV['exclude_factories'])
32 |   options[:exclude_fixtures] = Annotate::Helpers.true?(ENV['exclude_fixtures'])
33 |   options[:exclude_serializers] = Annotate::Helpers.true?(ENV['exclude_serializers'])
34 |   options[:exclude_scaffolds] = Annotate::Helpers.true?(ENV['exclude_scaffolds'])
35 |   options[:exclude_controllers] = Annotate::Helpers.true?(ENV.fetch('exclude_controllers', 'true'))
36 |   options[:exclude_helpers] = Annotate::Helpers.true?(ENV.fetch('exclude_helpers', 'true'))
37 |   options[:exclude_sti_subclasses] = Annotate::Helpers.true?(ENV['exclude_sti_subclasses'])
38 |   options[:ignore_model_sub_dir] = Annotate::Helpers.true?(ENV['ignore_model_sub_dir'])
39 |   options[:format_bare] = Annotate::Helpers.true?(ENV['format_bare'])
40 |   options[:format_rdoc] = Annotate::Helpers.true?(ENV['format_rdoc'])
41 |   options[:format_yard] = Annotate::Helpers.true?(ENV['format_yard'])
42 |   options[:format_markdown] = Annotate::Helpers.true?(ENV['format_markdown'])
43 |   options[:sort] = Annotate::Helpers.true?(ENV['sort'])
44 |   options[:force] = Annotate::Helpers.true?(ENV['force'])
45 |   options[:frozen] = Annotate::Helpers.true?(ENV['frozen'])
46 |   options[:classified_sort] = Annotate::Helpers.true?(ENV['classified_sort'])
47 |   options[:trace] = Annotate::Helpers.true?(ENV['trace'])
48 |   options[:wrapper_open] = Annotate::Helpers.fallback(ENV['wrapper_open'], ENV['wrapper'])
49 |   options[:wrapper_close] = Annotate::Helpers.fallback(ENV['wrapper_close'], ENV['wrapper'])
50 |   options[:ignore_columns] = ENV.fetch('ignore_columns', nil)
51 |   options[:ignore_routes] = ENV.fetch('ignore_routes', nil)
52 |   options[:hide_limit_column_types] = Annotate::Helpers.fallback(ENV['hide_limit_column_types'], '')
53 |   options[:hide_default_column_types] = Annotate::Helpers.fallback(ENV['hide_default_column_types'], '')
54 |   options[:with_comment] = Annotate::Helpers.true?(ENV['with_comment'])
55 |   options[:with_comment_column] = Annotate::Helpers.true?(ENV['with_comment_column'])
56 |   options[:ignore_unknown_models] = Annotate::Helpers.true?(ENV.fetch('ignore_unknown_models', 'false'))
57 | 
58 |   AnnotateModels.do_annotations(options)
59 | end
60 | 
61 | desc 'Remove schema information from model and fixture files'
62 | task remove_annotation: :environment do
63 |   require "#{annotate_lib}/annotate/annotate_models"
64 |   require "#{annotate_lib}/annotate/active_record_patch"
65 | 
66 |   options = {is_rake: true}
67 |   options[:model_dir] = ENV['model_dir']
68 |   options[:root_dir] = ENV['root_dir']
69 |   options[:require] = ENV['require'] ? ENV['require'].split(',') : []
70 |   options[:trace] = Annotate::Helpers.true?(ENV['trace'])
71 |   AnnotateModels.remove_annotations(options)
72 | end
73 | 


--------------------------------------------------------------------------------
/lib/tasks/annotate_models_migrate.rake:
--------------------------------------------------------------------------------
 1 | # These tasks are added to the project if you install annotate as a Rails plugin.
 2 | # (They are not used to build annotate itself.)
 3 | 
 4 | # Append annotations to Rake tasks for ActiveRecord, so annotate automatically gets
 5 | # run after doing db:migrate.
 6 | 
 7 | migration_tasks = %w(db:migrate db:migrate:up db:migrate:down db:migrate:reset db:migrate:redo db:rollback)
 8 | if defined?(Rails::Application) && Rails.version.split('.').first.to_i >= 6
 9 |   require 'active_record'
10 | 
11 |   databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
12 | 
13 |   ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
14 |     migration_tasks.concat(%w(db:migrate db:migrate:up db:migrate:down).map { |task| "#{task}:#{spec_name}" })
15 |   end
16 | end
17 | 
18 | migration_tasks.each do |task|
19 |   next unless Rake::Task.task_defined?(task)
20 | 
21 |   Rake::Task[task].enhance do
22 |     Rake::Task[Rake.application.top_level_tasks.last].enhance do
23 |       annotation_options_task = if Rake::Task.task_defined?('app:set_annotation_options')
24 |                                   'app:set_annotation_options'
25 |                                 else
26 |                                   'set_annotation_options'
27 |                                 end
28 |       Rake::Task[annotation_options_task].invoke
29 |       Annotate::Migration.update_annotations
30 |     end
31 |   end
32 | end
33 | 
34 | module Annotate
35 |   class Migration
36 |     @@working = false
37 | 
38 |     def self.update_annotations
39 |       unless @@working || Annotate::Helpers.skip_on_migration?
40 |         @@working = true
41 | 
42 |         self.update_models if Annotate::Helpers.include_models?
43 |         self.update_routes if Annotate::Helpers.include_routes?
44 |       end
45 |     end
46 | 
47 |     def self.update_models
48 |       if Rake::Task.task_defined?("annotate_models")
49 |         Rake::Task["annotate_models"].invoke
50 |       elsif Rake::Task.task_defined?("app:annotate_models")
51 |         Rake::Task["app:annotate_models"].invoke
52 |       end
53 |     end
54 | 
55 |     def self.update_routes
56 |       if Rake::Task.task_defined?("annotate_routes")
57 |         Rake::Task["annotate_routes"].invoke
58 |       elsif Rake::Task.task_defined?("app:annotate_routes")
59 |         Rake::Task["app:annotate_routes"].invoke
60 |       end
61 |     end
62 |   end
63 | end
64 | 


--------------------------------------------------------------------------------
/lib/tasks/annotate_routes.rake:
--------------------------------------------------------------------------------
 1 | annotate_lib = File.expand_path(File.dirname(File.dirname(__FILE__)))
 2 | 
 3 | unless ENV['is_cli']
 4 |   task :set_annotation_options
 5 |   task annotate_routes: :set_annotation_options
 6 | end
 7 | 
 8 | desc "Adds the route map to routes.rb"
 9 | task :annotate_routes => :environment do
10 |   require "#{annotate_lib}/annotate/annotate_routes"
11 | 
12 |   options={}
13 |   ENV['position'] = options[:position] = Annotate::Helpers.fallback(ENV['position'], 'before')
14 |   options[:position_in_routes] = Annotate::Helpers.fallback(ENV['position_in_routes'], ENV['position'])
15 |   options[:ignore_routes] = Annotate::Helpers.fallback(ENV['ignore_routes'],  nil)
16 |   options[:require] = ENV['require'] ? ENV['require'].split(',') : []
17 |   options[:frozen] = Annotate::Helpers.true?(ENV['frozen'])
18 |   options[:wrapper_open] = Annotate::Helpers.fallback(ENV['wrapper_open'], ENV['wrapper'])
19 |   options[:wrapper_close] = Annotate::Helpers.fallback(ENV['wrapper_close'], ENV['wrapper'])
20 |   AnnotateRoutes.do_annotations(options)
21 | end
22 | 
23 | desc "Removes the route map from routes.rb"
24 | task :remove_routes => :environment do
25 |   annotate_lib = File.expand_path(File.dirname(File.dirname(__FILE__)))
26 |   require "#{annotate_lib}/annotate/annotate_routes"
27 | 
28 |   options={}
29 |   options[:require] = ENV['require'] ? ENV['require'].split(',') : []
30 |   AnnotateRoutes.remove_annotations(options)
31 | end
32 | 


--------------------------------------------------------------------------------
/potato.md:
--------------------------------------------------------------------------------
 1 | Colons can be used to align columns.
 2 | 
 3 | | Tables        | Are           | Cool  |
 4 | | ------------- |:-------------:| -----:|
 5 | | col 3 is      | right-aligned | $1600 |
 6 | | col 2 is      | centered      |   $12 |
 7 | | zebra stripes | are neat      |    $1 |
 8 | 
 9 | There must be at least 3 dashes separating each header cell.
10 | The outer pipes (|) are optional, and you don't need to make the
11 | raw Markdown line up prettily. You can also use inline Markdown.
12 | 
13 | Markdown | Less | Pretty
14 | --- | --- | ---
15 | *Still* | `renders` | **nicely**
16 | 1 | 2 | 3
17 | 
18 | 
19 |  ## Route Map
20 | 
21 |   Prefix    | Verb       | URI Pattern     | Controller#Action    
22 |   --------- | ---------- | --------------- | --------------------
23 |   myaction1 | GET        | /url1(.:format) | mycontroller1#action
24 |   myaction2 | POST       | /url2(.:format) | mycontroller2#action
25 |   myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action \n")
26 | 
27 | 
28 | 
29 |  Table name: `users`
30 | 
31 |  ### Columns
32 | 
33 |  Name                    | Type               | Attributes
34 |  ----------------------- | ------------------ | ---------------------------
35 |  **`id`**                | `integer`          | `not null, primary key`
36 |  **`foreign_thing_id`**  | `integer`          | `not null`
37 | 
38 |  ### Foreign Keys
39 | 
40 |  * `fk_rails_...` (_ON DELETE => on_delete_value ON UPDATE => on_update_value_):
41 |      * **`foreign_thing_id => foreign_things.id`**
42 | 


--------------------------------------------------------------------------------
/spec/lib/annotate/annotate_models/file_patterns_spec.rb:
--------------------------------------------------------------------------------
  1 | require_relative '../../../spec_helper'
  2 | require 'annotate/annotate_models'
  3 | 
  4 | describe AnnotateModels::FilePatterns do
  5 |   describe '.by_pattern' do
  6 |     subject { AnnotateModels::FilePatterns.generate(root_directory, pattern_type, options) }
  7 | 
  8 |     let(:root_directory) { '/root' }
  9 |     let(:options) { {} }
 10 | 
 11 |     context 'when pattern_type is "test"' do
 12 |       let(:pattern_type) { 'test' }
 13 | 
 14 |       it 'returns patterns of test files' do
 15 |         is_expected.to eq([
 16 |           '/root/test/unit/%MODEL_NAME%_test.rb',
 17 |           '/root/test/models/%MODEL_NAME%_test.rb',
 18 |           '/root/spec/models/%MODEL_NAME%_spec.rb'
 19 |         ])
 20 |       end
 21 |     end
 22 | 
 23 |     context 'when pattern_type is "fixture"' do
 24 |       let(:pattern_type) { 'fixture' }
 25 | 
 26 |       it 'returns patterns of fixture files' do
 27 |         is_expected.to eq([
 28 |           '/root/test/fixtures/%TABLE_NAME%.yml',
 29 |           '/root/spec/fixtures/%TABLE_NAME%.yml',
 30 |           '/root/test/fixtures/%PLURALIZED_MODEL_NAME%.yml',
 31 |           '/root/spec/fixtures/%PLURALIZED_MODEL_NAME%.yml'
 32 |         ])
 33 |       end
 34 |     end
 35 | 
 36 |     context 'when pattern_type is "scaffold"' do
 37 |       let(:pattern_type) { 'scaffold' }
 38 | 
 39 |       it 'returns patterns of scaffold files' do
 40 |         is_expected.to eq([
 41 |           '/root/test/controllers/%PLURALIZED_MODEL_NAME%_controller_test.rb',
 42 |           '/root/spec/controllers/%PLURALIZED_MODEL_NAME%_controller_spec.rb',
 43 |           '/root/spec/requests/%PLURALIZED_MODEL_NAME%_spec.rb',
 44 |           '/root/spec/routing/%PLURALIZED_MODEL_NAME%_routing_spec.rb'
 45 |         ])
 46 |       end
 47 |     end
 48 | 
 49 |     context 'when pattern_type is "factory"' do
 50 |       let(:pattern_type) { 'factory' }
 51 | 
 52 |       it 'returns patterns of factory files' do
 53 |         is_expected.to eq([
 54 |           '/root/test/exemplars/%MODEL_NAME%_exemplar.rb',
 55 |           '/root/spec/exemplars/%MODEL_NAME%_exemplar.rb',
 56 |           '/root/test/blueprints/%MODEL_NAME%_blueprint.rb',
 57 |           '/root/spec/blueprints/%MODEL_NAME%_blueprint.rb',
 58 |           '/root/test/factories/%MODEL_NAME%_factory.rb',
 59 |           '/root/spec/factories/%MODEL_NAME%_factory.rb',
 60 |           '/root/test/factories/%TABLE_NAME%.rb',
 61 |           '/root/spec/factories/%TABLE_NAME%.rb',
 62 |           '/root/test/factories/%PLURALIZED_MODEL_NAME%.rb',
 63 |           '/root/spec/factories/%PLURALIZED_MODEL_NAME%.rb',
 64 |           '/root/test/fabricators/%MODEL_NAME%_fabricator.rb',
 65 |           '/root/spec/fabricators/%MODEL_NAME%_fabricator.rb'
 66 |         ])
 67 |       end
 68 |     end
 69 | 
 70 |     context 'when pattern_type is "serializer"' do
 71 |       let(:pattern_type) { 'serializer' }
 72 | 
 73 |       it 'returns patterns of serializer files' do
 74 |         is_expected.to eq([
 75 |           '/root/app/serializers/%MODEL_NAME%_serializer.rb',
 76 |           '/root/test/serializers/%MODEL_NAME%_serializer_test.rb',
 77 |           '/root/spec/serializers/%MODEL_NAME%_serializer_spec.rb'
 78 |         ])
 79 |       end
 80 |     end
 81 | 
 82 |     context 'when pattern_type is "additional_file_patterns"' do
 83 |       let(:pattern_type) { 'additional_file_patterns' }
 84 | 
 85 |       context 'when additional_file_patterns is specified in the options' do
 86 |         let(:additional_file_patterns) do
 87 |           [
 88 |             '%PLURALIZED_MODEL_NAME%/**/*.rb',
 89 |             '%PLURALIZED_MODEL_NAME%/*_form'
 90 |           ]
 91 |         end
 92 | 
 93 |         let(:options) { { additional_file_patterns: additional_file_patterns } }
 94 | 
 95 |         it 'returns additional_file_patterns in the argument "options"' do
 96 |           is_expected.to eq(additional_file_patterns)
 97 |         end
 98 |       end
 99 | 
100 |       context 'when additional_file_patterns is not specified in the options' do
101 |         let(:options) { {} }
102 | 
103 |         it 'returns an empty array' do
104 |           is_expected.to eq([])
105 |         end
106 |       end
107 |     end
108 | 
109 |     context 'when pattern_type is "controller"' do
110 |       let(:pattern_type) { 'controller' }
111 | 
112 |       it 'returns patterns of controller files' do
113 |         is_expected.to eq([
114 |           '/root/app/controllers/%PLURALIZED_MODEL_NAME%_controller.rb'
115 |         ])
116 |       end
117 |     end
118 | 
119 |     context 'when pattern_type is "admin"' do
120 |       let(:pattern_type) { 'admin' }
121 | 
122 |       it 'returns both singular and pluralized model names' do
123 |         is_expected.to eq(['/root/app/admin/%MODEL_NAME%.rb', '/root/app/admin/%PLURALIZED_MODEL_NAME%.rb'])
124 |       end
125 |     end
126 | 
127 |     context 'when pattern_type is "helper"' do
128 |       let(:pattern_type) { 'helper' }
129 | 
130 |       it 'returns patterns of helper files' do
131 |         is_expected.to eq([
132 |           '/root/app/helpers/%PLURALIZED_MODEL_NAME%_helper.rb'
133 |         ])
134 |       end
135 |     end
136 |   end
137 | end
138 | 


--------------------------------------------------------------------------------
/spec/lib/annotate/annotate_routes_spec.rb:
--------------------------------------------------------------------------------
  1 | require_relative '../../spec_helper'
  2 | require 'annotate/annotate_routes'
  3 | 
  4 | describe AnnotateRoutes do
  5 |   ROUTE_FILE = 'config/routes.rb'.freeze
  6 | 
  7 |   MESSAGE_ANNOTATED = "#{ROUTE_FILE} was annotated.".freeze
  8 |   MESSAGE_UNCHANGED = "#{ROUTE_FILE} was not changed.".freeze
  9 |   MESSAGE_NOT_FOUND = "#{ROUTE_FILE} could not be found.".freeze
 10 |   MESSAGE_REMOVED = "Annotations were removed from #{ROUTE_FILE}.".freeze
 11 | 
 12 |   MAGIC_COMMENTS = [
 13 |     '# encoding: UTF-8',
 14 |     '# coding: UTF-8',
 15 |     '# -*- coding: UTF-8 -*-',
 16 |     '#encoding: utf-8',
 17 |     '# encoding: utf-8',
 18 |     '# -*- encoding : utf-8 -*-',
 19 |     "# encoding: utf-8\n# frozen_string_literal: true",
 20 |     "# frozen_string_literal: true\n# encoding: utf-8",
 21 |     '# frozen_string_literal: true',
 22 |     '#frozen_string_literal: false',
 23 |     '# -*- frozen_string_literal : true -*-'
 24 |   ].freeze unless const_defined?(:MAGIC_COMMENTS)
 25 | 
 26 |   let :stubs do
 27 |     {}
 28 |   end
 29 | 
 30 |   let :mock_file do
 31 |     double(File, stubs)
 32 |   end
 33 | 
 34 |   describe '.do_annotations' do
 35 |     context 'When "config/routes.rb" does not exist' do
 36 |       before :each do
 37 |         expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(false).once
 38 |       end
 39 | 
 40 |       it 'does not annotates any file' do
 41 |         expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_NOT_FOUND)
 42 | 
 43 |         AnnotateRoutes.do_annotations
 44 |       end
 45 |     end
 46 | 
 47 |     context 'When "config/routes.rb" exists' do
 48 |       before :each do
 49 |         expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(true).once
 50 |         expect(File).to receive(:read).with(ROUTE_FILE).and_return(route_file_content).once
 51 | 
 52 |         expect(AnnotateRoutes::HeaderGenerator).to receive(:`).with('rake routes').and_return(rake_routes_result).once
 53 |       end
 54 | 
 55 |       context 'When the result of `rake routes` is present' do
 56 |         context 'When the result of `rake routes` does not contain Rake version' do
 57 |           context 'When the file does not contain magic comment' do
 58 |             let :rake_routes_result do
 59 |               <<-EOS
 60 |                                       Prefix Verb       URI Pattern                                               Controller#Action
 61 |                                    myaction1 GET        /url1(.:format)                                           mycontroller1#action
 62 |                                    myaction2 POST       /url2(.:format)                                           mycontroller2#action
 63 |                                    myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
 64 |               EOS
 65 |             end
 66 | 
 67 |             let :route_file_content do
 68 |               ''
 69 |             end
 70 | 
 71 |             context 'When the file does not contain annotation yet' do
 72 |               context 'When no option is passed' do
 73 |                 let :expected_result do
 74 |                   <<~EOS
 75 | 
 76 |                     # == Route Map
 77 |                     #
 78 |                     #                                       Prefix Verb       URI Pattern                                               Controller#Action
 79 |                     #                                    myaction1 GET        /url1(.:format)                                           mycontroller1#action
 80 |                     #                                    myaction2 POST       /url2(.:format)                                           mycontroller2#action
 81 |                     #                                    myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
 82 |                   EOS
 83 |                 end
 84 | 
 85 |                 it 'annotates normally' do
 86 |                   expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
 87 |                   expect(mock_file).to receive(:puts).with(expected_result).once
 88 |                   expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
 89 | 
 90 |                   AnnotateRoutes.do_annotations
 91 |                 end
 92 |               end
 93 | 
 94 |               context 'When the option "format_markdown" is passed' do
 95 |                 let :expected_result do
 96 |                   <<~EOS
 97 | 
 98 |                     # ## Route Map
 99 |                     #
100 |                     # Prefix    | Verb       | URI Pattern     | Controller#Action   
101 |                     # --------- | ---------- | --------------- | --------------------
102 |                     # myaction1 | GET        | /url1(.:format) | mycontroller1#action
103 |                     # myaction2 | POST       | /url2(.:format) | mycontroller2#action
104 |                     # myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action
105 |                   EOS
106 |                 end
107 | 
108 |                 it 'annotates in Markdown format' do
109 |                   expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
110 |                   expect(mock_file).to receive(:puts).with(expected_result).once
111 |                   expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
112 | 
113 |                   AnnotateRoutes.do_annotations(format_markdown: true)
114 |                 end
115 |               end
116 | 
117 |               context 'When the options "wrapper_open" and "wrapper_close" are passed' do
118 |                 let :expected_result do
119 |                   <<~EOS
120 | 
121 |                     # START
122 |                     # == Route Map
123 |                     #
124 |                     #                                       Prefix Verb       URI Pattern                                               Controller#Action
125 |                     #                                    myaction1 GET        /url1(.:format)                                           mycontroller1#action
126 |                     #                                    myaction2 POST       /url2(.:format)                                           mycontroller2#action
127 |                     #                                    myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
128 |                     # END
129 |                   EOS
130 |                 end
131 | 
132 |                 it 'annotates and wraps annotation with specified words' do
133 |                   expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
134 |                   expect(mock_file).to receive(:puts).with(expected_result).once
135 |                   expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
136 | 
137 |                   AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END')
138 |                 end
139 |               end
140 |             end
141 |           end
142 | 
143 |           context 'When the file contains magic comments' do
144 |             MAGIC_COMMENTS.each do |magic_comment|
145 |               describe "magic comment: #{magic_comment.inspect}" do
146 |                 let :route_file_content do
147 |                   <<~EOS
148 |                     #{magic_comment}
149 |                   EOS
150 |                 end
151 | 
152 |                 let :rake_routes_result do
153 |                   <<-EOS
154 |                                       Prefix Verb       URI Pattern                                               Controller#Action
155 |                                    myaction1 GET        /url1(.:format)                                           mycontroller1#action
156 |                                    myaction2 POST       /url2(.:format)                                           mycontroller2#action
157 |                                    myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
158 |                   EOS
159 |                 end
160 | 
161 |                 context 'When the file does not contain annotation yet' do
162 |                   context 'When no option is passed' do
163 |                     let :expected_result do
164 |                       <<~EOS
165 |                         #{magic_comment}
166 | 
167 |                         # == Route Map
168 |                         #
169 |                         #                                       Prefix Verb       URI Pattern                                               Controller#Action
170 |                         #                                    myaction1 GET        /url1(.:format)                                           mycontroller1#action
171 |                         #                                    myaction2 POST       /url2(.:format)                                           mycontroller2#action
172 |                         #                                    myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
173 |                       EOS
174 |                     end
175 | 
176 |                     it 'annotates normally' do
177 |                       expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
178 |                       expect(mock_file).to receive(:puts).with(expected_result).once
179 |                       expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
180 | 
181 |                       AnnotateRoutes.do_annotations
182 |                     end
183 |                   end
184 | 
185 |                   context 'When the option "format_markdown" is passed' do
186 |                     let :expected_result do
187 |                       <<~EOS
188 |                         #{magic_comment}
189 | 
190 |                         # ## Route Map
191 |                         #
192 |                         # Prefix    | Verb       | URI Pattern     | Controller#Action   
193 |                         # --------- | ---------- | --------------- | --------------------
194 |                         # myaction1 | GET        | /url1(.:format) | mycontroller1#action
195 |                         # myaction2 | POST       | /url2(.:format) | mycontroller2#action
196 |                         # myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action
197 |                       EOS
198 |                     end
199 | 
200 |                     it 'annotates in Markdown format' do
201 |                       expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
202 |                       expect(mock_file).to receive(:puts).with(expected_result).once
203 |                       expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
204 | 
205 |                       AnnotateRoutes.do_annotations(format_markdown: true)
206 |                     end
207 |                   end
208 | 
209 |                   context 'When the options "wrapper_open" and "wrapper_close" are passed' do
210 |                     let :expected_result do
211 |                       <<~EOS
212 |                         #{magic_comment}
213 | 
214 |                         # START
215 |                         # == Route Map
216 |                         #
217 |                         #                                       Prefix Verb       URI Pattern                                               Controller#Action
218 |                         #                                    myaction1 GET        /url1(.:format)                                           mycontroller1#action
219 |                         #                                    myaction2 POST       /url2(.:format)                                           mycontroller2#action
220 |                         #                                    myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
221 |                         # END
222 |                       EOS
223 |                     end
224 | 
225 |                     it 'annotates and wraps annotation with specified words' do
226 |                       expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
227 |                       expect(mock_file).to receive(:puts).with(expected_result).once
228 |                       expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
229 | 
230 |                       AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END')
231 |                     end
232 |                   end
233 |                 end
234 |               end
235 |             end
236 |           end
237 |         end
238 | 
239 |         context 'When the result of `rake routes` contains Rake version' do
240 |           context 'with older Rake versions' do
241 |             let :rake_routes_result do
242 |               <<~EOS.chomp
243 |                 (in /bad/line)
244 |                 good line
245 |               EOS
246 |             end
247 | 
248 |             context 'When the route file does not end with an empty line' do
249 |               let :route_file_content do
250 |                 <<~EOS.chomp
251 |                   ActionController::Routing...
252 |                   foo
253 |                 EOS
254 |               end
255 | 
256 |               let :expected_result do
257 |                 <<~EOS
258 |                   ActionController::Routing...
259 |                   foo
260 | 
261 |                   # == Route Map
262 |                   #
263 |                   # good line
264 |                 EOS
265 |               end
266 | 
267 |               it 'annotates with an empty line' do
268 |                 expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
269 |                 expect(mock_file).to receive(:puts).with(expected_result).once
270 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
271 | 
272 |                 AnnotateRoutes.do_annotations
273 |               end
274 |             end
275 | 
276 |             context 'When the route file ends with an empty line' do
277 |               let :route_file_content do
278 |                 <<~EOS
279 |                   ActionController::Routing...
280 |                   foo
281 |                 EOS
282 |               end
283 | 
284 |               let :expected_result do
285 |                 <<~EOS
286 |                   ActionController::Routing...
287 |                   foo
288 | 
289 |                   # == Route Map
290 |                   #
291 |                   # good line
292 |                 EOS
293 |               end
294 | 
295 |               it 'annotates without an empty line' do
296 |                 expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
297 |                 expect(mock_file).to receive(:puts).with(expected_result).once
298 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
299 | 
300 |                 AnnotateRoutes.do_annotations
301 |               end
302 |             end
303 |           end
304 | 
305 |           context 'with newer Rake versions' do
306 |             let :rake_routes_result do
307 |               <<~EOS.chomp
308 |                 another good line
309 |                 good line
310 |               EOS
311 |             end
312 | 
313 |             context 'When the route file does not end with an empty line' do
314 |               context 'When no option is passed' do
315 |                 let :route_file_content do
316 |                   <<~EOS.chomp
317 |                     ActionController::Routing...
318 |                     foo
319 |                   EOS
320 |                 end
321 | 
322 |                 let :expected_result do
323 |                   <<~EOS
324 |                     ActionController::Routing...
325 |                     foo
326 | 
327 |                     # == Route Map
328 |                     #
329 |                     # another good line
330 |                     # good line
331 |                   EOS
332 |                 end
333 | 
334 |                 it 'annotates with an empty line' do
335 |                   expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
336 |                   expect(mock_file).to receive(:puts).with(expected_result).once
337 |                   expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
338 | 
339 |                   AnnotateRoutes.do_annotations
340 |                 end
341 |               end
342 |             end
343 | 
344 |             context 'When the route file ends with an empty line' do
345 |               let :route_file_content do
346 |                 <<~EOS
347 |                   ActionController::Routing...
348 |                   foo
349 |                 EOS
350 |               end
351 | 
352 |               let :expected_result do
353 |                 <<~EOS
354 |                   ActionController::Routing...
355 |                   foo
356 | 
357 |                   # == Route Map
358 |                   #
359 |                   # another good line
360 |                   # good line
361 |                 EOS
362 |               end
363 | 
364 |               it 'annotates without an empty line' do
365 |                 expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
366 |                 expect(mock_file).to receive(:puts).with(expected_result).once
367 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
368 | 
369 |                 AnnotateRoutes.do_annotations
370 |               end
371 |             end
372 | 
373 |             context 'When option "timestamp" is passed' do
374 |               let :route_file_content do
375 |                 <<~EOS.chomp
376 |                   ActionController::Routing...
377 |                   foo
378 |                 EOS
379 |               end
380 | 
381 |               let :expected_result do
382 |                 /ActionController::Routing...\nfoo\n\n# == Route Map \(Updated \d{4}-\d{2}-\d{2} \d{2}:\d{2}\)\n#\n# another good line\n# good line\n/
383 |               end
384 | 
385 |               it 'annotates with the timestamp and an empty line' do
386 |                 expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
387 |                 expect(mock_file).to receive(:puts).with(expected_result).once
388 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
389 | 
390 |                 AnnotateRoutes.do_annotations timestamp: true
391 |               end
392 |             end
393 |           end
394 |         end
395 |       end
396 | 
397 |       context 'When the result of `rake routes` is blank' do
398 |         let :rake_routes_result do
399 |           ''
400 |         end
401 | 
402 |         context 'When the file does not contain magic comment' do
403 |           context 'When the file does not contain annotation yet' do
404 |             let :route_file_content do
405 |               ''
406 |             end
407 | 
408 |             context 'When no option is specified' do
409 |               let :expected_result do
410 |                 <<~EOS
411 | 
412 |                   # == Route Map
413 |                   #
414 |                 EOS
415 |               end
416 | 
417 |               it 'inserts annotations' do
418 |                 expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
419 |                 expect(mock_file).to receive(:puts).with(expected_result).once
420 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
421 | 
422 |                 AnnotateRoutes.do_annotations
423 |               end
424 |             end
425 | 
426 |             context 'When the option "ignore_routes" is specified' do
427 |               let :expected_result do
428 |                 <<~EOS
429 | 
430 |                   # == Route Map
431 |                   #
432 |                 EOS
433 |               end
434 | 
435 |               it 'inserts annotations' do
436 |                 expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
437 |                 expect(mock_file).to receive(:puts).with(expected_result).once
438 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
439 | 
440 |                 AnnotateRoutes.do_annotations(ignore_routes: 'my_route')
441 |               end
442 |             end
443 | 
444 |             context 'When the option "position_in_routes" is specified as "top"' do
445 |               let :expected_result do
446 |                 <<~EOS
447 |                   # == Route Map
448 |                   #
449 |                 EOS
450 |               end
451 | 
452 |               it 'inserts annotations' do
453 |                 expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
454 |                 expect(mock_file).to receive(:puts).with(expected_result).once
455 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
456 | 
457 |                 AnnotateRoutes.do_annotations(position_in_routes: 'top')
458 |               end
459 |             end
460 |           end
461 | 
462 |           context 'When the file already contains annotation' do
463 |             context 'When no option is specified' do
464 |               let :route_file_content do
465 |                 <<~EOS
466 | 
467 |                   # == Route Map
468 |                   #
469 |                 EOS
470 |               end
471 | 
472 |               it 'should skip annotations if file does already contain annotation' do
473 |                 expect(File).not_to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
474 |                 expect(mock_file).not_to receive(:puts)
475 |                 expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_UNCHANGED).once
476 | 
477 |                 AnnotateRoutes.do_annotations
478 |               end
479 |             end
480 |           end
481 |         end
482 | 
483 |         context 'When the file contains magic comments' do
484 |           MAGIC_COMMENTS.each do |magic_comment|
485 |             describe "magic comment: #{magic_comment.inspect}" do
486 |               let :route_file_content do
487 |                 <<~EOS
488 |                   #{magic_comment}
489 |                   Something
490 |                 EOS
491 |               end
492 | 
493 |               context 'When the file does not contain annotation yet' do
494 |                 context 'When the option "position_in_routes" is specified as "top"' do
495 |                   let :expected_result do
496 |                     <<~EOS
497 |                       #{magic_comment}
498 | 
499 |                       # == Route Map
500 |                       #
501 | 
502 |                       Something
503 |                     EOS
504 |                   end
505 | 
506 |                   it 'leaves magic comment on top and adds an empty line between magic comment and annotation' do
507 |                     expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
508 |                     expect(mock_file).to receive(:puts).with(expected_result).once
509 |                     expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
510 | 
511 |                     AnnotateRoutes.do_annotations(position_in_routes: 'top')
512 |                   end
513 |                 end
514 | 
515 |                 context 'When the option "position_in_routes" is specified as "bottom"' do
516 |                   let :expected_result do
517 |                     <<~EOS
518 |                       #{magic_comment}
519 |                       Something
520 | 
521 |                       # == Route Map
522 |                       #
523 |                     EOS
524 |                   end
525 | 
526 |                   it 'leaves magic comment on top and adds an empty line between magic comment and annotation' do
527 |                     expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
528 |                     expect(mock_file).to receive(:puts).with(expected_result).once
529 |                     expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once
530 | 
531 |                     AnnotateRoutes.do_annotations(position_in_routes: 'bottom')
532 |                   end
533 |                 end
534 |               end
535 | 
536 |               context 'When the file already contains annotation' do
537 |                 let :route_file_content do
538 |                   <<~EOS
539 |                     #{magic_comment}
540 | 
541 |                     # == Route Map
542 |                     #
543 |                   EOS
544 |                 end
545 | 
546 |                 it 'skips annotations' do
547 |                   expect(File).not_to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
548 |                   expect(mock_file).not_to receive(:puts)
549 |                   expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_UNCHANGED).once
550 | 
551 |                   AnnotateRoutes.do_annotations
552 |                 end
553 |               end
554 |             end
555 |           end
556 |         end
557 |       end
558 |     end
559 | 
560 |     describe 'frozen option' do
561 |       let :aborted_message do
562 |         "annotate error. #{ROUTE_FILE} needs to be updated, but annotate was run with `--frozen`."
563 |       end
564 | 
565 |       let :rake_routes_result do
566 |         <<-EOS
567 |                                 Prefix Verb       URI Pattern                                               Controller#Action
568 |                              myaction1 GET        /url1(.:format)                                           mycontroller1#action
569 |                              myaction2 POST       /url2(.:format)                                           mycontroller2#action
570 |                              myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
571 |         EOS
572 |       end
573 | 
574 |       before :each do
575 |         expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(true).once
576 |         expect(File).to receive(:read).with(ROUTE_FILE).and_return(route_file_content).once
577 | 
578 |         expect(AnnotateRoutes::HeaderGenerator).to receive(:`).with('rake routes').and_return(rake_routes_result).once
579 |       end
580 | 
581 |       context 'when annotation does not exists' do
582 |         let :route_file_content do
583 |           ''
584 |         end
585 | 
586 |         it 'aborts' do
587 |           expect { AnnotateRoutes.do_annotations(frozen: true) }.to raise_error SystemExit, aborted_message
588 |         end
589 |       end
590 | 
591 |       context 'when annotation exists but is not updated' do
592 |         let :route_file_content do
593 |           <<~EOS
594 |             # == Route Map
595 |             #
596 |             #                                 Prefix Verb       URI Pattern                                               Controller#Action
597 |             #                              myaction2 POST       /url2(.:format)                                           mycontroller2#action
598 |             #                              myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
599 |           EOS
600 |         end
601 | 
602 |         it 'aborts' do
603 |           expect { AnnotateRoutes.do_annotations(frozen: true) }.to raise_error SystemExit, aborted_message
604 |         end
605 |       end
606 | 
607 |       context 'when annotation exists and is already updated' do
608 |         let :route_file_content do
609 |           <<~EOS
610 |             # == Route Map
611 |             #
612 |             #                                 Prefix Verb       URI Pattern                                               Controller#Action
613 |             #                              myaction1 GET        /url1(.:format)                                           mycontroller1#action
614 |             #                              myaction2 POST       /url2(.:format)                                           mycontroller2#action
615 |             #                              myaction3 DELETE|GET /url3(.:format)                                           mycontroller3#action
616 |           EOS
617 |         end
618 | 
619 |         it 'does NOT abort' do
620 |           expect { AnnotateRoutes.do_annotations(frozen: true) }.not_to raise_error
621 |         end
622 |       end
623 |     end
624 |   end
625 | 
626 |   describe '.remove_annotations' do
627 |     before :each do
628 |       expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(true).once
629 |       expect(File).to receive(:read).with(ROUTE_FILE).and_return(route_file_content).once
630 |       expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once
631 |     end
632 | 
633 |     context 'When trailing annotation exists' do
634 |       let :route_file_content do
635 |         <<~EOS
636 | 
637 | 
638 | 
639 |           ActionController::Routing...
640 |           foo
641 | 
642 | 
643 |           # == Route Map
644 |           #
645 |           # another good line
646 |           # good line
647 |         EOS
648 |       end
649 | 
650 |       let :expected_result do
651 |         <<~EOS
652 | 
653 | 
654 | 
655 |           ActionController::Routing...
656 |           foo
657 |         EOS
658 |       end
659 | 
660 |       it 'removes trailing annotation and trim trailing newlines, but leave leading newlines alone' do
661 |         expect(mock_file).to receive(:puts).with(expected_result).once
662 |         expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_REMOVED).once
663 | 
664 |         AnnotateRoutes.remove_annotations
665 |       end
666 |     end
667 | 
668 |     context 'When prepended annotation exists' do
669 |       let :route_file_content do
670 |         <<~EOS
671 |           # == Route Map
672 |           #
673 |           # another good line
674 |           # good line
675 | 
676 | 
677 | 
678 | 
679 |           Rails.application.routes.draw do
680 |             root 'root#index'
681 |           end
682 | 
683 | 
684 | 
685 |         EOS
686 |       end
687 | 
688 |       let :expected_result do
689 |         <<~EOS
690 |           Rails.application.routes.draw do
691 |             root 'root#index'
692 |           end
693 | 
694 | 
695 | 
696 |         EOS
697 |       end
698 | 
699 |       it 'removes prepended annotation and trim leading newlines, but leave trailing newlines alone' do
700 |         expect(mock_file).to receive(:puts).with(expected_result).once
701 |         expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_REMOVED).once
702 | 
703 |         AnnotateRoutes.remove_annotations
704 |       end
705 |     end
706 | 
707 |     context 'When custom comments are above route map' do
708 |       let :route_file_content do
709 |         <<~EOS
710 |           # My comment
711 |           # == Route Map
712 |           #
713 |           # another good line
714 |           # good line
715 |           Rails.application.routes.draw do
716 |             root 'root#index'
717 |           end
718 |         EOS
719 |       end
720 | 
721 |       let :expected_result do
722 |         <<~EOS
723 |           # My comment
724 |           Rails.application.routes.draw do
725 |             root 'root#index'
726 |           end
727 |         EOS
728 |       end
729 | 
730 |       it 'does not remove custom comments above route map' do
731 |         expect(mock_file).to receive(:puts).with(expected_result).once
732 |         expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_REMOVED).once
733 | 
734 |         AnnotateRoutes.remove_annotations
735 |       end
736 |     end
737 |   end
738 | end
739 | 


--------------------------------------------------------------------------------
/spec/lib/annotate/helpers_spec.rb:
--------------------------------------------------------------------------------
  1 | require_relative '../../spec_helper'
  2 | 
  3 | RSpec.describe Annotate::Helpers do
  4 |   describe '.skip_on_migration?' do
  5 |     subject { described_class.skip_on_migration? }
  6 | 
  7 |     before do
  8 |       allow(ENV).to receive(:[]).and_return(nil)
  9 |     end
 10 | 
 11 |     it { is_expected.to be_falsy }
 12 | 
 13 |     context "when ENV['ANNOTATE_SKIP_ON_DB_MIGRATE'] is set" do
 14 |       let(:key) { 'ANNOTATE_SKIP_ON_DB_MIGRATE' }
 15 |       let(:env_value) { '1' }
 16 | 
 17 |       before do
 18 |         allow(ENV).to receive(:[]).with(key).and_return(env_value)
 19 |       end
 20 | 
 21 |       it { is_expected.to be_truthy }
 22 |     end
 23 | 
 24 |     context "when ENV['skip_on_db_migrate'] is set" do
 25 |       let(:key) { 'skip_on_db_migrate' }
 26 |       let(:env_value) { '1' }
 27 | 
 28 |       before do
 29 |         allow(ENV).to receive(:[]).with(key).and_return(env_value)
 30 |       end
 31 | 
 32 |       it { is_expected.to be_truthy }
 33 |     end
 34 |   end
 35 | 
 36 |   describe '.include_routes?' do
 37 |     subject { described_class.include_routes? }
 38 | 
 39 |     before do
 40 |       allow(ENV).to receive(:[]).and_return(nil)
 41 |     end
 42 | 
 43 |     it { is_expected.to be_falsy }
 44 | 
 45 |     context "when ENV['routes'] is set" do
 46 |       let(:key) { 'routes' }
 47 |       let(:env_value) { '1' }
 48 | 
 49 |       before do
 50 |         allow(ENV).to receive(:[]).with(key).and_return(env_value)
 51 |       end
 52 | 
 53 |       it { is_expected.to be_truthy }
 54 |     end
 55 |   end
 56 | 
 57 |   describe '.include_models?' do
 58 |     subject { described_class.include_models? }
 59 | 
 60 |     before do
 61 |       allow(ENV).to receive(:[]).and_return(nil)
 62 |     end
 63 | 
 64 |     it { is_expected.to be_falsy }
 65 | 
 66 |     context "when ENV['models'] is set" do
 67 |       let(:key) { 'models' }
 68 |       let(:env_value) { '1' }
 69 | 
 70 |       before do
 71 |         allow(ENV).to receive(:[]).with(key).and_return(env_value)
 72 |       end
 73 | 
 74 |       it { is_expected.to be_truthy }
 75 |     end
 76 |   end
 77 | 
 78 |   describe '.true?' do
 79 |     subject { described_class.true?(val) }
 80 | 
 81 |     let(:val) { nil }
 82 |     it { is_expected.to be_falsy }
 83 | 
 84 |     context 'when val is blank' do
 85 |       let(:val) { '' }
 86 | 
 87 |       it { is_expected.to be_falsy }
 88 |     end
 89 | 
 90 |     context 'when it matches the regex' do
 91 |       valid_truthy_values = %w[true t yes y 1]
 92 | 
 93 |       valid_truthy_values.each do |truthy_value|
 94 |         let(:val) { truthy_value }
 95 | 
 96 |         it "returns truthy for '#{truthy_value}'" do
 97 |           is_expected.to be_truthy
 98 |         end
 99 |       end
100 |     end
101 |   end
102 | 
103 |   describe '.fallback' do
104 |     subject { described_class.fallback(*args) }
105 |     let(:args) { [arg_1, arg_2] }
106 | 
107 |     let(:arg_1) { '' } # is considered blank
108 |     let(:arg_2) { 'yes' }
109 | 
110 |     it 'returns the first non-blank argument' do
111 |       is_expected.to eq(arg_2)
112 |     end
113 | 
114 |     context 'when the first argument is non-blank' do
115 |       let(:arg_1) { 'yes' }
116 |       let(:arg_2) { 'no' }
117 | 
118 |       it { is_expected.to eq(arg_1) }
119 |     end
120 |   end
121 | 
122 |   describe '.reset_options' do
123 |     subject { described_class.reset_options(options) }
124 | 
125 |     let(:options) { [included_option] }
126 |     let(:included_option) { :some_key }
127 |     let(:excluded_option) { :yet_another_key }
128 |     let(:reset_value) { nil }
129 | 
130 |     before do
131 |       allow(ENV).to receive(:[]=)
132 |     end
133 | 
134 |     it 'resets ENV value' do
135 |       expect(ENV).to receive(:[]=).with(included_option.to_s, reset_value)
136 |       expect(ENV).to_not receive(:[]=).with(excluded_option.to_s, reset_value)
137 | 
138 |       subject
139 |     end
140 |   end
141 | end
142 | 


--------------------------------------------------------------------------------
/spec/lib/annotate/parser_spec.rb:
--------------------------------------------------------------------------------
  1 | require_relative '../../spec_helper'
  2 | 
  3 | module Annotate # rubocop:disable Metrics/ModuleLength
  4 |   describe Parser do
  5 |     before(:example) do
  6 |       ENV.clear
  7 |     end
  8 | 
  9 |     context 'when given empty args' do
 10 |       it 'returns an options hash with defaults' do
 11 |         result = Parser.parse([])
 12 |         expect(result).to be_a(Hash)
 13 |         expect(result).to include(target_action: :do_annotations)
 14 |       end
 15 |     end
 16 | 
 17 |     %w[--additional-file-patterns].each do |option|
 18 |       describe option do
 19 |         it 'sets array of paths to :additional_file_patterns' do
 20 |           paths = 'foo/bar,baz'
 21 |           allow(ENV).to receive(:[]=)
 22 |           Parser.parse([option, paths])
 23 |           expect(ENV).to have_received(:[]=).with('additional_file_patterns', ['foo/bar', 'baz'])
 24 |         end
 25 |       end
 26 |     end
 27 | 
 28 |     %w[-d --delete].each do |option|
 29 |       describe option do
 30 |         it 'sets target_action to :remove_annotations' do
 31 |           result = Parser.parse([option])
 32 |           expect(result).to include(target_action: :remove_annotations)
 33 |         end
 34 |       end
 35 |     end
 36 | 
 37 |     %w[-p --position].each do |option|
 38 |       describe option do
 39 |         Parser::ANNOTATION_POSITIONS.each do |position|
 40 |           context "when specifying #{position}" do
 41 |             it "#{position} position is an option" do
 42 |               allow(ENV).to receive(:[]=)
 43 |               Parser.parse([option, position])
 44 |               expect(Parser::ANNOTATION_POSITIONS).to include(position)
 45 |             end
 46 | 
 47 |             it "sets ENV['position'] to be position" do
 48 |               allow(ENV).to receive(:[]=)
 49 |               Parser.parse([option, position])
 50 | 
 51 |               expect(ENV).to have_received(:[]=).with('position', position)
 52 |             end
 53 | 
 54 |             it 'sets the value in ENV for the different file types' do
 55 |               allow(ENV).to receive(:[]=)
 56 |               Parser.parse([option, position])
 57 | 
 58 |               Parser::FILE_TYPE_POSITIONS.each do |file_type|
 59 |                 expect(ENV).to have_received(:[]=).with(file_type, position)
 60 |               end
 61 |             end
 62 |           end
 63 |         end
 64 |       end
 65 |     end
 66 | 
 67 |     context 'when position_in_class is set to top' do
 68 |       context 'and when position is a different value' do
 69 |         it 'does not override' do
 70 |           other_commands = %w[--pc top]
 71 |           position_command = %w[-p bottom]
 72 |           options = other_commands + position_command
 73 | 
 74 |           Parser.parse(options)
 75 |           expect(ENV['position_in_class']).to eq('top')
 76 |           expect(ENV['position']).to eq('bottom')
 77 |         end
 78 |       end
 79 |     end
 80 | 
 81 |     %w[--pc --position-in-class].each do |option|
 82 |       describe option do
 83 |         let(:env_key) { 'position_in_class' }
 84 | 
 85 |         Parser::ANNOTATION_POSITIONS.each do |position|
 86 |           context "when specifying '#{position}'" do
 87 |             it "sets the ENV variable to '#{position}'" do
 88 |               allow(ENV).to receive(:[]=)
 89 |               Parser.parse([option, position])
 90 |               expect(ENV).to have_received(:[]=).with(env_key, position)
 91 |             end
 92 |           end
 93 |         end
 94 |       end
 95 |     end
 96 | 
 97 |     %w[--pf --position-in-factory].each do |option|
 98 |       describe option do
 99 |         let(:env_key) { 'position_in_factory' }
100 | 
101 |         Parser::ANNOTATION_POSITIONS.each do |position|
102 |           context "when specifying #{position}" do
103 |             it "sets the ENV variable to #{position}" do
104 |               allow(ENV).to receive(:[]=)
105 |               Parser.parse([option, position])
106 |               expect(ENV).to have_received(:[]=).with(env_key, position)
107 |             end
108 |           end
109 |         end
110 |       end
111 |     end
112 | 
113 |     %w[--px --position-in-fixture].each do |option|
114 |       describe option do
115 |         let(:env_key) { 'position_in_fixture' }
116 | 
117 |         Parser::ANNOTATION_POSITIONS.each do |position|
118 |           context "when specifying #{position}" do
119 |             it "sets the ENV variable to #{position}" do
120 |               allow(ENV).to receive(:[]=)
121 |               Parser.parse([option, position])
122 |               expect(ENV).to have_received(:[]=).with(env_key, position)
123 |             end
124 |           end
125 |         end
126 |       end
127 |     end
128 | 
129 |     %w[--pt --position-in-test].each do |option|
130 |       describe option do
131 |         let(:env_key) { 'position_in_test' }
132 | 
133 |         Parser::ANNOTATION_POSITIONS.each do |position|
134 |           context "when specifying #{position}" do
135 |             it "sets the ENV variable to #{position}" do
136 |               allow(ENV).to receive(:[]=)
137 |               Parser.parse([option, position])
138 |               expect(ENV).to have_received(:[]=).with(env_key, position)
139 |             end
140 |           end
141 |         end
142 |       end
143 |     end
144 | 
145 |     %w[--pr --position-in-routes].each do |option|
146 |       describe option do
147 |         let(:env_key) { 'position_in_routes' }
148 | 
149 |         Parser::ANNOTATION_POSITIONS.each do |position|
150 |           context "when specifying #{position}" do
151 |             it "sets the ENV variable to #{position}" do
152 |               allow(ENV).to receive(:[]=)
153 |               Parser.parse([option, position])
154 |               expect(ENV).to have_received(:[]=).with(env_key, position)
155 |             end
156 |           end
157 |         end
158 |       end
159 |     end
160 | 
161 |     %w[--ps --position-in-serializer].each do |option|
162 |       describe option do
163 |         let(:env_key) { 'position_in_serializer' }
164 | 
165 |         Parser::ANNOTATION_POSITIONS.each do |position|
166 |           context "when specifying #{position}" do
167 |             it "sets the ENV variable to #{position}" do
168 |               allow(ENV).to receive(:[]=)
169 |               Parser.parse([option, position])
170 |               expect(ENV).to have_received(:[]=).with(env_key, position)
171 |             end
172 |           end
173 |         end
174 |       end
175 |     end
176 | 
177 |     %w[--w --wrapper].each do |option|
178 |       describe option do
179 |         let(:env_key) { 'wrapper' }
180 |         let(:set_value) { 'STR' }
181 |         it 'sets the ENV variable' do
182 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
183 |           Parser.parse([option, set_value])
184 |         end
185 |       end
186 |     end
187 | 
188 |     %w[--wo --wrapper-open].each do |option|
189 |       describe option do
190 |         let(:env_key) { 'wrapper_open' }
191 |         let(:set_value) { 'STR' }
192 |         it 'sets the ENV variable' do
193 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
194 |           Parser.parse([option, set_value])
195 |         end
196 |       end
197 |     end
198 | 
199 |     %w[--wc --wrapper-close].each do |option|
200 |       describe option do
201 |         let(:env_key) { 'wrapper_close' }
202 |         let(:set_value) { 'STR' }
203 |         it 'sets the ENV variable' do
204 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
205 |           Parser.parse([option, set_value])
206 |         end
207 |       end
208 |     end
209 | 
210 |     %w[-r --routes].each do |option|
211 |       describe option do
212 |         let(:env_key) { 'routes' }
213 |         let(:set_value) { 'true' }
214 |         it 'sets the ENV variable' do
215 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
216 |           Parser.parse([option])
217 |         end
218 |       end
219 |     end
220 | 
221 |     %w[--models].each do |option|
222 |       describe option do
223 |         let(:env_key) { 'models' }
224 |         let(:set_value) { 'true' }
225 |         it 'sets the ENV variable' do
226 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
227 |           Parser.parse([option])
228 |         end
229 |       end
230 |     end
231 | 
232 |     %w[-a --active-admin].each do |option|
233 |       describe option do
234 |         let(:env_key) { 'active_admin' }
235 |         let(:set_value) { 'true' }
236 |         it 'sets the ENV variable' do
237 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
238 |           Parser.parse([option])
239 |         end
240 |       end
241 |     end
242 | 
243 |     %w[-v --version].each do |option|
244 |       describe option do
245 |         it 'sets the ENV variable' do
246 |           expect { Parser.parse([option]) }.to output("annotate v#{Annotate.version}\n").to_stdout
247 |           expect(Parser.parse([option])).to include(exit: true)
248 |         end
249 |       end
250 |     end
251 | 
252 |     %w[-m --show-migration].each do |option|
253 |       describe option do
254 |         let(:env_key) { 'include_version' }
255 |         let(:set_value) { 'yes' }
256 |         it 'sets the ENV variable' do
257 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
258 |           Parser.parse([option])
259 |         end
260 |       end
261 |     end
262 | 
263 |     %w[-c --show-check-constraints].each do |option|
264 |       describe option do
265 |         let(:env_key) { 'show_check_constraints' }
266 |         let(:set_value) { 'yes' }
267 |         it 'sets the ENV variable' do
268 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
269 |           Parser.parse([option])
270 |         end
271 |       end
272 |     end
273 | 
274 |     %w[-k --show-foreign-keys].each do |option|
275 |       describe option do
276 |         let(:env_key) { 'show_foreign_keys' }
277 |         let(:set_value) { 'yes' }
278 |         it 'sets the ENV variable' do
279 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
280 |           Parser.parse([option])
281 |         end
282 |       end
283 |     end
284 | 
285 |     %w[--ck --complete-foreign-keys].each do |option|
286 |       describe option do
287 |         it 'sets the ENV variable' do
288 |           allow(ENV).to receive(:[]=)
289 |           Parser.parse([option])
290 | 
291 |           expect(ENV).to have_received(:[]=).with('show_foreign_keys', 'yes')
292 |           expect(ENV).to have_received(:[]=).with('show_complete_foreign_keys', 'yes')
293 |         end
294 |       end
295 |     end
296 | 
297 |     %w[-i --show-indexes].each do |option|
298 |       describe option do
299 |         let(:env_key) { 'show_indexes' }
300 |         let(:set_value) { 'yes' }
301 |         it 'sets the ENV variable' do
302 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
303 |           Parser.parse([option])
304 |         end
305 |       end
306 |     end
307 | 
308 |     %w[-s --simple-indexes].each do |option|
309 |       describe option do
310 |         let(:env_key) { 'simple_indexes' }
311 |         let(:set_value) { 'yes' }
312 |         it 'sets the ENV variable' do
313 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
314 |           Parser.parse([option])
315 |         end
316 |       end
317 |     end
318 | 
319 |     describe '--model-dir' do
320 |       let(:option) { '--model-dir' }
321 |       let(:env_key) { 'model_dir' }
322 |       let(:set_value) { 'some_dir/' }
323 |       it 'sets the ENV variable' do
324 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
325 |         Parser.parse([option, set_value])
326 |       end
327 |     end
328 | 
329 |     describe '--root-dir' do
330 |       let(:option) { '--root-dir' }
331 |       let(:env_key) { 'root_dir' }
332 |       let(:set_value) { 'some_dir/' }
333 |       it 'sets the ENV variable' do
334 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
335 |         Parser.parse([option, set_value])
336 |       end
337 |     end
338 | 
339 |     describe '--ignore-model-subdirects' do
340 |       let(:option) { '--ignore-model-subdirects' }
341 |       let(:env_key) { 'ignore_model_sub_dir' }
342 |       let(:set_value) { 'yes' }
343 |       it 'sets the ENV variable' do
344 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
345 |         Parser.parse([option])
346 |       end
347 |     end
348 | 
349 |     describe '--sort' do
350 |       let(:option) { '--sort' }
351 |       let(:env_key) { 'sort' }
352 |       let(:set_value) { 'yes' }
353 |       it 'sets the ENV variable' do
354 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
355 |         Parser.parse([option])
356 |       end
357 |     end
358 | 
359 |     describe '--classified-sort' do
360 |       let(:option) { '--classified-sort' }
361 |       let(:env_key) { 'classified_sort' }
362 |       let(:set_value) { 'yes' }
363 |       it 'sets the ENV variable' do
364 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
365 |         Parser.parse([option])
366 |       end
367 |     end
368 | 
369 |     %w[-R --require].each do |option|
370 |       describe option do
371 |         let(:env_key) { 'require' }
372 |         let(:set_value) { 'another_dir' }
373 |         it 'sets the ENV variable' do
374 |           expect(ENV).to receive(:[]=).with(env_key, set_value)
375 |           Parser.parse([option, set_value])
376 |         end
377 | 
378 |         context "when ENV['require'] is already set" do
379 |           let(:preset_require_value) { 'some_dir/' }
380 |           it "appends the path to ENV['require']" do
381 |             env = { 'require' => preset_require_value }
382 |             expect(ENV).to receive(:[]=).with(env_key, "#{preset_require_value},#{set_value}")
383 |             Parser.parse([option, set_value], env)
384 |           end
385 |         end
386 |       end
387 |     end
388 | 
389 |     describe 'Parser::EXCLUSION_LIST' do
390 |       it "has 'tests'" do
391 |         expect(Parser::EXCLUSION_LIST).to include('tests')
392 |       end
393 | 
394 |       it "has 'fixtures'" do
395 |         expect(Parser::EXCLUSION_LIST).to include('fixtures')
396 |       end
397 | 
398 |       it "has 'factories'" do
399 |         expect(Parser::EXCLUSION_LIST).to include('factories')
400 |       end
401 | 
402 |       it "has 'serializers'" do
403 |         expect(Parser::EXCLUSION_LIST).to include('serializers')
404 |       end
405 |     end
406 | 
407 |     %w[-e --exclude].each do |option|
408 |       describe option do
409 |         let(:set_value) { 'yes' }
410 | 
411 |         it "sets the exclusion ENV variables for 'tests', 'fixtures', 'factories', and 'serializers'" do
412 |           allow(ENV).to receive(:[]=)
413 |           Parser.parse([option])
414 | 
415 |           expect(ENV).to have_received(:[]=).with('exclude_tests', set_value)
416 |           expect(ENV).to have_received(:[]=).with('exclude_fixtures', set_value)
417 |           expect(ENV).to have_received(:[]=).with('exclude_factories', set_value)
418 |           expect(ENV).to have_received(:[]=).with('exclude_serializers', set_value)
419 |         end
420 | 
421 |         context 'when a type is passed in' do
422 |           let(:exclusions) { "tests" }
423 | 
424 |           it "sets the exclusion ENV variable for 'tests' only" do
425 |             expect(ENV).to receive(:[]=).with('exclude_tests', set_value)
426 |             Parser.parse([option, exclusions])
427 |           end
428 |         end
429 | 
430 |         context 'when two types are passed in' do
431 |           let(:exclusions) { "tests,fixtures" }
432 | 
433 |           it "sets the exclusion ENV variable for 'tests' and 'fixtures'" do
434 |             allow(ENV).to receive(:[]=)
435 |             Parser.parse([option, exclusions])
436 |             expect(ENV).to have_received(:[]=).with('exclude_tests', set_value)
437 |             expect(ENV).to have_received(:[]=).with('exclude_fixtures', set_value)
438 |           end
439 |         end
440 |       end
441 |     end
442 | 
443 |     %w[-f --format].each do |option|
444 |       describe option do
445 |         Parser::FORMAT_TYPES.each do |format_type|
446 |           context "when passing in format type '#{format_type}'" do
447 |             let(:env_key) { "format_#{format_type}" }
448 |             let(:set_value) { 'yes' }
449 | 
450 |             it 'sets the ENV variable' do
451 |               expect(ENV).to receive(:[]=).with(env_key, set_value)
452 |               Parser.parse([option, format_type])
453 |             end
454 |           end
455 |         end
456 |       end
457 |     end
458 | 
459 |     describe '--force' do
460 |       let(:option) { '--force' }
461 |       let(:env_key) { 'force' }
462 |       let(:set_value) { 'yes' }
463 |       it 'sets the ENV variable' do
464 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
465 |         Parser.parse([option])
466 |       end
467 |     end
468 | 
469 |     describe '--frozen' do
470 |       let(:option) { '--frozen' }
471 |       let(:env_key) { 'frozen' }
472 |       let(:set_value) { 'yes' }
473 |       it 'sets the ENV variable' do
474 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
475 |         Parser.parse([option])
476 |       end
477 |     end
478 | 
479 |     describe '--timestamp' do
480 |       let(:option) { '--timestamp' }
481 |       let(:env_key) { 'timestamp' }
482 |       let(:set_value) { 'true' }
483 |       it 'sets the ENV variable' do
484 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
485 |         Parser.parse([option])
486 |       end
487 |     end
488 | 
489 |     describe '--trace' do
490 |       let(:option) { '--trace' }
491 |       let(:env_key) { 'trace' }
492 |       let(:set_value) { 'yes' }
493 |       it 'sets the ENV variable' do
494 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
495 |         Parser.parse([option])
496 |       end
497 |     end
498 | 
499 |     %w[-I --ignore-columns].each do |option|
500 |       describe option do
501 |         let(:env_key) { 'ignore_columns' }
502 |         let(:regex) { '^(id|updated_at|created_at)' }
503 | 
504 |         it 'sets the ENV variable' do
505 |           expect(ENV).to receive(:[]=).with(env_key, regex)
506 |           Parser.parse([option, regex])
507 |         end
508 |       end
509 |     end
510 | 
511 |     describe '--ignore-routes' do
512 |       let(:option) { '--ignore-routes' }
513 |       let(:env_key) { 'ignore_routes' }
514 |       let(:regex) { '(mobile|resque|pghero)' }
515 | 
516 |       it 'sets the ENV variable' do
517 |         expect(ENV).to receive(:[]=).with(env_key, regex)
518 |         Parser.parse([option, regex])
519 |       end
520 |     end
521 | 
522 |     describe '--hide-limit-column-types' do
523 |       let(:option) { '--hide-limit-column-types' }
524 |       let(:env_key) { 'hide_limit_column_types' }
525 |       let(:values) { 'integer,boolean,text' }
526 | 
527 |       it 'sets the ENV variable' do
528 |         expect(ENV).to receive(:[]=).with(env_key, values)
529 |         Parser.parse([option, values])
530 |       end
531 |     end
532 | 
533 |     describe '--hide-default-column-types' do
534 |       let(:option) { '--hide-default-column-types' }
535 |       let(:env_key) { 'hide_default_column_types' }
536 |       let(:values) { 'json,jsonb,hstore' }
537 | 
538 |       it 'sets the ENV variable' do
539 |         expect(ENV).to receive(:[]=).with(env_key, values)
540 |         Parser.parse([option, values])
541 |       end
542 |     end
543 | 
544 |     describe '--ignore-unknown-models' do
545 |       let(:option) { '--ignore-unknown-models' }
546 |       let(:env_key) { 'ignore_unknown_models' }
547 |       let(:set_value) { 'true' }
548 |       it 'sets the ENV variable' do
549 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
550 |         Parser.parse([option])
551 |       end
552 |     end
553 | 
554 |     describe '--with-comment' do
555 |       let(:option) { '--with-comment' }
556 |       let(:env_key) { 'with_comment' }
557 |       let(:set_value) { 'true' }
558 |       it 'sets the ENV variable' do
559 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
560 |         Parser.parse([option])
561 |       end
562 |     end
563 | 
564 |     describe '--with-comment-column' do
565 |       let(:option) { '--with-comment-column' }
566 |       let(:env_key) { 'with_comment_column' }
567 |       let(:set_value) { 'true' }
568 |       it 'sets the ENV variable' do
569 |         expect(ENV).to receive(:[]=).with(env_key, set_value)
570 |         Parser.parse([option])
571 |       end
572 |     end
573 |   end
574 | end
575 | 


--------------------------------------------------------------------------------
/spec/lib/annotate_spec.rb:
--------------------------------------------------------------------------------
 1 | require_relative '../spec_helper'
 2 | 
 3 | describe Annotate do
 4 |   describe '.version' do
 5 |     it 'has version' do
 6 |       expect(Annotate.version).to be_instance_of(String)
 7 |     end
 8 |   end
 9 | end
10 | 


--------------------------------------------------------------------------------
/spec/lib/tasks/annotate_models_migrate_spec.rb:
--------------------------------------------------------------------------------
 1 | require_relative '../../spec_helper'
 2 | 
 3 | describe 'ActiveRecord migration rake task hooks' do
 4 |   before do
 5 |     Rake.application = Rake::Application.new
 6 | 
 7 |     # Stub migration tasks
 8 |     %w(db:migrate db:migrate:up db:migrate:down db:migrate:reset db:rollback).each do |task|
 9 |       Rake::Task.define_task(task)
10 |     end
11 |     Rake::Task.define_task('db:migrate:redo') do
12 |       Rake::Task['db:rollback'].invoke
13 |       Rake::Task['db:migrate'].invoke
14 |     end
15 | 
16 |     Rake::Task.define_task('set_annotation_options')
17 |     Rake.load_rakefile('tasks/annotate_models_migrate.rake')
18 | 
19 |     Rake.application.instance_variable_set(:@top_level_tasks, [subject])
20 |   end
21 | 
22 |   describe 'db:migrate' do
23 |     it 'should update annotations' do
24 |       expect(Annotate::Migration).to receive(:update_annotations)
25 |       Rake.application.top_level
26 |     end
27 |   end
28 | 
29 |   describe 'db:migrate:up' do
30 |     it 'should update annotations' do
31 |       expect(Annotate::Migration).to receive(:update_annotations)
32 |       Rake.application.top_level
33 |     end
34 |   end
35 | 
36 |   describe 'db:migrate:down' do
37 |     it 'should update annotations' do
38 |       expect(Annotate::Migration).to receive(:update_annotations)
39 |       Rake.application.top_level
40 |     end
41 |   end
42 | 
43 |   describe 'db:migrate:reset' do
44 |     it 'should update annotations' do
45 |       expect(Annotate::Migration).to receive(:update_annotations)
46 |       Rake.application.top_level
47 |     end
48 |   end
49 | 
50 |   describe 'db:rollback' do
51 |     it 'should update annotations' do
52 |       expect(Annotate::Migration).to receive(:update_annotations)
53 |       Rake.application.top_level
54 |     end
55 |   end
56 | 
57 |   describe 'db:migrate:redo' do
58 |     it 'should update annotations after all migration tasks' do
59 |       allow(Annotate::Migration).to receive(:update_annotations)
60 | 
61 |       # Confirm that update_annotations isn't called when the original redo task finishes
62 |       Rake::Task[subject].enhance do
63 |         expect(Annotate::Migration).not_to have_received(:update_annotations)
64 |       end
65 | 
66 |       Rake.application.top_level
67 | 
68 |       # Hooked 3 times by db:rollback, db:migrate, and db:migrate:redo tasks
69 |       expect(Annotate::Migration).to have_received(:update_annotations).exactly(3).times
70 |     end
71 |   end
72 | end
73 | 


--------------------------------------------------------------------------------
/spec/lib/tasks/annotate_models_spec.rb:
--------------------------------------------------------------------------------
 1 | require_relative '../../spec_helper'
 2 | 
 3 | describe 'Annotate annotate_models rake task and Annotate.set_defaults' do # rubocop:disable RSpec/DescribeClass
 4 |   before do
 5 |     Rake.application = Rake::Application.new
 6 |     Rake::Task.define_task('environment')
 7 |     Rake.load_rakefile('tasks/annotate_models.rake')
 8 |   end
 9 | 
10 |   after do
11 |     Annotate.instance_variable_set('@has_set_defaults', false)
12 |   end
13 | 
14 |   let(:annotate_models_argument) do
15 |     argument = nil
16 |     allow(AnnotateModels).to receive(:do_annotations) { |arg| argument = arg }
17 |     Rake::Task['annotate_models'].invoke
18 |     argument
19 |   end
20 | 
21 |   describe 'with_comment_column' do
22 |     subject { annotate_models_argument[:with_comment_column] }
23 | 
24 |     after { ENV.delete('with_comment_column') }
25 | 
26 |     context 'when Annotate.set_defaults is not called (defaults)' do
27 |       it { is_expected.to be_falsey }
28 |     end
29 | 
30 |     context 'when Annotate.set_defaults sets it to "true"' do
31 |       before { Annotate.set_defaults('with_comment_column' => 'true') }
32 | 
33 |       it { is_expected.to be_truthy }
34 |     end
35 |   end
36 | end
37 | 


--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
 1 | if ENV['COVERAGE']
 2 |   require 'coveralls'
 3 |   require 'codeclimate-test-reporter'
 4 |   require 'simplecov'
 5 | 
 6 |   SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
 7 |     [
 8 |       Coveralls::SimpleCov::Formatter,
 9 |       SimpleCov::Formatter::HTMLFormatter,
10 |       CodeClimate::TestReporter::Formatter
11 |     ]
12 |   )
13 | 
14 |   SimpleCov.start
15 | end
16 | 
17 | require 'rubygems'
18 | require 'bundler'
19 | Bundler.setup
20 | 
21 | require 'rake'
22 | require 'rspec'
23 | 
24 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../lib'))
25 | $LOAD_PATH.unshift(File.dirname(__FILE__))
26 | 
27 | require 'active_support'
28 | require 'active_support/core_ext/object/blank'
29 | require 'active_support/core_ext/class/subclasses'
30 | require 'active_support/core_ext/string/inflections'
31 | require 'annotate'
32 | require 'annotate/parser'
33 | require 'annotate/helpers'
34 | require 'annotate/constants'
35 | require 'byebug'
36 | 
37 | RSpec.configure do |config|
38 |   config.order = 'random'
39 |   config.filter_run_when_matching :focus
40 | end
41 | 


--------------------------------------------------------------------------------