Module: OpenGraphReader::Object::DSL

Defined in:
lib/open_graph_reader/object/dsl.rb,
lib/open_graph_reader/object/dsl/types.rb

Overview

This module provides the methods to define new types and properties, as well as setting other metadata necessary to describe an object, such as its namespace.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.define_type(name) {|value, *args, options| ... } ⇒ Object

Defines a new DSL method for modeling a new type

Yields:

  • convert and validate

Yield Parameters:

  • value (::Object)

    the value to be converted and validated

  • *args (Array<::Object>)

    any additional arguments

  • options ({Symbol => Bool, Class, Array<String>})

    the options hash as last parameter



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/open_graph_reader/object/dsl.rb', line 32

def self.define_type(name, &processor)
  processors[name] = processor

  define_method(name) do |name, *args|
    options = args.pop if args.last.is_a? Hash
    options ||= {}

    available_properties << name.to_s
    required_properties << name.to_s if options[:required]
    Registry.register [@namespace, name].join(':'), options[:to] if options[:to]

    if options[:verticals]
      options[:verticals].each do |vertical|
        vertical = [@namespace, vertical].join('.')
        verticals[vertical] << name.to_s
        Registry.verticals <<  vertical
      end
    end

    if options[:collection]
      define_method("#{name}s") do
        children[name.to_s]
      end

      define_method(name) do
        value = children[name.to_s].first
        # @todo figure out a sane way to distinguish subobject properties
        value.content if value && value.is_a?(Object)
        value || options[:default]
      end
    else
      define_method(name) do
        properties[name.to_s] || options[:default]
      end

      define_method("#{name}=") do |value|
        # @todo figure out a sane way to distinguish subobject properties
        unless value.is_a? Object
          value.downcase! if options[:downcase]
          value = processor.call(value, *args, options)
        end
        properties[name.to_s] = value
      end
    end
  end
end

.processors{Symbol => Proc}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A map from type names to processing blocks.

Returns:

  • ({Symbol => Proc})


135
136
137
# File 'lib/open_graph_reader/object/dsl.rb', line 135

def self.processors
  @processors ||= {}
end

Instance Method Details

#available_propertiesArray<String>

The list of defined properties on this object.

Returns:

  • (Array<String>)


120
121
122
# File 'lib/open_graph_reader/object/dsl.rb', line 120

def available_properties
  @available_properties ||= []
end

#boolean(name, options = {}) ⇒ Object

Parameters:

  • name (Symbol)

    the name of the property in the current namespace

  • options ({Symbol => Bool, Class, Array<String>}) (defaults to: {})

    additional options

Options Hash (options):

  • :required (Bool) — default: false

    Make the property required.

  • :collection (Bool) — default: false

    This property can occur multiple times.

  • :to (Class)

    This property maps to the given object (optional). belongs to the given verticals of the object (optional).

  • :verticials (Array<String>)

    This property

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.



80
81
82
83
84
85
86
# File 'lib/open_graph_reader/object/dsl/types.rb', line 80

define_type :boolean do |value|
  {'true' => true, 'false' => false, '1' => true, '0' => false}[value].tap {|bool|
    if bool.nil?
      raise InvalidObjectError, "Boolean expected, but was #{value.inspect}"
    end
  }
end

#content(type, *args, options = {}) ⇒ Object

Set the type for the content attribute

Parameters:

  • type (Symbol)

    one of the registered types.

  • args (Array<Object>)

    Additional parameters for the type

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.



106
107
108
109
110
111
112
113
114
115
# File 'lib/open_graph_reader/object/dsl.rb', line 106

def content type, *args
  options = args.pop if args.last.is_a? Hash
  options ||= {}

  @content_processor = proc {|value|
    value.downcase! if options[:downcase]
    options[:to] ||= self
    DSL.processors[type].call(value, *args, options)
  }
end

#content_processorProc

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The processor for the content attribute.

Returns:

  • (Proc)


143
144
145
# File 'lib/open_graph_reader/object/dsl.rb', line 143

def content_processor
  @content_processor
end

#datetime(name, options = {}) ⇒ Object

Parameters:

  • name (Symbol)

    the name of the property in the current namespace

  • options ({Symbol => Bool, Class, Array<String>}) (defaults to: {})

    additional options

Options Hash (options):

  • :required (Bool) — default: false

    Make the property required.

  • :collection (Bool) — default: false

    This property can occur multiple times.

  • :to (Class)

    This property maps to the given object (optional). belongs to the given verticals of the object (optional).

  • :verticials (Array<String>)

    This property

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.



71
72
73
74
75
76
77
# File 'lib/open_graph_reader/object/dsl/types.rb', line 71

define_type :datetime do |value|
  begin
    DateTime.iso8601 value
  rescue ArgumentError => e
    raise InvalidObjectError, "ISO8601 datetime expected, but was #{value.inspect}"
  end
end

#enum(name, allowed, options = {}) ⇒ Object

Parameters:

  • allowed (Array<String>)

    the list of allowed values

  • name (Symbol)

    the name of the property in the current namespace

  • options ({Symbol => Bool, Class, Array<String>}) (defaults to: {})

    additional options

Options Hash (options):

  • :required (Bool) — default: false

    Make the property required.

  • :collection (Bool) — default: false

    This property can occur multiple times.

  • :to (Class)

    This property maps to the given object (optional). belongs to the given verticals of the object (optional).

  • :verticials (Array<String>)

    This property

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.

See Also:



53
54
55
56
57
58
59
# File 'lib/open_graph_reader/object/dsl/types.rb', line 53

