drwl / annotaterb Goto Github PK
View Code? Open in Web Editor NEWA Ruby Gem that adds annotations to your Rails models and route files.
License: Other
A Ruby Gem that adds annotations to your Rails models and route files.
License: Other
It should seamlessly support the data_migrate
gem.
I'm trying out annotaterb on a Rails project which has packs-rails setup. The packs/
directory doesn't get automatically picked up, understandably.
:root_dir: ['.', 'packs/*']
and only app/
directory in the root gets picked up, none of the packs were recognized.
packs/*
by expanding it to packs/packone
packs/packtwo
etc, still doesn't work.While the title is specifically on packs-rails, I wouldn't mind having a compromise via :root_dir:
or :model_dir:
if it supports globs ๐
P.S. ๐๐ป hey Andrew, hope you've been well!
Describe your problem here.
We've been using annotate for some time alongside with custom AR types (via ActiveRecord::Type.register
). Unfortunately, annotate was serializing values of these types into extremely long strings:
# currency :string default(#<Money::Currency id: usd, priority: 100, symbol_first: false, thousands_separator: ., html_entity: ₽, decimal_mark: ,, name: United States Dollar, symbol: $, subunit_to_unit: 100, exponent: 2, iso_code: RUB, iso_numeric: 643, subunit: Cent, smallest_denomination: 1, format: %n %u>), not null
We workaround the issue by monkey-patching ``AnnotateModels.quote`:
....
when BigDecimal then value.to_s("F")
when Array then value.map { |v| quote(v) }
when Locale then value.to_s.inspect # custom types start here
when Region then value.to_s.inspect
when Billing::Plan then value.to_s.inspect
so annotations were good to look at:
# currency :string default("USD"), not null
We are looking forward migration to annotaterb so we'd also want to get rid of that monkey-patch. Perhaps an addtional configuration option would be sufficient?
As a user, I would like an easy way to migrate from the old annotate gem to annotaterb. It would take actions mentioned in the migration guide.
Because there are destructive actions (i.e. deleting of a file), I would imagine the default command being a preview and requiring an additional argument like --continue
to actually make those change, similar to how Rubocop requires the passing of --auto-correct
to actually apply changes.
After this command is run, I would like the following to be true:
lib/tasks/auto_annotate_models.rake
exists then
.annotaterb.yml
file is created with defaults, using the values in the rake file to override defaults in the yml filelib/tasks/auto_annotate_models.rake
exists.annotaterb.yml
file is created with defaultsANNOTATE_SKIP_ON_DB_MIGRATE=1
becomes ANNOTATERB_SKIP_ON_DB_TASKS=1
I tried to migrate from annotate gem, to see if this gem fixes an issue we had with the original in which it does not work with Zeitwerk namespaces.
Our project structure like this:
/app/models/
/app/namespace/models/
/spec/models/
/spec/fabricators/
/spec/namespace/models/
/spec/namespace/fabricators/
In an initializor we have:
Object.const_set('Namespace', Module.new) unless Object.const_defined?('Namespace')
Rails.autoloaders.main.push_dir(Rails.root.join("app/namespace/models"), namespace: Namespace)
In .annotate.yml
I tried with this setup:
:model_dir:
- app/models
- app/namespace/models
When I run annotaterb models
the models in app/models/
are annotated correctly, but I see these errors for models in app/namespace/models
dir:
Unable to process app/namespace/models/foo.rb: file doesn't contain a valid model class
Unable to process app/namespace/models/bar.rb: file doesn't contain a valid model class
The file app/namespace/models/foo.rb
is like
module Namespace
class Foo < ApplicationRecord
end
end
I also tried using root_dir config, but got same error:
:root_dir:
- 'app'
- 'app/namespace'
For the original annotate gem version 3.2.0 I have developed the following monkey patch to make this setup work in our project:
# frozen_string_literal: true
annotate_gem_specs = Gem.loaded_specs['annotate']
return unless annotate_gem_specs
module AnnotateModelsWithZeitwerkNamespaces
module FilePatterns
def test_files(root_directory)
super + NAMESPACE_DIRS_WITH_MODELS.map do |namespace_dir|
File.join(root_directory, 'spec', namespace_dir.to_s, 'models', '%MODEL_NAME_WITHOUT_NS%_spec.rb')
end
end
def factory_files(root_directory)
super + NAMESPACE_DIRS_WITH_MODELS.map do |namespace_dir|
File.join(root_directory, 'spec', namespace_dir.to_s, 'fabricators', '%MODEL_NAME_WITHOUT_NS%_fabricator.rb')
end
end
end
def get_model_class(file)
loader = Rails.autoloaders.main
root_dirs = loader.dirs(namespaces: true)
expanded_file = File.expand_path(file)
root_dir, namespace = root_dirs.find do |dir, _|
expanded_file.start_with?(dir)
end
_, filepath_relative_to_root_dir = expanded_file.split(root_dir)
filepath_relative_to_root_dir = filepath_relative_to_root_dir[1..].sub(/\.rb$/, '')
camelize = loader.inflector.camelize(filepath_relative_to_root_dir, nil)
namespace.const_get(camelize)
end
def resolve_filename(filename_template, model_name, table_name)
super.gsub('%MODEL_NAME_WITHOUT_NS%', model_name.split('/', 2).last)
end
end
AnnotateModels.singleton_class.prepend(AnnotateModelsWithZeitwerkNamespaces)
AnnotateModels::FilePatterns.singleton_class.prepend(AnnotateModelsWithZeitwerkNamespaces::FilePatterns)
In the config, when exclude_tests
is true
but exclude_serializers
is false
, you still end up with annotations for the specs of serializers when the Rake task runs. I don't know if this is intentional, but for our codebase we gain little from having annotations in our serializers. Likewise, we lose little from having annotations in our serializers, so it's by no means an urgent request.
---
:position: after
:classified_sort: true
:exclude_controllers: true
:exclude_factories: false
:exclude_fixtures: false
:exclude_helpers: true
:exclude_scaffolds: true
:exclude_serializers: false
:exclude_sti_subclasses: false
:exclude_tests: true
:force: false
:format_markdown: false
:format_rdoc: false
:format_yard: false
:frozen: false
:ignore_model_sub_dir: false
:ignore_unknown_models: false
:include_version: false
:show_complete_foreign_keys: false
:show_foreign_keys: true
:show_indexes: true
:simple_indexes: false
:sort: false
:timestamp: false
:trace: false
:with_comment: true
:with_column_comments: true
:with_table_comments: true
:active_admin: false
:command:
:debug: false
:hide_default_column_types: ''
:hide_limit_column_types: ''
:ignore_columns:
:ignore_routes:
:models: true
:routes: false
:skip_on_db_migrate: false
:target_action: :do_annotations
:wrapper:
:wrapper_close:
:wrapper_open:
:additional_file_patterns: []
:model_dir:
- app/models
:require: []
:root_dir:
- ''
When I annotate models, the content of fixture is duplicated. It's working fine for model and model test files.
Here is my config:
---
:position: before
:position_in_additional_file_patterns: before
:position_in_class: before
:position_in_factory: before
:position_in_fixture: before
:position_in_routes: before
:position_in_serializer: before
:position_in_test: before
:classified_sort: true
:exclude_controllers: true
:exclude_factories: false
:exclude_fixtures: false
:exclude_helpers: true
:exclude_scaffolds: true
:exclude_serializers: false
:exclude_sti_subclasses: false
:exclude_tests: false
:force: false
:format_markdown: false
:format_rdoc: false
:format_yard: false
:frozen: false
:ignore_model_sub_dir: false
:ignore_unknown_models: false
:include_version: false
:show_complete_foreign_keys: false
:show_foreign_keys: true
:show_indexes: true
:simple_indexes: false
:sort: false
:timestamp: false
:trace: false
:with_comment: true
:with_column_comments: true
:with_table_comments: true
:active_admin: false
:command:
:debug: false
:hide_default_column_types: ''
:hide_limit_column_types: ''
:ignore_columns:
:ignore_routes:
:models: true
:routes: false
:skip_on_db_migrate: false
:target_action: :do_annotations
:wrapper:
:wrapper_close:
:wrapper_open:
:classes_default_to_s: []
:additional_file_patterns: []
:model_dir:
- app/models
:require: []
:root_dir:
- ''
$ bundle exec annotaterb models
Hey there. We currently use annotate_models
, looking at maybe switching over, but it seems this fork does not support annotating check constraints. ctran/annotate_models#868
@drwl would you be keen to see a similar implementation here?
Hi, I'm seeing some odd behaviour for a model nested inside a name space with annotations previously generated by annotate_models
eg, we have (roughly, excuse any errors anonymising stuff)
# == Schema Information
#
# Table name: my_models
#
# id :bigint(8) not null, primary key
# name :string not null
#
# Indexes
#
# index_my_models_on_name (name) UNIQUE
module MyModule
# a long comment
# over a few lines
# more explanation
class MyModel < ApplicationModel
end
end
after running annotaterb
I end up with a duplicate index + newline like this:
# == Schema Information
#
# Table name: my_models
#
# id :bigint(8) not null, primary key
# name :string not null
#
# Indexes
#
# index_my_models_on_name (name) UNIQUE
#
# index_my_models_on_name (name) UNIQUE
module MyModule
# a long comment
# over a few lines
# more explanation
class MyModel < ApplicationModel
end
end
removing the annotations and starting from scratch letting annotaterb pick where it thinks they belong, I end up with
module MyModule
# a long comment
# over a few lines
# == Schema Information
#
# Table name: my_models
#
# id :bigint(8) not null, primary key
# name :string not null
#
# Indexes
#
# index_my_models_on_name (name) UNIQUE
# more explanation
class MyModel < ApplicationModel
end
end
with the annotations inserted midway through the comment, and with an outdent as above. Any pointers which config options might help here?
When I set the default value for an array text column via the Attributes API, the annotate output is double-quoted (or quoted and escaped?).
attribute :notifications, default: %w(newsletter)
generates
# notifications :text default(["\"newsletter\""]), not null, is an Array
$ bundle exec annotaterb models
When migrating from the annotate
gem to the annotaterb
gem the default column values aren't represented in the same way as previously. My expectation would be that when migrating, as long as I have the same configuration setup, that the results would be the same as the previous gem. The output from the annotate
gem "humanized" the defaults instead of directly representing what is the in database. For example instead of showing a default of 0
or 1
for a boolean field, as that is stored as a TINYINT
, it would display it as TRUE
or FALSE
. Here are some example diffs from columns with default fields:
Boolean column:
-# enabled :boolean default(TRUE), not null
+# enabled :boolean default("1"), not null
Integer column:
-# lock_version :integer default(0), not null
+# lock_version :integer default("0"), not null
Enum column:
-# initiation_type :integer default("one_time"), not null
+# initiation_type :integer default("0"), not null
$ bundle exec annotate models
annotaterb
version: 4.3.0
rails
version: 7.0.4.3
ruby
version: 3.1.3
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.