diff --git a/lib/annotate_rb/model_annotator/model_wrapper.rb b/lib/annotate_rb/model_annotator/model_wrapper.rb index 12c7864b..e546723d 100644 --- a/lib/annotate_rb/model_annotator/model_wrapper.rb +++ b/lib/annotate_rb/model_annotator/model_wrapper.rb @@ -6,6 +6,8 @@ class ModelWrapper # Should be the wrapper for an ActiveRecord model that serves as the source of truth of the model # of the model that we're annotating + DEFAULT_TIMESTAMP_COLUMNS = %w[created_at updated_at] + def initialize(klass, options) @klass = klass @options = options @@ -143,10 +145,13 @@ def classified_sort(cols) associations = [] id = nil + # specs don't load defaults, so ensure we have defaults here + timestamp_columns = @options[:timestamp_columns] || DEFAULT_TIMESTAMP_COLUMNS + cols.each do |c| if c.name.eql?("id") id = c - elsif c.name.eql?("created_at") || c.name.eql?("updated_at") + elsif timestamp_columns.include?(c.name) timestamps << c elsif c.name[-3, 3].eql?("_id") associations << c @@ -154,7 +159,10 @@ def classified_sort(cols) rest_cols << c end end - [rest_cols, timestamps, associations].each { |a| a.sort_by!(&:name) } + + timestamp_order = timestamp_columns.each_with_index.to_h + timestamps.sort_by! { |col| timestamp_order[col.name] } + [rest_cols, associations].each { |a| a.sort_by!(&:name) } ([id] << rest_cols << timestamps << associations).flatten.compact end diff --git a/lib/annotate_rb/options.rb b/lib/annotate_rb/options.rb index 368a1395..2d7df57f 100644 --- a/lib/annotate_rb/options.rb +++ b/lib/annotate_rb/options.rb @@ -67,6 +67,9 @@ def from(options = {}, state = {}) # ModelAnnotator hide_limit_column_types: "", + # ModelAnnotator + timestamp_columns: ModelAnnotator::ModelWrapper::DEFAULT_TIMESTAMP_COLUMNS, + ignore_columns: nil, # ModelAnnotator ignore_routes: nil, # RouteAnnotator ignore_unknown_models: false, # ModelAnnotator diff --git a/spec/lib/annotate_rb/model_annotator/annotation/annotation_builder_spec.rb b/spec/lib/annotate_rb/model_annotator/annotation/annotation_builder_spec.rb index 49c6a4ae..d175491d 100644 --- a/spec/lib/annotate_rb/model_annotator/annotation/annotation_builder_spec.rb +++ b/spec/lib/annotate_rb/model_annotator/annotation/annotation_builder_spec.rb @@ -181,6 +181,60 @@ it 'works with option "classified_sort"' do is_expected.to eq expected_result end + + context 'when default timestamps are included' do + let(:columns) do + [ + mock_column("parent_id", :integer), + mock_column("updated_at", :datetime), + mock_column("name", :string), + mock_column("id", :integer), + mock_column("deleted_at", :datetime), + mock_column("created_at", :datetime) + ] + end + + it 'sorts default timestamps second last before associations' do + is_expected.to eq <<~EOS + # == Schema Information + # + # Table name: users + # + # id :integer not null, primary key + # deleted_at :datetime not null + # name :string not null + # created_at :datetime not null + # updated_at :datetime not null + # parent_id :integer not null + # + EOS + end + + context 'when timestamps_column option is set' do + let(:options) do + AnnotateRb::Options.new( + classified_sort: true, + timestamp_columns: %w[created_at updated_at deleted_at] + ) + end + + it 'sorts configured timestamps into config order' do + is_expected.to eq <<~EOS + # == Schema Information + # + # Table name: users + # + # id :integer not null, primary key + # name :string not null + # created_at :datetime not null + # updated_at :datetime not null + # deleted_at :datetime not null + # parent_id :integer not null + # + EOS + end + end + end end context "when geometry columns are included" do diff --git a/spec/lib/annotate_rb/options_spec.rb b/spec/lib/annotate_rb/options_spec.rb index dc82b429..29ef5247 100644 --- a/spec/lib/annotate_rb/options_spec.rb +++ b/spec/lib/annotate_rb/options_spec.rb @@ -54,7 +54,6 @@ context 'when default value of "show_complete_foreign_keys" is not set' do let(:key) { :show_complete_foreign_keys } - let(:options) { {} } it "returns false" do expect(subject[key]).to eq(false) @@ -70,10 +69,14 @@ end end + describe "default timestamp_columns" do + it "sets defaults matching Rails' convention" do + expect(subject[:timestamp_columns]).to match_array(%w[created_at updated_at]) + end + end + describe "comment options" do context "when using defaults" do - let(:options) { {} } - it "uses the defaults" do expect(subject[:with_comment]).to eq(true) expect(subject[:with_column_comments]).to eq(true)