diff --git a/ams.gemspec b/ams.gemspec index 42cd4a5b..3e37ac1a 100644 --- a/ams.gemspec +++ b/ams.gemspec @@ -31,8 +31,8 @@ Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.1' - rails_versions = ['>= 4.1', '< 6'] - spec.add_runtime_dependency 'activemodel', rails_versions + # rails_versions = ['>= 4.1', '< 6'] + # spec.add_runtime_dependency 'activemodel', rails_versions # 'activesupport', rails_versions # 'builder' diff --git a/lib/ams/inflector.rb b/lib/ams/inflector.rb new file mode 100644 index 00000000..2bd30942 --- /dev/null +++ b/lib/ams/inflector.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +# Adapted from +# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb +# https://github.com/mbj/inflecto/blob/master/lib/inflecto.rb +module AMS + begin + require "active_support/inflector/methods" + # :nocov: + Inflector = ActiveSupport::Inflector + # :nocov: + rescue LoadError + module Inflector + extend self + + # Makes an underscored, lowercase form from the expression in the string. + # + # Changes '::' to '/' to convert namespaces to paths. + # + # underscore('ActiveModel') # => "active_model" + # underscore('ActiveModel::Errors') # => "active_model/errors" + # + # As a rule of thumb you can think of +underscore+ as the inverse of + # #camelize, though there are cases where that does not hold: + # + # camelize(underscore('SSLError')) # => "SslError" + def underscore(camel_cased_word) + return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word) + word = camel_cased_word.to_s.gsub("::".freeze, "/".freeze) + word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze) + word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze) + word.tr!("-".freeze, "_".freeze) + word.downcase! + word + end + + def pluralize(word) + word + "s".freeze + end + end + end +end diff --git a/lib/ams/serializer.rb b/lib/ams/serializer.rb index a09f6c3a..86592293 100644 --- a/lib/ams/serializer.rb +++ b/lib/ams/serializer.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "json" +require "ams/inflector" module AMS # Lightweight mapping of a model to a JSON API resource object # with attributes and relationships @@ -62,11 +63,21 @@ module AMS $VERBOSE = original_verbose end + # @!visibility private + def _infer_type(base) + Inflector.pluralize( + Inflector.underscore( + base.name.split("::")[-1].sub(/Serializer/, "") + ) + ) + end + def inherited(base) super base._attributes = _attributes.dup base._relations = _relations.dup - base._type = base.name.split("::")[-1].sub("Serializer", "").downcase + base._type = _infer_type(base) + add_class_method "def class; #{base}; end", base add_instance_method "def id; object.id; end", base end