class Tapioca::Compilers::Dsl::ActiveRecordColumns
`Tapioca::Compilers::Dsl::ActiveRecordColumns` refines RBI
files for subclasses of [`ActiveRecord::Base`](api.rubyonrails.org/classes/ActiveRecord/Base.html). This generator is only responsible for defining the attribute methods that would be created for the columns that are defined in the Active Record model.
For example, with the following model class: ~~~rb class Post < ActiveRecord::Base end ~~~
and the following database schema:
~~~rb # db/schema.rb create_table :posts do |t|
t.string :title, null: false t.string :body t.boolean :published t.timestamps
end ~~~
this generator will produce the following methods in the RBI
file `post.rbi`:
~~~rbi # post.rbi # typed: true class Post
include GeneratedAttributeMethods module GeneratedAttributeMethods sig { returns(T.nilable(::String)) } def body; end sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) } def body=; end sig { returns(T::Boolean) } def body?; end sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) } def created_at; end sig { params(value: ::ActiveSupport::TimeWithZone).returns(::ActiveSupport::TimeWithZone) } def created_at=; end sig { returns(T::Boolean) } def created_at?; end sig { returns(T.nilable(T::Boolean)) } def published; end sig { params(value: T::Boolean).returns(T::Boolean) } def published=; end sig { returns(T::Boolean) } def published?; end sig { returns(::String) } def title; end sig { params(value: ::String).returns(::String) } def title=(value); end sig { returns(T::Boolean) } def title?; end sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) } def updated_at; end sig { params(value: ::ActiveSupport::TimeWithZone).returns(::ActiveSupport::TimeWithZone) } def updated_at=; end sig { returns(T::Boolean) } def updated_at?; end ## Also the methods added by https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html ## Also the methods added by https://api.rubyonrails.org/classes/ActiveModel/Dirty.html ## Also the methods added by https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/BeforeTypeCast.html end
end ~~~
Public Instance Methods
decorate(root, constant)
click to toggle source
# File lib/tapioca/compilers/dsl/active_record_columns.rb, line 101 def decorate(root, constant) return unless constant.table_exists? root.create_path(constant) do |model| module_name = "GeneratedAttributeMethods" model.create_module(module_name) do |mod| constant.columns_hash.each_key do |column_name| column_name = column_name.to_s add_methods_for_attribute(mod, constant, column_name) end constant.attribute_aliases.each do |attribute_name, column_name| attribute_name = attribute_name.to_s column_name = column_name.to_s new_method_names = constant.attribute_method_matchers.map { |m| m.method_name(attribute_name) } old_method_names = constant.attribute_method_matchers.map { |m| m.method_name(column_name) } methods_to_add = new_method_names - old_method_names add_methods_for_attribute(mod, constant, column_name, attribute_name, methods_to_add) end end model.create_include(module_name) end end
gather_constants()
click to toggle source
# File lib/tapioca/compilers/dsl/active_record_columns.rb, line 129 def gather_constants descendants_of(::ActiveRecord::Base).reject(&:abstract_class?) end
Private Instance Methods
add_method(klass, name, methods_to_add, return_type: "void", parameters: [])
click to toggle source
# File lib/tapioca/compilers/dsl/active_record_columns.rb, line 144 def add_method(klass, name, methods_to_add, return_type: "void", parameters: []) klass.create_method( name, parameters: parameters.map { |param, type| create_param(param, type: type) }, return_type: return_type ) if methods_to_add.nil? || methods_to_add.include?(name) end
add_methods_for_attribute(klass, constant, column_name, attribute_name = column_name, methods_to_add = nil)
click to toggle source
# File lib/tapioca/compilers/dsl/active_record_columns.rb, line 161 def add_methods_for_attribute(klass, constant, column_name, attribute_name = column_name, methods_to_add = nil) getter_type, setter_type = ActiveRecordColumnTypeHelper.new(constant).type_for(column_name) # Added by ActiveRecord::AttributeMethods::Read # add_method( klass, attribute_name.to_s, methods_to_add, return_type: getter_type ) # Added by ActiveRecord::AttributeMethods::Write # add_method( klass, "#{attribute_name}=", methods_to_add, parameters: [["value", setter_type]], return_type: setter_type ) # Added by ActiveRecord::AttributeMethods::Query # add_method( klass, "#{attribute_name}?", methods_to_add, return_type: "T::Boolean" ) # Added by ActiveRecord::AttributeMethods::Dirty # add_method( klass, "#{attribute_name}_before_last_save", methods_to_add, return_type: as_nilable_type(getter_type) ) add_method( klass, "#{attribute_name}_change_to_be_saved", methods_to_add, return_type: "T.nilable([#{getter_type}, #{getter_type}])" ) add_method( klass, "#{attribute_name}_in_database", methods_to_add, return_type: as_nilable_type(getter_type) ) add_method( klass, "saved_change_to_#{attribute_name}", methods_to_add, return_type: "T.nilable([#{getter_type}, #{getter_type}])" ) add_method( klass, "saved_change_to_#{attribute_name}?", methods_to_add, return_type: "T::Boolean" ) add_method( klass, "will_save_change_to_#{attribute_name}?", methods_to_add, return_type: "T::Boolean" ) # Added by ActiveModel::Dirty # add_method( klass, "#{attribute_name}_change", methods_to_add, return_type: "T.nilable([#{getter_type}, #{getter_type}])" ) add_method( klass, "#{attribute_name}_changed?", methods_to_add, return_type: "T::Boolean" ) add_method( klass, "#{attribute_name}_will_change!", methods_to_add ) add_method( klass, "#{attribute_name}_was", methods_to_add, return_type: as_nilable_type(getter_type) ) add_method( klass, "#{attribute_name}_previous_change", methods_to_add, return_type: "T.nilable([#{getter_type}, #{getter_type}])" ) add_method( klass, "#{attribute_name}_previously_changed?", methods_to_add, return_type: "T::Boolean" ) add_method( klass, "#{attribute_name}_previously_was", methods_to_add, return_type: as_nilable_type(getter_type) ) add_method( klass, "restore_#{attribute_name}!", methods_to_add ) # Added by ActiveRecord::AttributeMethods::BeforeTypeCast # add_method( klass, "#{attribute_name}_before_type_cast", methods_to_add, return_type: "T.untyped" ) add_method( klass, "#{attribute_name}_came_from_user?", methods_to_add, return_type: "T::Boolean" ) end
as_nilable_type(type)
click to toggle source
# File lib/tapioca/compilers/dsl/active_record_columns.rb, line 297 def as_nilable_type(type) return type if type.start_with?("T.nilable(") "T.nilable(#{type})" end