Skip to content

Instantly share code, notes, and snippets.

@hellola
Last active September 12, 2022 23:27
Show Gist options
  • Save hellola/b832cff599f67a5e353e6af4914d467a to your computer and use it in GitHub Desktop.
Save hellola/b832cff599f67a5e353e6af4914d467a to your computer and use it in GitHub Desktop.
# Add the folder you choose in your config/application.rb
# example:
# config.autoload_paths << Rails.root.join('app/solargraph')
gen_directory = Rails.root.join("app", "solargraph")
# run the script as a rails runner:
# bundle exec rails r ./bin/generate_solar_models.rb
type_translation = {
decimal: "Decimal",
integer: "Int",
date: "Date",
datetime: "DateTime",
string: "String",
boolean: "Bool"
}
def class_for(name)
name = name.to_s
found = ApplicationRecord.descendants.detect do |model|
model.model_name.plural == name || model.model_name.singular == name
end
found&.first&.model_name&.name
end
def reflection_type(reflection)
case reflection
when ActiveRecord::Reflection::HasManyReflection
:many
when ActiveRecord::Reflection::HasOneReflection
when ActiveRecord::Reflection::BelongsToReflection
:one
when ActiveRecord::Reflection::ThroughReflection
reflection_type(reflection.through_reflection)
else
puts("# cannot infer association for #{reflection.name} -> #{reflection.class}")
nil
end
end
def reflection_class_name(reflection)
case reflection
when ActiveRecord::Reflection::HasManyReflection
when ActiveRecord::Reflection::ThroughReflection
class_name =
if reflection.options[:class_name].present?
reflection.options[:class_name]
else
class_for(reflection.name)
end
class_name
when ActiveRecord::Reflection::HasOneReflection
when ActiveRecord::Reflection::BelongsToReflection
reflection.name.to_s.capitalize
else
puts("# cannot infer association for #{reflection.name} -> #{reflection.class}")
nil
end
end
def reflection_comment(reflection)
case reflection_type(reflection)
when :one
"[#{reflection_class_name(reflection)}]"
when :many
"[Array<#{reflection_class_name(reflection)}>]"
end
end
# if you wanted to choose specific models to generate for
# models = [User]
Rails.application.eager_load!
models = ApplicationRecord.descendants
puts("generating for #{models.count} models")
models.each do |model|
puts "processing #{model.name}."
attributes =
columns = model.columns.map do |col|
type = type_translation[col.type]
<<-TXT
# @!attribute #{col.name}
# @return [#{type}]
TXT
end
reflections = model.reflections.map do |key, reflection|
type = reflection_comment(reflection)
next if type.nil?
<<-TXT
# @!attribute #{key}
# @return #{type}
TXT
end
generated_attributes = <<-TXT
class #{model.name}
#{reflections.join("\n")}
#{attributes.join("\n")}
end
TXT
path = gen_directory.join("#{model.model_name.singular}_attrs.rb")
File.write(path, generated_attributes)
puts("written : #{path}")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment