Skip to content

Instantly share code, notes, and snippets.

@iftheshoefritz
Created July 13, 2020 18:06
Show Gist options
  • Save iftheshoefritz/7a195eb5676bb790cdbff91ab7d42f31 to your computer and use it in GitHub Desktop.
Save iftheshoefritz/7a195eb5676bb790cdbff91ab7d42f31 to your computer and use it in GitHub Desktop.
namespace :solargraph do
task generate: :environment do
# Add the folder you choose in your config/application.rb
# example:
# config.autoload_paths << Rails.root.join('app/solargraph')
gen_directory = Rails.root.join("config", "yard")
# run the script as a rails runner:
# jundle exec rails r ./bin/generate_solar_models.rb
# 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}."
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)
puts "KEY: #{key} TYPE: #{type}"
next if type.nil?
<<~TXT
# @!attribute #{key}
# @return #{type}
TXT
end
generated_attributes = <<~TXT
class #{model.name}
#{reflections.join("\n")}
#{columns.join("\n")}
end
TXT
path = gen_directory.join("#{model.model_name.singular}.rb")
File.write(path, generated_attributes)
puts("written : #{path}")
end
end
def type_translation
{
decimal: "Decimal",
integer: "Int",
date: "Date",
datetime: "DateTime",
string: "String",
boolean: "Bool"
}
end
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)
puts "Reflecting with #{reflection}"
case reflection
when ActiveRecord::Reflection::HasManyReflection
:many
when ActiveRecord::Reflection::HasAndBelongsToManyReflection
:many
when ActiveRecord::Reflection::HasOneReflection
:one
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
class_name =
if reflection.options[:class_name].present?
reflection.options[:class_name]
else
class_for(reflection.name)
end
class_name
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::HasAndBelongsToManyReflection
class_name =
if reflection.options[:class_name].present?
reflection.options[:class_name]
else
class_for(reflection.name)
end
class_name
when ActiveRecord::Reflection::HasOneReflection
reflection.name.to_s.capitalize
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
end
@iftheshoefritz
Copy link
Author

Like the name of the file says, this is plagiarized / heavily influenced by this example: https://gist.github.com/hellola/b832cff599f67a5e353e6af4914d467a

@guledali
Copy link

@iftheshoefritz What's the instruction here? How do I ran this file and where do I put it?

@iftheshoefritz
Copy link
Author

@guledali, sorry I didn't spot your question here for so long. Check out the Rails thread in the solargraph project: castwide/solargraph#87 and also the gem solargraph-rails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment