From e138ea93bc3cc38401d6c9db27644730542183eb Mon Sep 17 00:00:00 2001 From: Dan Erikson Date: Mon, 4 Mar 2024 12:35:25 -0700 Subject: [PATCH 1/2] Add the enum column to the test database --- .../20240226015501_add_status_to_user.rb | 5 +++ test/app/db/schema.rb | 3 +- test/expectations/user.rbs | 36 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 test/app/db/migrate/20240226015501_add_status_to_user.rb diff --git a/test/app/db/migrate/20240226015501_add_status_to_user.rb b/test/app/db/migrate/20240226015501_add_status_to_user.rb new file mode 100644 index 0000000..491929e --- /dev/null +++ b/test/app/db/migrate/20240226015501_add_status_to_user.rb @@ -0,0 +1,5 @@ +class AddStatusToUser < ActiveRecord::Migration[6.1] + def change + add_column :users, :status, :integer, null: false + end +end diff --git a/test/app/db/schema.rb b/test/app/db/schema.rb index 53dea36..fceee2f 100644 --- a/test/app/db/schema.rb +++ b/test/app/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_04_14_110904) do +ActiveRecord::Schema.define(version: 2024_02_26_015501) do create_table "blogs", force: :cascade do |t| t.string "title", null: false @@ -31,6 +31,7 @@ t.integer "age", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.integer "status", null: false end end diff --git a/test/expectations/user.rbs b/test/expectations/user.rbs index d317140..24bda23 100644 --- a/test/expectations/user.rbs +++ b/test/expectations/user.rbs @@ -181,6 +181,42 @@ class User < ::ApplicationRecord def restore_updated_at!: () -> void def clear_updated_at_change: () -> void + + def status: () -> ::String + + def status=: (::String) -> ::String + + def status?: () -> bool + + def status_changed?: () -> bool + + def status_change: () -> [ ::String?, ::String? ] + + def status_will_change!: () -> void + + def status_was: () -> ::String? + + def status_previously_changed?: () -> bool + + def status_previous_change: () -> ::Array[::String?]? + + def status_previously_was: () -> ::String? + + def status_before_last_save: () -> ::String? + + def status_change_to_be_saved: () -> ::Array[::String?]? + + def status_in_database: () -> ::String? + + def saved_change_to_status: () -> ::Array[::String?]? + + def saved_change_to_status?: () -> bool + + def will_save_change_to_status?: () -> bool + + def restore_status!: () -> void + + def clear_status_change: () -> void end include GeneratedAttributeMethods From 0c888b1cb8856e1cc78a773b6ebc1e03f9df891d Mon Sep 17 00:00:00 2001 From: Dan Erikson Date: Wed, 6 Mar 2024 09:40:21 -0700 Subject: [PATCH 2/2] Add additional methods generated by `enum` --- lib/rbs_rails/active_record.rb | 10 +++++++--- sig/rbs_rails/active_record.rbs | 2 +- test/expectations/user.rbs | 9 +++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/rbs_rails/active_record.rb b/lib/rbs_rails/active_record.rb index f260497..0c77cc3 100644 --- a/lib/rbs_rails/active_record.rb +++ b/lib/rbs_rails/active_record.rb @@ -39,7 +39,7 @@ def generate #{delegated_type_instance} #{delegated_type_scope(singleton: true)} #{enum_instance_methods} - #{enum_scope_methods(singleton: true)} + #{enum_class_methods(singleton: true)} #{scopes(singleton: true)} #{generated_relation_methods_decl} @@ -63,7 +63,7 @@ def generate private def generated_relation_methods_decl <<~RBS module #{generated_relation_methods_name(abs: false)} - #{enum_scope_methods(singleton: false)} + #{enum_class_methods(singleton: false)} #{scopes(singleton: false)} #{delegated_type_scope(singleton: false)} end @@ -333,16 +333,20 @@ def authenticate_#{attribute}: (String) -> (#{klass_name} | false) methods.join("\n") end - private def enum_scope_methods(singleton:) + private def enum_class_methods(singleton:) # @type var methods: Array[String] methods = [] enum_definitions.each do |hash| hash.each do |name, values| next if IGNORED_ENUM_KEYS.include?(name) + class_name = sql_type_to_class(klass.columns_hash[name.to_s].type) + methods << "def #{singleton ? 'self.' : ''}#{name.to_s.pluralize}: () -> ::ActiveSupport::HashWithIndifferentAccess[::String, #{class_name}]" + values.each do |label, value| value_method_name = enum_method_name(hash, name, label) methods << "def #{singleton ? 'self.' : ''}#{value_method_name}: () -> #{relation_class_name}" + methods << "def #{singleton ? 'self.' : ''}not_#{value_method_name}: () -> #{relation_class_name}" end end end diff --git a/sig/rbs_rails/active_record.rbs b/sig/rbs_rails/active_record.rbs index d848bf1..7e98265 100644 --- a/sig/rbs_rails/active_record.rbs +++ b/sig/rbs_rails/active_record.rbs @@ -49,7 +49,7 @@ class RbsRails::ActiveRecord::Generator def enum_instance_methods: () -> String - def enum_scope_methods: (singleton: untyped `singleton`) -> String + def enum_class_methods: (singleton: untyped `singleton`) -> String def enum_definitions: () -> Array[Hash[Symbol, untyped]] diff --git a/test/expectations/user.rbs b/test/expectations/user.rbs index 24bda23..0218982 100644 --- a/test/expectations/user.rbs +++ b/test/expectations/user.rbs @@ -261,17 +261,26 @@ class User < ::ApplicationRecord def temporary?: () -> bool def accepted!: () -> bool def accepted?: () -> bool + def self.statuses: () -> ::ActiveSupport::HashWithIndifferentAccess[::String, ::Integer] def self.temporary: () -> ::User::ActiveRecord_Relation + def self.not_temporary: () -> ::User::ActiveRecord_Relation def self.accepted: () -> ::User::ActiveRecord_Relation + def self.not_accepted: () -> ::User::ActiveRecord_Relation def self.all_kind_args: (untyped type, ?untyped m, ?untyped n, *untyped rest, untyped x, ?k: untyped, **untyped untyped) { (*untyped) -> untyped } -> ::User::ActiveRecord_Relation def self.no_arg: () -> ::User::ActiveRecord_Relation def self.with_attached_avatar: () -> ::User::ActiveRecord_Relation module GeneratedRelationMethods + def statuses: () -> ::ActiveSupport::HashWithIndifferentAccess[::String, ::Integer] + def temporary: () -> ::User::ActiveRecord_Relation + def not_temporary: () -> ::User::ActiveRecord_Relation + def accepted: () -> ::User::ActiveRecord_Relation + def not_accepted: () -> ::User::ActiveRecord_Relation + def all_kind_args: (untyped type, ?untyped m, ?untyped n, *untyped rest, untyped x, ?k: untyped, **untyped untyped) { (*untyped) -> untyped } -> ::User::ActiveRecord_Relation def no_arg: () -> ::User::ActiveRecord_Relation