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)