lib/alba/resource.rb in alba-2.2.0 vs lib/alba/resource.rb in alba-2.3.0

- old
+ new

@@ -15,19 +15,25 @@ private_constant :DSLS WITHIN_DEFAULT = Object.new.freeze private_constant :WITHIN_DEFAULT + # `setup` method is meta-programmatically defined here for performance. # @private - def self.included(base) + def self.included(base) # rubocop:disable Metrics/MethodLength super + setup_method_body = 'private def _setup;' base.class_eval do # Initialize DSLS.each do |name, initial| instance_variable_set("@#{name}", initial.dup) unless instance_variable_defined?("@#{name}") + setup_method_body << "@#{name} = self.class.#{name};" end + base.define_method(:encode, Alba.encoder) end + setup_method_body << 'end' + base.class_eval(setup_method_body, __FILE__, __LINE__ + 1) base.include InstanceMethods base.extend ClassMethods end # Instance methods @@ -39,11 +45,11 @@ # @param within [Object, nil, false, true] determines what associations to be serialized. If not set, it serializes all associations. def initialize(object, params: {}, within: WITHIN_DEFAULT) @object = object @params = params @within = within - DSLS.each_key { |name| instance_variable_set("@#{name}", self.class.__send__(name)) } + _setup end # Serialize object into JSON string # # @param root_key [Symbol, nil, true] @@ -78,11 +84,12 @@ # # @param root_key [Symbol, nil, true] # @param meta [Hash] metadata for this seialization # @return [Hash] def as_json(root_key: nil, meta: {}) - key = root_key.nil? ? fetch_key : root_key.to_s + key = root_key.nil? ? fetch_key : root_key + key = Alba.regularize_key(key) if key && !key.empty? h = {key => serializable_hash} hash_with_metadata(h, meta) else serializable_hash @@ -97,19 +104,13 @@ end alias to_h serializable_hash private - def encode(hash) - Alba.encoder.call(hash) - end - def _to_json(root_key, meta, options) options.reject! { |k, _| %i[layout prefixes template status].include?(k) } # Rails specific guard - # TODO: use `filter_map` after dropping support of Ruby 2.6 - names = options.map { |k, v| k unless v.nil? } - names.compact! + names = options.filter_map { |k, v| k unless v.nil? } unless names.empty? names.sort! names.map! { |s| "\"#{s}\"" } message = "You passed #{names.join(', ')} options but ignored. Please refer to the document: https://github.com/okuramasafumi/alba/blob/main/docs/rails.md" Kernel.warn(message) @@ -132,11 +133,15 @@ hash end def serializable_hash_for_collection if @_collection_key - @object.to_h { |item| [item.public_send(@_collection_key).to_s, converter.call(item)] } + @object.to_h do |item| + k = item.public_send(@_collection_key) + key = Alba.regularize_key(k) + [key, converter.call(item)] + end else @object.each_with_object([], &collection_converter) end end @@ -145,38 +150,30 @@ k = collection? ? _key_for_collection : _key transforming_root_key? ? transform_key(k) : k end def _key_for_collection - if Alba.inflector - @_key_for_collection == true ? resource_name(pluralized: true) : @_key_for_collection.to_s - else - @_key_for_collection == true ? raise_root_key_inference_error : @_key_for_collection.to_s - end + k = @_key_for_collection == true ? resource_name(pluralized: true) : @_key_for_collection + Alba.regularize_key(k) end - # @return [String] def _key - if Alba.inflector - @_key == true ? resource_name(pluralized: false) : @_key.to_s - else - @_key == true ? raise_root_key_inference_error : @_key.to_s - end + k = @_key == true ? resource_name(pluralized: false) : @_key + Alba.regularize_key(k) end def resource_name(pluralized: false) - class_name = self.class.name inflector = Alba.inflector - name = inflector.demodulize(class_name).delete_suffix('Resource') + raise Alba::Error, 'You must set inflector when setting root key as true.' unless inflector + + class_name = self.class.name + suffix = class_name.end_with?('Resource') ? 'Resource' : 'Serializer' + name = inflector.demodulize(class_name).delete_suffix(suffix) underscore_name = inflector.underscore(name) pluralized ? inflector.pluralize(underscore_name) : underscore_name end - def raise_root_key_inference_error - raise Alba::Error, 'You must set inflector when setting root key as true.' - end - def transforming_root_key? @_transforming_root_key end def converter @@ -235,18 +232,20 @@ key, value = on_error.call(error, obj, key, attribute, self.class) hash[key] = value end end - # @return [Symbol] - def transform_key(key) # rubocop:disable Metrics/CyclomaticComplexity - key = key.to_s - return key if @_transform_type == :none || key.empty? # We can skip transformation + def transform_key(key) + return Alba.regularize_key(key) if @_transform_type == :none || key.nil? || key.empty? # We can skip transformation inflector = Alba.inflector raise Alba::Error, 'Inflector is nil. You must set inflector before transforming keys.' unless inflector + Alba.regularize_key(_transform_key(inflector, key.to_s)) + end + + def _transform_key(inflector, key) case @_transform_type # rubocop:disable Style/MissingElse when :camel then inflector.camelize(key) when :lower_camel then inflector.camelize_lower(key) when :dash then inflector.dasherize(key) when :snake then inflector.underscore(key) @@ -256,11 +255,12 @@ def fetch_attribute(obj, key, attribute) # rubocop:disable Metrics/CyclomaticComplexity value = case attribute when Symbol then fetch_attribute_from_object_and_resource(obj, attribute) when Proc then instance_exec(obj, &attribute) when Alba::Association then yield_if_within(attribute.name.to_sym) { |within| attribute.to_h(obj, params: params, within: within) } - when TypedAttribute, NestedAttribute then attribute.value(obj) + when TypedAttribute then attribute.value(obj) + when NestedAttribute then attribute.value(object: obj, params: params) when ConditionalAttribute then attribute.with_passing_condition(resource: self, object: obj) { |attr| fetch_attribute(obj, key, attr) } else raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}" end value.nil? && nil_handler ? instance_exec(obj, key, attribute, &nil_handler) : value @@ -325,11 +325,12 @@ assign_attributes_with_types(attrs_with_types, if_value) end def assign_attributes(attrs, if_value) attrs.each do |attr_name| - attr = if_value ? ConditionalAttribute.new(body: attr_name.to_sym, condition: if_value) : attr_name.to_sym - @_attributes[attr_name.to_sym] = attr + attr_name = attr_name.to_sym + attr = if_value ? ConditionalAttribute.new(body: attr_name, condition: if_value) : attr_name + @_attributes[attr_name] = attr end end private :assign_attributes def assign_attributes_with_types(attrs_with_types, if_value)