define_type_no_doc :enum do |value, allowed|
  unless allowed.include? value
    raise InvalidObjectError, "Expected one of #{allowed.inspect} but was #{value.inspect}"
  end

  value.to_s
end

#float(name, options = {}) ⇒ Object

Parameters:

  • name (Symbol)

    the name of the property in the current namespace

  • options ({Symbol => Bool, Class, Array<String>}) (defaults to: {})

    additional options

Options Hash (options):

  • :required (Bool) — default: false

    Make the property required.

  • :collection (Bool) — default: false

    This property can occur multiple times.

  • :to (Class)

    This property maps to the given object (optional). belongs to the given verticals of the object (optional).

  • :verticials (Array<String>)

    This property

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.



89
90
91
92
93
94
95
# File 'lib/open_graph_reader/object/dsl/types.rb', line 89

define_type :float do |value|
  begin
    Float(value)
  rescue ArgumentError => e
    raise InvalidObjectError, "Float expected, but was #{value.inspect}"
  end
end

#integer(name, options = {}) ⇒ Object

Parameters:

  • name (Symbol)

    the name of the property in the current namespace

  • options ({Symbol => Bool, Class, Array<String>}) (defaults to: {})

    additional options

Options Hash (options):

  • :required (Bool) — default: false

    Make the property required.

  • :collection (Bool) — default: false

    This property can occur multiple times.

  • :to (Class)

    This property maps to the given object (optional). belongs to the given verticals of the object (optional).

  • :verticials (Array<String>)

    This property

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.



62
63
64
65
66
67
68
# File 'lib/open_graph_reader/object/dsl/types.rb', line 62

define_type :integer do  |value|
  begin
    Integer(value)
  rescue  ArgumentError => e
    raise InvalidObjectError, "Integer expected, but was #{value.inspect}"
  end
end

#namespaceString #namespace(*names) ⇒ Object

Overloads:

  • #namespaceString

    Get the namespace of this object.

    Returns:

    • (String)

      A colon separated namespace, for example og:image.

  • #namespace(*names) ⇒ Object

    Set the namespace of this object.

    Examples:

    namespace :og, :image

    Parameters:

    • *names (Array<#to_s>)

      The individual parts of the namespace as list



92
93
94
95
96
# File 'lib/open_graph_reader/object/dsl.rb', line 92

def namespace *names
  return @namespace if names.empty?
  @namespace = names.join(':')
  Registry.register @namespace, self
end

#required_propertiesArray<String]

The list of required properties on this object.

Returns:

  • (Array<String])

    Array<String]



127
128
129
# File 'lib/open_graph_reader/object/dsl.rb', line 127

def required_properties
  @required_properties ||= []
end

#string(name, options = {}) ⇒ Object

Parameters:

  • name (Symbol)

    the name of the property in the current namespace

  • options ({Symbol => Bool, Class, Array<String>}) (defaults to: {})

    additional options

Options Hash (options):

  • :required (Bool) — default: false

    Make the property required.

  • :collection (Bool) — default: false

    This property can occur multiple times.

  • :to (Class)

    This property maps to the given object (optional). belongs to the given verticals of the object (optional).

  • :verticials (Array<String>)

    This property

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.



10
11
12
# File 'lib/open_graph_reader/object/dsl/types.rb', line 10

define_type :string do |value|
  value.to_s
end

#url(name, options = {}) ⇒ Object

Parameters:

  • name (Symbol)

    the name of the property in the current namespace

  • options ({Symbol => Bool, Class, Array<String>}) (defaults to: {})

    additional options

Options Hash (options):

  • :image (Bool) — default: false

    Mark attribute as image to be eligible for URL synthesization. See Configuration#synthesize_image_url.

  • :required (Bool) — default: false

    Make the property required.

  • :collection (Bool) — default: false

    This property can occur multiple times.

  • :to (Class)

    This property maps to the given object (optional). belongs to the given verticals of the object (optional).

  • :verticials (Array<String>)

    This property

  • :downcase (Bool) — default: false

    Normalize the contents case to lowercase.

See Also:



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/open_graph_reader/object/dsl/types.rb', line 19

define_type_no_doc :url do |value, options|
  value = value.to_s

  unless value.start_with?('http://') || value.start_with?('https://')
    if options[:image] && OpenGraphReader.config.synthesize_image_url
      unless OpenGraphReader.current_origin
        raise ArgumentError, "Enabled image url synthesization but didn't pass an origin"
      end

      # Synthesize scheme hack to https (//example.org/foo/bar.png)
      if value.start_with?('//') && value.split('/', 4)[2] =~ URI::HOST
        value = "https:#{value}"
      else # Synthesize absolute path (/foo/bar.png)
        begin
          value = "/#{value}" unless value.start_with? '/' # Normalize to absolute path
          uri = URI.parse(OpenGraphReader.current_origin)
          uri.path = value
          value = uri.to_s
        rescue
          raise InvalidObjectError, "URL #{value.inspect} does not start with http:// or https:// and failed to synthesize a full URL"
        end
      end
    elsif options.has_key?(:to) && OpenGraphReader.config.validate_references
      raise InvalidObjectError, "URL #{value.inspect} does not start with http:// or https://"
    end
  end

  value
end

#verticals{String => Array<Strin>}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A map from vertical names to attributes that belong to them.

Returns:

  • ({String => Array<Strin>})


151
152
153
# File 'lib/open_graph_reader/object/dsl.rb', line 151

def verticals
  @verticals ||= Hash.new {|h, k| h[k] = [] }
end