occi 2.5.19 → 3.0.0.beta.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.travis.yml +3 -1
- data/AUTHORS +4 -3
- data/Gemfile +9 -0
- data/Gemfile.lock +64 -21
- data/README.md +19 -14
- data/Rakefile +12 -8
- data/Test Results - discovery_interface.html +862 -0
- data/bin/occi +333 -83
- data/examples/dsl_example.rb +6 -6
- data/examples/x509auth_example.rb +6 -6
- data/features/common/step_definitions/common_steps.rb +32 -0
- data/features/occi/core/create/create.feature +17 -0
- data/features/occi/core/create/step_definitions/create_steps.rb +0 -0
- data/features/occi/core/delete/delete.feature +14 -0
- data/features/occi/core/delete/step_definitions/delete_steps.rb +0 -0
- data/features/occi/core/discovery_interface/discovery_interface.feature +35 -0
- data/features/occi/core/discovery_interface/step_definitions/discovery_interface_steps.rb +19 -0
- data/features/occi/core/miscellaneous/miscellaneous.feature +14 -0
- data/features/occi/core/miscellaneous/step_definitions/miscellaneous_steps.rb +0 -0
- data/features/occi/core/read/read.feature +14 -0
- data/features/occi/core/read/step_definitions/read_steps.rb +0 -0
- data/features/occi/core/update/step_definitions/update_steps.rb +0 -0
- data/features/occi/core/update/update.feature +14 -0
- data/features/occi/infrastructure/create/create.feature +14 -0
- data/features/occi/infrastructure/create/step_definitions/create_steps.rb +0 -0
- data/features/support/env.rb +4 -0
- data/lib/occi.rb +29 -3
- data/lib/occi/api/client/client_amqp.rb +756 -0
- data/lib/occi/api/client/client_http.rb +922 -0
- data/lib/occi/api/client/http/httparty_fix.rb +53 -0
- data/lib/occi/api/client/http/net_http_fix.rb +46 -0
- data/lib/occi/api/dsl.rb +77 -73
- data/lib/occi/bin/helpers.rb +91 -0
- data/lib/occi/bin/occi_opts.rb +251 -0
- data/lib/occi/bin/resource_output_factory.rb +90 -0
- data/lib/occi/bin/templates/compute.erb +15 -0
- data/lib/occi/bin/templates/network.erb +11 -0
- data/lib/occi/bin/templates/os_tpl.erb +9 -0
- data/lib/occi/bin/templates/resource_tpl.erb +9 -0
- data/lib/occi/bin/templates/storage.erb +10 -0
- data/lib/occi/collection.rb +122 -25
- data/lib/occi/core.rb +18 -9
- data/lib/occi/core/action.rb +20 -4
- data/lib/occi/core/action_instance.rb +24 -0
- data/lib/occi/core/actions.rb +22 -0
- data/lib/occi/core/attribute_properties.rb +33 -84
- data/lib/occi/core/attributes.rb +32 -14
- data/lib/occi/core/categories.rb +46 -0
- data/lib/occi/core/category.rb +94 -20
- data/lib/occi/core/entities.rb +50 -0
- data/lib/occi/core/entity.rb +130 -89
- data/lib/occi/core/kind.rb +28 -35
- data/lib/occi/core/kinds.rb +22 -0
- data/lib/occi/core/link.rb +43 -40
- data/lib/occi/core/links.rb +34 -0
- data/lib/occi/core/mixin.rb +28 -23
- data/lib/occi/core/mixins.rb +22 -0
- data/lib/occi/core/related.rb +20 -0
- data/lib/occi/core/resource.rb +40 -40
- data/lib/occi/core/resources.rb +14 -0
- data/lib/occi/infrastructure.rb +27 -0
- data/lib/occi/infrastructure/compute.rb +159 -0
- data/lib/occi/infrastructure/network.rb +131 -0
- data/lib/occi/infrastructure/network/ipnetwork.rb +34 -0
- data/lib/occi/infrastructure/networkinterface.rb +124 -0
- data/lib/occi/infrastructure/networkinterface/ipnetworkinterface.rb +34 -0
- data/lib/occi/infrastructure/os_tpl.rb +19 -0
- data/lib/occi/infrastructure/resource_tpl.rb +19 -0
- data/lib/occi/infrastructure/storage.rb +96 -0
- data/lib/occi/infrastructure/storagelink.rb +73 -0
- data/lib/occi/log.rb +6 -2
- data/lib/occi/model.rb +38 -70
- data/lib/occi/parser.rb +108 -88
- data/lib/occi/version.rb +2 -2
- data/lib/occiantlr/OCCIANTLR.g +6 -5
- data/lib/occiantlr/OCCIANTLRLexer.rb +52 -52
- data/lib/occiantlr/OCCIANTLRParser.rb +678 -569
- data/lib/occiantlr/README.md +1 -1
- data/occi.gemspec +2 -1
- data/spec/cassettes/client_http_text_plain.yml +1066 -0
- data/spec/occi/api/client/client_amqp_spec.rb +148 -0
- data/spec/occi/api/client/client_http_0.5_spec.rb +292 -0
- data/spec/occi/api/client/client_http_spec.rb +259 -0
- data/spec/occi/api/dsl_spec.rb +0 -0
- data/spec/occi/collection_spec.rb +23 -10
- data/spec/occi/core/categories_spec.rb +30 -0
- data/spec/occi/core/category_spec.rb +41 -0
- data/spec/occi/core/entity_spec.rb +52 -0
- data/spec/occi/core/resource_spec.rb +21 -0
- data/spec/occi/infrastructure/compute_spec.rb +32 -0
- data/spec/occi/log_spec.rb +10 -10
- data/spec/occi/model_spec.rb +24 -24
- data/spec/occi/parser_spec.rb +89 -39
- data/spec/occi/test.json +22 -58
- data/spec/occiantlr/parser_spec.rb +5 -7
- data/spec/spec_helper.rb +13 -3
- metadata +116 -19
- data/etc/model/infrastructure/compute.json +0 -108
- data/etc/model/infrastructure/ipnetwork.json +0 -40
- data/etc/model/infrastructure/ipnetworkinterface.json +0 -40
- data/etc/model/infrastructure/network.json +0 -55
- data/etc/model/infrastructure/networkinterface.json +0 -38
- data/etc/model/infrastructure/os_template.json +0 -9
- data/etc/model/infrastructure/resource_template.json +0 -9
- data/etc/model/infrastructure/storage.json +0 -72
- data/etc/model/infrastructure/storagelink.json +0 -38
- data/lib/occi/api/client.rb +0 -596
- data/lib/occi/client/occiopts.rb +0 -146
- data/spec/occi/client_spec.rb +0 -12
@@ -1,99 +1,48 @@
|
|
1
1
|
require 'hashie/mash'
|
2
2
|
|
3
|
-
module
|
3
|
+
module Occi
|
4
4
|
module Core
|
5
5
|
class AttributeProperties < Hashie::Mash
|
6
6
|
|
7
|
-
# @param [
|
7
|
+
# @param [Hash] properties
|
8
8
|
# @param [Hash] default
|
9
|
-
def initialize(
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
super(attributes, default)
|
9
|
+
def initialize(properties=nil,default=nil)
|
10
|
+
properties ||= {}
|
11
|
+
properties[:type] ||= 'string'
|
12
|
+
properties[:required] ||= false
|
13
|
+
properties[:mutable] ||= false
|
14
|
+
properties[:pattern] ||= '.*'
|
15
|
+
super properties, default
|
17
16
|
end
|
18
17
|
|
19
|
-
# @
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
# @param [Hash] properties
|
19
|
+
# @return [Occi::Core::Attributes] parsed Attribute Properties
|
20
|
+
def self.parse(properties)
|
21
|
+
properties ||= Hashie::Mash.new
|
22
|
+
if [:Type, :Required, :Mutable, :Default, :Description, :Pattern, :type, :required, :mutable, :default, :description, :pattern].any? { |k| properties.key?(k) and not properties[k].kind_of? Hash }
|
23
|
+
properties[:type] ||= properties[:Type] ||= "string"
|
24
|
+
properties[:required] ||= properties[:Required] ||= false
|
25
|
+
properties[:mutable] ||= properties[:Mutable] ||= false
|
26
|
+
properties[:default] = properties[:Default] if properties[:Default]
|
27
|
+
properties[:description] = properties[:Description] if properties[:Description]
|
28
|
+
properties[:pattern] ||= properties[:Pattern] ||= ".*"
|
29
|
+
properties.delete :Type
|
30
|
+
properties.delete :Required
|
31
|
+
properties.delete :Mutable
|
32
|
+
properties.delete :Default
|
33
|
+
properties.delete :Description
|
34
|
+
properties.delete :Pattern
|
35
|
+
return self.new properties
|
36
|
+
else
|
37
|
+
attributes = Occi::Core::Attributes.new
|
38
|
+
properties.each_key do |key|
|
39
|
+
attributes[key] = self.parse properties[key]
|
28
40
|
end
|
29
|
-
|
30
|
-
array
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
# @return [Hash] key value pairs of attribute names with their defaults set
|
35
|
-
def combine_with_defaults
|
36
|
-
hash = { }
|
37
|
-
self.each_key do |key|
|
38
|
-
if self[key].include?('Type') || self[key].include?('type')
|
39
|
-
hash[key] = self[key]['Default']
|
40
|
-
else
|
41
|
-
self[key].combine_with_defaults.each { |k, v| hash[key + '.' + k] = v }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
hash
|
45
|
-
end
|
46
|
-
|
47
|
-
def convert_value(val, duping=false) #:nodoc:
|
48
|
-
case val
|
49
|
-
when self.class
|
50
|
-
val.dup
|
51
|
-
when ::Hash
|
52
|
-
val = val.dup if duping
|
53
|
-
self.class.subkey_class.new(val)
|
54
|
-
when Array
|
55
|
-
val.collect { |e| convert_value(e) }
|
56
|
-
else
|
57
|
-
val
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# Overrides method of hashie mash to check if one of the attribute properties has been set
|
62
|
-
def method_missing(method_name, *args, &blk)
|
63
|
-
return self.[](method_name, &blk) if key?(method_name)
|
64
|
-
match = method_name.to_s.match(/(.*?)([?=!]?)$/)
|
65
|
-
case match[2]
|
66
|
-
when "="
|
67
|
-
key = match[1]
|
68
|
-
self[key] = args.first
|
69
|
-
if %w|Type Required Mutable Pattern Default Minimum Maximum Description|.any? { |k| key.to_s.capitalize == k }
|
70
|
-
self["Type"] = "string" unless key?("Type") || key?("type")
|
71
|
-
self["Required"] = false unless key?("Required") || key?("required")
|
72
|
-
self["Mutable"] = false unless key?("Mutable") || key?("mutable")
|
73
|
-
self["Pattern"] = ".*" unless key?("Pattern") || key?("pattern")
|
74
|
-
end
|
75
|
-
when "?"
|
76
|
-
!!self[match[1]]
|
77
|
-
when "!"
|
78
|
-
initializing_reader(match[1])
|
79
|
-
else
|
80
|
-
default(method_name, *args, &blk)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Sets an attribute in the Mash. Key will be converted to
|
85
|
-
# a string before it is set, and Hashes will be converted
|
86
|
-
# into Mashes for nesting purposes.
|
87
|
-
def []=(key, value) #:nodoc:
|
88
|
-
regular_writer(convert_key(key), convert_value(value))
|
89
|
-
if %w|Type Required Mutable Pattern Default Minimum Maximum Description|.any? { |k| key.to_s.capitalize == k }
|
90
|
-
self["Type"] = "string" unless key?("Type") || key?("type")
|
91
|
-
self["Required"] = false unless key?("Required") || key?("required")
|
92
|
-
self["Mutable"] = false unless key?("Mutable") || key?("mutable")
|
93
|
-
self["Pattern"] = ".*" unless key?("Pattern") || key?("pattern")
|
41
|
+
return attributes
|
94
42
|
end
|
95
43
|
end
|
96
44
|
|
45
|
+
# @return [String] json representation
|
97
46
|
def inspect
|
98
47
|
JSON.pretty_generate(JSON.parse(to_json))
|
99
48
|
end
|
data/lib/occi/core/attributes.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'hashie/mash'
|
2
2
|
|
3
|
-
module
|
3
|
+
module Occi
|
4
4
|
module Core
|
5
5
|
class Attributes < Hashie::Mash
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
# @return [Array] key value pair of full attribute names with their corresponding values
|
8
|
+
def combine
|
9
9
|
hash = { }
|
10
10
|
self.each_key do |key|
|
11
|
-
if self[key].kind_of?
|
11
|
+
if self[key].kind_of? Occi::Core::Attributes
|
12
12
|
self[key].combine.each_pair { |k, v| hash[key + '.' + k] = v }
|
13
13
|
else
|
14
14
|
hash[key] = self[key]
|
@@ -17,12 +17,34 @@ module OCCI
|
|
17
17
|
hash
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def convert_value(val, duping=false) #:nodoc:
|
21
|
+
case val
|
22
|
+
when self.class
|
23
|
+
val.dup
|
24
|
+
when Hashie::Mash
|
25
|
+
val = val.dup if duping
|
26
|
+
val
|
27
|
+
when ::Hash
|
28
|
+
val = val.dup if duping
|
29
|
+
self.class.subkey_class.new.merge(val)
|
30
|
+
when Array
|
31
|
+
val.collect { |e| convert_value(e) }
|
32
|
+
else
|
33
|
+
val
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [String] json representation
|
38
|
+
def inspect
|
39
|
+
JSON.pretty_generate(JSON.parse(to_json))
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [Hash] attributes key value pair of full attribute names with their corresponding values
|
43
|
+
# @return [Occi::Core::Attributes]
|
44
|
+
def self.split(attributes)
|
23
45
|
attribute = Attributes.new
|
24
|
-
attributes.each do |name,value|
|
25
|
-
|
46
|
+
attributes.each do |name, value|
|
47
|
+
Occi::Log.debug "Attribute named #{name}"
|
26
48
|
key, _, rest = name.partition('.')
|
27
49
|
if rest.empty?
|
28
50
|
attribute[key] = value
|
@@ -35,9 +57,5 @@ module OCCI
|
|
35
57
|
|
36
58
|
end
|
37
59
|
|
38
|
-
def inspect
|
39
|
-
JSON.pretty_generate(JSON.parse(to_json))
|
40
|
-
end
|
41
|
-
|
42
60
|
end
|
43
|
-
end
|
61
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Occi
|
2
|
+
module Core
|
3
|
+
class Categories < Set
|
4
|
+
|
5
|
+
attr_accessor :model
|
6
|
+
|
7
|
+
def initialize(categories=[])
|
8
|
+
categories.collect! { |category| convert category } if categories
|
9
|
+
super categories
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(category)
|
13
|
+
super convert category
|
14
|
+
end
|
15
|
+
|
16
|
+
def join(separator)
|
17
|
+
self.to_a.join(separator)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [Occi::Model] model
|
21
|
+
# @return [Occi::Model]
|
22
|
+
def model=(model)
|
23
|
+
@model = model
|
24
|
+
collect! { |category| model.get_by_id category.to_s or category }
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param [Hash] options
|
28
|
+
# @return [Hashie::Mash] json representation
|
29
|
+
def as_json(options={ })
|
30
|
+
self.to_a.as_json
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String] json representation
|
34
|
+
def inspect
|
35
|
+
JSON.pretty_generate(JSON.parse(to_json))
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def convert(category)
|
41
|
+
(@model.get_by_id category if @model if category.kind_of? String) or category
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/occi/core/category.rb
CHANGED
@@ -1,22 +1,76 @@
|
|
1
|
-
|
2
|
-
require 'active_support/inflector'
|
3
|
-
require 'hashie/mash'
|
4
|
-
|
5
|
-
module OCCI
|
1
|
+
module Occi
|
6
2
|
module Core
|
7
3
|
class Category
|
8
4
|
|
9
|
-
attr_accessor :
|
5
|
+
attr_accessor :scheme, :term, :title, :attributes, :model
|
6
|
+
|
7
|
+
def self.categories
|
8
|
+
self.mixins + self.actions << self.kind
|
9
|
+
end
|
10
10
|
|
11
11
|
# @param [String ] scheme
|
12
12
|
# @param [String] term
|
13
13
|
# @param [String] title
|
14
|
-
# @param [
|
15
|
-
def initialize(scheme
|
14
|
+
# @param [Hash] attributes
|
15
|
+
def initialize(scheme='http://schemas.ogf.org/occi/core#',
|
16
|
+
term='category',
|
17
|
+
title=nil,
|
18
|
+
attributes=Occi::Core::Attributes.new)
|
16
19
|
@scheme = scheme
|
17
20
|
@term = term
|
18
21
|
@title = title
|
19
|
-
@attributes =
|
22
|
+
@attributes = Occi::Core::AttributeProperties.parse attributes
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] scheme
|
26
|
+
# @param [String] term
|
27
|
+
# @param [Array] related
|
28
|
+
# @return [Class] ruby class with scheme as namespace, term as name and related kind as super class
|
29
|
+
def self.get_class(scheme, term, related=['http://schemas.ogf.org/occi/core#entity'])
|
30
|
+
related = related.to_a.flatten
|
31
|
+
scheme += '#' unless scheme.end_with? '#'
|
32
|
+
|
33
|
+
if related.first.to_s == 'http://schemas.ogf.org/occi/core#entity' or related.first.nil?
|
34
|
+
parent = Occi::Core::Entity
|
35
|
+
elsif related.first.kind_of? Occi::Core::Category
|
36
|
+
parent = related.first.class
|
37
|
+
else
|
38
|
+
related_scheme, related_term = related.first.to_s.split '#'
|
39
|
+
parent = self.get_class related_scheme, related_term
|
40
|
+
end
|
41
|
+
|
42
|
+
uri = URI.parse(scheme)
|
43
|
+
|
44
|
+
namespace = if uri.host == 'schemas.ogf.org'
|
45
|
+
uri.path.reverse.chomp('/').reverse.split('/')
|
46
|
+
else
|
47
|
+
uri.host.split('.').reverse + uri.path.reverse.chomp('/').reverse.split('/')
|
48
|
+
end
|
49
|
+
|
50
|
+
namespace = namespace.inject(Object) do |mod, name|
|
51
|
+
if mod.constants.collect { |sym| sym.to_s }.include? name.classify
|
52
|
+
mod.const_get name.classify
|
53
|
+
else
|
54
|
+
mod.const_set name.classify, Module.new
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
if namespace.const_defined? term.classify
|
59
|
+
klass = namespace.const_get term.classify
|
60
|
+
unless klass.ancestors.include? Occi::Core::Entity or klass.ancestors.include? Occi::Core::Category
|
61
|
+
raise "OCCI Kind with type identifier #{scheme + term} could not be created as the corresponding class #{klass.to_s} already exists and is not derived from Occi::Core::Entity"
|
62
|
+
end
|
63
|
+
else
|
64
|
+
klass = namespace.const_set term.classify, Class.new(parent)
|
65
|
+
klass.kind = Occi::Core::Kind.new scheme, term, nil, { }, related unless parent.ancestors.include? Occi::Core::Category
|
66
|
+
end
|
67
|
+
|
68
|
+
klass
|
69
|
+
end
|
70
|
+
|
71
|
+
# @param [Occi::Model] model
|
72
|
+
def model=(model)
|
73
|
+
@related.model=model if @related
|
20
74
|
end
|
21
75
|
|
22
76
|
# @return [String] Type identifier of the category
|
@@ -25,12 +79,12 @@ module OCCI
|
|
25
79
|
end
|
26
80
|
|
27
81
|
# check if category is related to another category
|
28
|
-
# @param [String]
|
82
|
+
# @param [String, Category] category Related Category or its type identifier
|
29
83
|
# @return [true,false] true if category is related to category_id else false
|
30
|
-
def related_to?(
|
31
|
-
self.related.each do |
|
32
|
-
return true if
|
33
|
-
end if
|
84
|
+
def related_to?(category)
|
85
|
+
self.related.each do |cat|
|
86
|
+
return true if cat.to_s == category.to_s
|
87
|
+
end if @related
|
34
88
|
false
|
35
89
|
end
|
36
90
|
|
@@ -45,22 +99,42 @@ module OCCI
|
|
45
99
|
category
|
46
100
|
end
|
47
101
|
|
102
|
+
# @return [String] short text representation of the category
|
103
|
+
def to_string_short
|
104
|
+
@term + ';scheme=' + @scheme.inspect + ';class=' + self.class.name.demodulize.downcase.inspect
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [String] full text representation of the category
|
108
|
+
def to_string
|
109
|
+
string = self.to_string_short
|
110
|
+
string << ';title=' + @title.inspect if @title
|
111
|
+
string
|
112
|
+
end
|
113
|
+
|
48
114
|
# @return [String] text representation
|
49
115
|
def to_text
|
50
|
-
|
51
|
-
text << ';title=' + @title.inspect if @title
|
52
|
-
text
|
116
|
+
'Category: ' + self.to_string
|
53
117
|
end
|
54
118
|
|
119
|
+
# @return [Hash] hash containing the HTTP headers of the text/occi rendering
|
55
120
|
def to_header
|
56
|
-
|
57
|
-
header[:Category] = self.to_text
|
121
|
+
{ :Category => self.to_string }
|
58
122
|
end
|
59
123
|
|
124
|
+
# @return [String] json representation
|
60
125
|
def inspect
|
61
126
|
JSON.pretty_generate(JSON.parse(to_json))
|
62
127
|
end
|
63
128
|
|
129
|
+
# @return [NilClass] category itself does not have a location
|
130
|
+
def location
|
131
|
+
nil # not implemented
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_s
|
135
|
+
self.type_identifier
|
136
|
+
end
|
137
|
+
|
64
138
|
end
|
65
139
|
end
|
66
|
-
end
|
140
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Occi
|
2
|
+
module Core
|
3
|
+
class Entities < Set
|
4
|
+
|
5
|
+
attr_accessor :model
|
6
|
+
|
7
|
+
def initialize(entities=[])
|
8
|
+
entities.to_a.each { |entity| entity.model = @model } if @model
|
9
|
+
super entities
|
10
|
+
end
|
11
|
+
|
12
|
+
def join(separator)
|
13
|
+
self.to_a.join(separator)
|
14
|
+
end
|
15
|
+
|
16
|
+
def model=(model)
|
17
|
+
@model = model
|
18
|
+
each { |entity| entity.model=model }
|
19
|
+
end
|
20
|
+
|
21
|
+
def check
|
22
|
+
each { |entity| entity.check }
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(*args)
|
26
|
+
entity = Occi::Core::Entity.new(*args)
|
27
|
+
entity.model = @model if @model
|
28
|
+
self << entity
|
29
|
+
entity
|
30
|
+
end
|
31
|
+
|
32
|
+
def <<(entity)
|
33
|
+
entity.model = @model if @model
|
34
|
+
super entity
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [Hash] options
|
38
|
+
# @return [Hashie::Mash] json representation
|
39
|
+
def as_json(options={ })
|
40
|
+
self.to_a.as_json
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [String] json representation
|
44
|
+
def inspect
|
45
|
+
JSON.pretty_generate(JSON.parse(to_json))
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|