Created
April 30, 2020 17:55
-
-
Save joegaudet/965f1569cec4a107562d81a2a1364774 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class JrClientGenerator < Rails::Generators::Base | |
source_root File.expand_path('../templates', __FILE__) | |
def self.process_resource(resource_klass) | |
attributes = resource_klass._attributes.clone | |
model_klass = resource_klass._model_name.safe_constantize | |
# We only want the type value from each column, and we also need | |
# to convert the key to a symbol, if you're using non AR records to back | |
# your JR model, its not going to have an attribute hash, so lets just | |
# rescue to an empty hash | |
model_attribute_types = model_klass.columns_hash.map {|k, v| [k.to_sym, v.type]}.to_h rescue {} | |
# for each of the resource attributes, if no type information | |
# is provided, lets us the backing model annotation | |
attributes.each do |k, v| | |
attributes[k][:type] ||= model_attribute_types[k] || :any | |
end | |
relationships = resource_klass._relationships.map do |k, v| | |
{ | |
name: k, | |
type: v.class_name, | |
one: v.is_a?(JSONAPI::Relationship::ToOne) | |
} | |
end | |
filters = resource_klass.filters.map do |k, v| | |
{ | |
name: k, | |
type: v[:type] || model_attribute_types[k] || :any | |
} | |
end | |
{ | |
name: resource_klass.name.demodulize.gsub('Resource', ''), | |
attributes: attributes, | |
relationships: relationships, | |
filters: filters | |
} | |
end | |
def self.process_resources(base_resource_klass) | |
base_resource_klass.descendants.reject {|r_k| r_k._abstract}.map {|r_k| process_resource(r_k)} | |
end | |
def self.process | |
# We're using our base resource because JR nuked the descendants expected behavior | |
# so we can't enumerate the Resources | |
process_resources(API::V3::BaseResource) | |
end | |
def self.map_to_js(resources) | |
resources.map do |resource| | |
resource_name = resource[:name] | |
resource_type = resource[:name].to_s.underscore.pluralize.dasherize | |
relationships = resource[:relationships].map do |relationship| | |
rel_name = camelize(relationship[:name].to_s) | |
rel_type = relationship[:type] | |
jr_name = rel_name.underscore.dasherize | |
{ | |
name: rel_name, | |
jr_name: jr_name, | |
js_name: rel_name, | |
klass: rel_type, | |
path: relationship[:one] ? jr_name : jr_name.pluralize, | |
one: relationship[:one] | |
} | |
end | |
ones = relationships.select {|r| r[:one]} | |
manies = relationships.reject {|r| r[:one]} | |
attributes = resource[:attributes].map do |attribute, details| | |
js_name = camelize(attribute.to_s) | |
attr_name = attribute.to_s | |
jr_name = attribute.to_s.underscore.dasherize | |
attr_type = map_types(details[:type]) | |
if attr_name == 'default' | |
js_name = 'isDefault' | |
end | |
unless attr_name == 'id' | |
{ | |
jr_name: jr_name, | |
js_name: js_name, | |
name: attr_name, | |
type: attr_type | |
} | |
end | |
end | |
filters = resource[:filters].map do |filter| | |
filter[:js_name] = camelize(filter[:name]) | |
filter | |
end | |
{ | |
filters: filters, | |
klass: resource_name, | |
js_name: camelize(resource_name), | |
type: resource_type, | |
path: resource_type, | |
attrs: attributes.compact, | |
relationships: relationships, | |
ones: ones, | |
manies: manies | |
} | |
end.sort {|x, y| y[:klass] <=> x[:klass]}.reverse | |
end | |
def self.map_types(type) | |
ret = case type | |
when :text | |
:string | |
when :time | |
when :datetime | |
:Date | |
when :decimal | |
when :integer | |
:number | |
else | |
type | |
end | |
ret || '*' | |
end | |
def self.camelize(term) | |
ActiveSupport::Inflector.camelize(term, false) | |
end | |
argument :path | |
# Do the stuff | |
def generate_jr_client | |
$resources = self.class.map_to_js(self.class.process + MICRO_SERVICE_RESOURCES) | |
template 'audit.csv.erb', "#{path}src/audit.csv" | |
template 'resources.js.erb', "#{path}src/resources/resources.js" | |
template 'daos.js.erb', "#{path}src/data-access/daos.js" | |
template 'index.js.erb', "#{path}/src/index.js" | |
template 'README.md.erb', "#{path}/README.md" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I can't seem to get
base_resource_klass.descendants
to return anythingMy resources hierarchy looks like this
and the resource files like this
so I have routes like this http://localhost:3000/api/part/thing