lib/contentful/resource.rb in contentful-0.8.0 vs lib/contentful/resource.rb in contentful-0.9.0

- old
+ new

@@ -7,44 +7,65 @@ # This is done by the default in the existing resource classes # # You can define your own classes that behave like contentful resources: # See examples/custom_classes.rb to see how. # - # Take a look at examples/resource_mapping.rb on how to register them - # to be returned by the client by default + # Take a look at examples/resource_mapping.rb on how to register them to be returned + # by the client by default + # + # @see _ examples/custom_classes.rb Custom Class as Resource + # @see _ examples/resource_mapping.rb Mapping a Custom Class module Resource + # @private + # rubocop:disable Style/DoubleNegation COERCIONS = { string: ->(v) { v.to_s }, integer: ->(v) { v.to_i }, float: ->(v) { v.to_f }, boolean: ->(v) { !!v }, date: ->(v) { DateTime.parse(v) } } + # rubocop:enable Style/DoubleNegation - attr_reader :properties, :request, :client, :default_locale + attr_reader :properties, :request, :client, :default_locale, :raw - def initialize(object = nil, request = nil, client = nil, default_locale = Contentful::Client::DEFAULT_CONFIGURATION[:default_locale]) + # @private + def initialize(object = nil, + request = nil, + client = nil, + default_locale = Contentful::Client::DEFAULT_CONFIGURATION[:default_locale]) self.class.update_coercions! @default_locale = default_locale - @properties = extract_from_object(object, :property, - self.class.property_coercions.keys) + @properties = {} + self.class.property_coercions.keys.each do |property_name| + @properties[property_name] = nil + end + + @properties = @properties.merge( + extract_from_object(object, :property, + self.class.property_coercions.keys) + ) @request = request @client = client - @api_object = object + @raw = object end + # @private def inspect(info = nil) properties_info = properties.empty? ? '' : " @properties=#{properties.inspect}" "#<#{self.class}:#{properties_info}#{info}>" end # Returns true for resources that behave like an array def array? false end + # Returns true if resource is localized + # + # @return [Boolean] def localized?(value) return false unless value.is_a? ::Hash value.keys.any? { |possible_locale| Contentful::Constants::KNOWN_LOCALES.include?(possible_locale) } end @@ -66,10 +87,61 @@ else false end end + # Register the resources properties on class level by using the #property method + # @private + module ClassMethods + # By default, fields come flattened in the current locale. This is different for sync + def property_coercions + @property_coercions ||= {} + end + + # Defines which properties of a resource your class expects + # Define them in :camelCase, they will be available as #snake_cased methods + # + # You can pass in a second "type" argument: + # - If it is a class, it will be initialized for the property + # - Symbols are looked up in the COERCION constant for a lambda that + # defines a type conversion to apply + # + # Note: This second argument is not meant for contentful sub-resources, + # but for structured objects (like locales in a space) + # Sub-resources are handled by the resource builder + def property(name, property_class = nil) + property_coercions[name.to_sym] = property_class + define_method Contentful::Support.snakify(name) do + properties[name.to_sym] + end + end + + # Ensure inherited classes pick up coercions + def update_coercions! + return if @coercions_updated + + if superclass.respond_to? :property_coercions + @property_coercions = superclass.property_coercions.dup.merge(@property_coercions || {}) + end + + if superclass.respond_to? :sys_coercions + @sys_coercions = superclass.sys_coercions.dup.merge(@sys_coercions || {}) + end + + if superclass.respond_to? :fields_coercions + @fields_coercions = superclass.fields_coercions.dup.merge(@fields_coercions || {}) + end + + @coercions_updated = true + end + end + + # @private + def self.included(base) + base.extend(ClassMethods) + end + private def initialize_fields_for_localized_resource(object) @fields = {} @@ -105,39 +177,39 @@ if value.nil? nil elsif value.is_a? ::Array value.map { |v| coerce_or_create_class(v, what) } elsif should_coerce_hash?(value) - ::Hash[value.map { |k, v| + ::Hash[value.map do |k, v| to_coerce = v.is_a?(Hash) ? v : v.to_s coercion = v.is_a?(Numeric) ? v : coerce_or_create_class(to_coerce, what) [k.to_sym, coercion] - }] + end] else coerce_or_create_class(value, what) end end def should_coerce_hash?(value) value.is_a?(::Hash) && - !self.is_a?(Asset) && - !self.is_a?(Field) && - !is_location?(value) && - !is_link?(value) && - !is_image?(value) + !is_a?(Asset) && + !is_a?(Field) && + !location?(value) && + !link?(value) && + !image?(value) end - def is_location?(value) - value.has_key?("lat") || value.has_key?("lon") + def location?(value) + value.key?('lat') || value.key?('lon') end - def is_link?(value) - value.has_key?("sys") && value["sys"]["type"] == "Link" + def link?(value) + value.key?('sys') && value['sys']['type'] == 'Link' end - def is_image?(value) - value.has_key?("image") + def image?(value) + value.key?('image') end def coerce_or_create_class(value, what) case what when Symbol @@ -145,57 +217,8 @@ when Class what.new(value, client) else value end - end - - # Register the resources properties on class level by using the #property method - module ClassMethods - # By default, fields come flattened in the current locale. This is different for sync - def property_coercions - @property_coercions ||= {} - end - - # Defines which properties of a resource your class expects - # Define them in :camelCase, they will be available as #snake_cased methods - # - # You can pass in a second "type" argument: - # - If it is a class, it will be initialized for the property - # - Symbols are looked up in the COERCION constant for a lambda that - # defines a type conversion to apply - # - # Note: This second argument is not meant for contentful sub-resources, - # but for structured objects (like locales in a space) - # Sub-resources are handled by the resource builder - def property(name, property_class = nil) - property_coercions[name.to_sym] = property_class - define_method Contentful::Support.snakify(name) do - properties[name.to_sym] - end - end - - # Ensure inherited classes pick up coercions - def update_coercions! - return if @coercions_updated - - if superclass.respond_to? :property_coercions - @property_coercions = superclass.property_coercions.dup.merge(@property_coercions || {}) - end - - if superclass.respond_to? :sys_coercions - @sys_coercions = superclass.sys_coercions.dup.merge(@sys_coercions || {}) - end - - if superclass.respond_to? :fields_coercions - @fields_coercions = superclass.fields_coercions.dup.merge(@fields_coercions || {}) - end - - @coercions_updated = true - end - end - - def self.included(base) - base.extend(ClassMethods) end end end