# typed: strict # frozen_string_literal: true begin require "active_resource" rescue LoadError return end module Tapioca module Dsl module Compilers # `Tapioca::Dsl::Compilers::ActiveResource` decorates RBI files for subclasses of # [`ActiveResource::Base`](https://github.com/rails/activeresource) which declare # `schema` fields. # # For example, with the following `ActiveResource::Base` subclass: # # ~~~rb # class Post < ActiveResource::Base # schema do # integer 'id', 'month', 'year' # end # end # ~~~ # # this compiler will produce the RBI file `post.rbi` with the following content: # # ~~~rbi # # post.rbi # # typed: true # class Post # sig { returns(Integer) } # def id; end # # sig { params(id: Integer).returns(Integer) } # def id=(id); end # # sig { returns(T::Boolean) } # def id?; end # # sig { returns(Integer) } # def month; end # # sig { params(month: Integer).returns(Integer) } # def month=(month); end # # sig { returns(T::Boolean) } # def month?; end # # sig { returns(Integer) } # def year; end # # sig { params(year: Integer).returns(Integer) } # def year=(year); end # # sig { returns(T::Boolean) } # def year?; end # end # ~~~ class ActiveResource < Compiler extend T::Sig ConstantType = type_member(fixed: T.class_of(::ActiveResource::Base)) sig { override.void } def decorate return if constant.schema.blank? root.create_path(constant) do |resource| constant.schema.each do |attribute, type| create_schema_methods(resource, attribute, type) end end end sig { override.returns(T::Enumerable[Module]) } def self.gather_constants descendants_of(::ActiveResource::Base) end private TYPES = T.let({ boolean: "T::Boolean", integer: "Integer", string: "String", float: "Float", date: "Date", time: "Time", datetime: "DateTime", decimal: "BigDecimal", binary: "String", text: "String", }.freeze, T::Hash[Symbol, String]) sig { params(attr_type: Symbol).returns(String) } def type_for(attr_type) TYPES.fetch(attr_type, "T.untyped") end sig { params(klass: RBI::Scope, attribute: String, type: String).void } def create_schema_methods(klass, attribute, type) return_type = type_for(type.to_sym) klass.create_method(attribute, return_type: return_type) klass.create_method("#{attribute}?", return_type: "T::Boolean") klass.create_method("#{attribute}=", parameters: [ create_param("value", type: return_type), ], return_type: return_type) end end end end end