active-orient 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e808c07b0d7ea4b6ab44772dcfbed8521f1dbe1b
4
+ data.tar.gz: d1dc78cd6f6b0b5b8da14512e54e39777479b31c
5
+ SHA512:
6
+ metadata.gz: da1131e98ac909ba6e77526f52a6c9ae608eabe9d9a0d5d3dc2bb2a702fb7454493a2de516746e00f2d6f1f60c1bb4191393f49a28da470a3f3e87c763b624cb
7
+ data.tar.gz: 883ea6e68bfe1fc3a88dc4b7d9173a1a454c6141d6dfb234286aab3de1677666a0a115a022acd36049ed9cbf490abfd153287a547c67dddb9115671daf4bf9a8
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+ gem 'activesupport' , "~>4.2"
4
+ gem 'activemodel'
5
+ gem 'rest-client', :git => 'git://github.com/rest-client/rest-client.git'
6
+ group :development, :test do
7
+ gem "rspec"
8
+ gem 'rspec-its'
9
+ gem 'rspec-collection_matchers'
10
+ gem 'rspec-context-private'
11
+ gem 'guard'
12
+ gem 'guard-rspec'
13
+ ## gem 'database_cleaner'
14
+ gem 'rb-inotify'
15
+ gem 'pry'
16
+ end
@@ -0,0 +1,21 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, cmd: "bundle exec rspec" do
5
+ require "ostruct"
6
+
7
+ # Generic Ruby apps
8
+ rspec = OpenStruct.new
9
+ rspec.spec = ->(m) { "spec/#{m}_spec.rb" }
10
+ rspec.spec_dir = "spec"
11
+ rspec.spec_helper = "spec/spec_helper.rb"
12
+
13
+
14
+ watch(%r{^spec/.+_spec\.rb$})
15
+ watch(%r{^spec/usecase/(.+).rb$})
16
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
17
+ watch('spec/spec_helper.rb') { "spec" }
18
+
19
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
20
+ end
21
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 topofocus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,275 @@
1
+ # ActiveOrient
2
+ Use OrientDB to persistently store dynamic Ruby-Objects and use database queries to manage even very large
3
+ datasets.
4
+
5
+ The Package ist tested with Ruby 2.2.1 and Orientdb 2.1.
6
+
7
+
8
+ To start you need a ruby 2.x Installation and a working OrientDB-Instance.
9
+ Clone the project and run bundle install/ bundle update,
10
+ then modify »config/connect.yml«.
11
+ Its adviserable to generate the rdoc-documentation with executing
12
+ ```
13
+ rdoc
14
+ ```
15
+ from the source directory of AcitiveOrient and then to load the doc-directory into any browser.
16
+
17
+ For a quick start, go to the home directory of the package and start an irb-session
18
+
19
+ then
20
+
21
+ ```ruby
22
+ require './config/boot'
23
+ r = ActiveOrient::OrientDB.new database: 'First'
24
+ => #<ActiveOrient::OrientDB:0x000000048d0488 @res=#<RestClient::Resource:0x00000004927288
25
+ @url="http://localhost:2480", @block=nil,
26
+ @options={:user=>"xx", :password=>"***"}>, @database="First", @classes=[]>
27
+ ```
28
+
29
+ »r« is the Database-Instance itself. Obviously the database is empty.
30
+
31
+
32
+ Let's create some classes
33
+
34
+ ```ruby
35
+ M = r.open_class 'classname' #
36
+ M = r.create_class 'classname' # creates or opens a basic document-class
37
+ M = r.create_vertex_class 'classname' # creates or opens a vertex-class
38
+ M = r.create_edge_class 'classname' # creates or opens an edge-class, providing bidirectional links between documents
39
+
40
+ r.delete_class M # universal removal-of-the-class-method
41
+ ```
42
+
43
+
44
+ »M« is the ActiveOrient::Model-Class itself, a constant pointing to the class-definition of the ruby-class.
45
+ Its a shortcut for »ActiveOrient::Model::{Classname} and is reused if defined elsewhere.
46
+
47
+ If a schema is used, properties can be created and retrieved as well
48
+ ```ruby
49
+ r.create_properties( M ) do
50
+ { symbol: { propertyType: 'STRING' },
51
+ con_id: { propertyType: 'INTEGER' },
52
+ details: { propertyType: 'LINK', linkedClass: 'Contracts' }
53
+ }
54
+
55
+ r.get_class_properties M
56
+ ```
57
+ or
58
+ ```ruby
59
+ M.create_property 'symbol'
60
+ M.create_property 'con_id', type: 'integer'
61
+ M.create_property 'details', type: 'link', other_class: 'Contracts'
62
+ ```
63
+
64
+ #### Active Model interface
65
+
66
+ Every OrientDB-Database-Class is mirrord as Ruby-Class. The Class itself is defined by
67
+ ```ruby
68
+ M = r.create_class 'classname'
69
+ M = r.create_class { superclass_name: 'classname' }
70
+ Vertex = r.create_vertex_class 'classname'
71
+ Edge = r.create_edge_class 'classname'
72
+ ```
73
+ and is of TYPE ActiveOrient::Model::{classname}
74
+
75
+ As for ActiveRecord-Tables, the Class itself provides methods to inspect and to filter datasets form the database.
76
+
77
+ ```ruby
78
+ M.all
79
+ M.first
80
+ M.last
81
+ ```
82
+ returns an Array containing all Documents/Edges of the Class; the first and the last Record.
83
+ ```ruby
84
+ M.where town: 'Berlin'
85
+ ```
86
+ performs a query on the class and returns the result as Array
87
+
88
+ ```ruby
89
+ M.count where: { town: 'Berlin' }
90
+ ```
91
+ gets the number of datasets fullfilling the search-criteria. Any parameter defining a valid
92
+ SQL-Query in Orientdb can be provided to the count, where, first and last-method.
93
+
94
+ A »normal« Query is submitted via
95
+ ```ruby
96
+ M.get_documents projection: { projection-parameter }
97
+ distinct: { some parameters }
98
+ where: { where-parameter }
99
+ order: { sorting-parameters }
100
+ group_by: { one grouping-parameter}
101
+ unwind:
102
+ skip:
103
+ limit:
104
+
105
+ # or
106
+ query = OrientSupport::OrientQuery.new {paramter}
107
+ M.get_documents query: query
108
+
109
+ ```
110
+
111
+ Basic graph-support:
112
+
113
+
114
+
115
+ ```ruby
116
+ vertex_1 = Vertex.create color: "blue"
117
+ vertex_2 = Vertex.create flower: "rose"
118
+ Edge.create_edge attributes: { :birthday => Date.today }, from: vertex_1, to: vertex_2
119
+ ```
120
+ connects the vertices and assigns the attributes to the edge
121
+
122
+
123
+ #### Links
124
+
125
+ A record in a database-class is defined by a »rid«. Every Model-Object comes with a handy »link«-method.
126
+
127
+ In OrientDB links are used to realise unidirectional 1:1 and 1:n relationships.
128
+
129
+ ActiveOrient autoloads Model-objects when they are accessed. As a consequence,
130
+ if an Object is stored in Cluster 30 and id 2, then "#30:2" fully qualifies the ActiveOrient::Model object.
131
+
132
+ ```ruby
133
+ TestLinks = r.create_class 'Test_link_class'
134
+ TestBase = r.create_class 'Test_base_class'
135
+
136
+ link_document = TestLinks.create att: 'one attribute'
137
+ base_document = TestBase.create base: 'my_base', single_link: link_document
138
+ ```
139
+ base_document.single_link just contains the rid. When accessed, the ActiveOrient::Model::Testlinkclass-object is autoloaded and
140
+ ``` ruby
141
+ base_document.single_link.att
142
+ ```
143
+ reads the stored content of link_document.
144
+
145
+ To store a list of links to other Database-Objects a simple Array is allocated
146
+ ``` ruby
147
+ # predefined linkmap-properties
148
+ base_document = TestBase.create links: []
149
+ ( 0 .. 20 ).each{ |y| base_document.links << TestLinks.create nr: y }
150
+ end
151
+ #or in schemaless-mode
152
+ base_document = TestBase.create links: (0..20).map{|y| TestLinks.create nr: y }
153
+
154
+
155
+ ```
156
+ base_document.links behaves like a ruby-array.
157
+
158
+ If you got an undirectional graph
159
+
160
+ a --> b ---> c --> d
161
+
162
+ the graphelements can be explored by joining the objects ( a.b.c.d ), or (a.b[5].c[9].d )
163
+
164
+ #### Edges
165
+
166
+ Edges are easily handled
167
+ ```ruby
168
+ Vertex = r.create_vertex_class 'd1'
169
+ Eedge = r.create_edge_class 'e1'
170
+
171
+ start = Vertex.create something: 'nice'
172
+ the_end = Vertex.create something: 'not_nice'
173
+ the_edge = Edge.create_edge attributes: { transform_to: 'very bad' },
174
+ from: start,
175
+ to: the_end
176
+
177
+ (...)
178
+ the_edge.delete
179
+ ```
180
+
181
+ There is a basic support for traversals throught a graph.
182
+ The Edges are accessed by their names (downcase).
183
+
184
+ ```ruby
185
+ start.e1[0]
186
+ --> #<ActiveOrient::Model::E1:0x000000041e4e30
187
+ @metadata={"type"=>"d", "class"=>"E1", "version"=>60, "fieldTypes"=>"out=x,in=x",
188
+ "cluster"=>16, "record"=>43},
189
+ @attributes={"out"=>"#31:23", "in"=>"#31:15", "transform_to"=>"very bad" }>
190
+ ```
191
+ The Attributes "in" and "out" can be used to move across the graph
192
+ ```ruby
193
+ start.e1[0].out.something
194
+ ---> "not_nice
195
+ start.e1[0].in.something
196
+ ---> "nice
197
+ ```
198
+
199
+ #### Execute SQL-Commands
200
+ At least - sql-commands can be executed as batch
201
+
202
+ The ActiveOrient::Query-Class provides a Query-Stack and an Records-Array which keeps the results.
203
+ The ActiveOrient::Query-Class acts as Parent-Class for aggregated Records (without a @rid), which are ActiveOrient::Model::Myquery Objects. If a Query returns a database-record, the correct ActiveOrient::Model-Class is instantiated.
204
+
205
+ ```ruby
206
+ ach = ActiveOrient::Query.new
207
+
208
+ ach.queries << 'create class Contracts ABSTRACT'
209
+ ach.queries << 'create property Contracts.subcategory link'
210
+ ach.queries << 'create property Contracts.details link'
211
+ ach.queries << 'create class Stocks extends Contracts'
212
+ ach.queries << 'create class Futures extends Contracts'
213
+ result = ach.execute_queries transaction: false
214
+
215
+
216
+
217
+ ```
218
+ queries the database as demonstrated above. In addition, the generated query itself is added to the »queries«-Stack and the result can be found in sample_query.records.
219
+
220
+ This feature can be used as a substitute for simple functions
221
+
222
+ ```ruby
223
+ roq = ActiveOrient::Query.new
224
+ roq.queries =["select name, categories.subcategories.contracts from Industries where name containstext …'ial'"]
225
+ roq.execute_queries.each{|x| puts x.name, x.categories.inspect }
226
+ --> Basic Materials [["#21:1"]]
227
+ --> Financial [["#21:2"]]
228
+ --> Industrial [["#23:0", "#23:1"]]
229
+ ```
230
+
231
+ OrientDB supports the execution of SQL-Batch-Commands.
232
+ ( http://orientdb.com/docs/2.0/orientdb.wiki/SQL-batch.html )
233
+ This is supported simply by using a Array as Argument for ActiveOrient::Query.queries
234
+
235
+ Therefor complex queries can be simplified using database-variables
236
+ ```ruby
237
+ ach = ActiveOrient::Query.new
238
+ ach.queries << [ "select expand( contracts ) from Openinterest"
239
+ "let con = select expand( contracts ) from Openinterest; ",
240
+ "...", ... ]
241
+ result = ach.execute_queries
242
+ ```
243
+
244
+ The contract-documents are accessible with
245
+ ```ruby
246
+ r.get_document '21:1'
247
+ --><Stocks: con_id: 77680640 currency: EUR details: #18:1 exchange: SMART local_symbol: BAS
248
+ primary_exchange: IBIS subcategory: #14:1 symbol: BAS>
249
+ ```
250
+ or
251
+ ```ruby
252
+ my_query = ActiveOrient::Query.new
253
+ ['Contracts', 'Industries', 'Categories', 'Subcategories'].each do |table|
254
+ my_query.queries = [ "select count(*) from #{table}"]
255
+
256
+ count = my_query.execute_queries
257
+ # count=> [#<ActiveOrient::Model::Myquery:0x00000003b317c8
258
+ # @metadata={"type"=>"d", "class"=>nil, "version"=>0, "fieldTypes"=>"count=l"},
259
+ # @attributes={"count"=>4 } ] --> an Array with one Element, therefor count.pop
260
+ puts "Table #{table} \t #{count.pop.count} Datasets "
261
+ end
262
+ -->Table Contracts 56 Datasets
263
+ -->Table Industries 8 Datasets
264
+ -->Table Categories 22 Datasets
265
+ -->Table Subcategories 35 Datasets
266
+
267
+ ```
268
+
269
+ Note that the fetched Object is of type »Stocks« (ActiveOrient::Model::Stocks).
270
+
271
+ The ActiveOrient-API documentation can be found here: https://github.com/orientechnologies/orientdb-docs/wiki/OrientDB-ActiveOrient
272
+ and the ActiveModel-documentation is here: http://www.rubydoc.info/gems/activemodel
273
+
274
+
275
+
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "active-orient"
6
+ s.version = File.open('VERSION').read.strip
7
+ s.authors = [" Hartmut Bischoff"]
8
+ s.email = ["topofocus@gmail.com"]
9
+ s.homepage = 'https://github.com/topofocus/active-orient'
10
+ s.licenses = ['MIT']
11
+ s.summary = 'Pure ruby client for OrientDB based on ActiveModel'
12
+ s.description = 'Persistent ORM for OrientDB, based on ActiveModel'
13
+ s.platform = Gem::Platform::RUBY
14
+ s.required_ruby_version = '>= 2.2.0'
15
+ s.date = Time.now.strftime "%Y-%m-%d"
16
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
17
+ s.require_paths = ["lib"]
18
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ s.bindir = "exe"
20
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+
22
+ s.add_development_dependency "bundler", "~> 1.8"
23
+ s.add_development_dependency "rake", "~> 10.0"
24
+ s.add_dependency 'activesupport'
25
+ # s.add_dependency 'rest-client', :git => 'git://github.com/rest-client/rest-client.git'
26
+
27
+ end
@@ -0,0 +1,24 @@
1
+ require 'bundler/setup'
2
+ require 'yaml'
3
+ project_root = File.expand_path('../..', __FILE__)
4
+ require "#{project_root}/lib/support.rb"
5
+ require "#{project_root}/lib/base.rb"
6
+ require "#{project_root}/lib/base_properties.rb"
7
+
8
+ require "#{project_root}/lib/model.rb"
9
+ require "#{project_root}/lib/orient.rb"
10
+ require "#{project_root}/lib/rest.rb"
11
+ #require "#{project_root}/lib/graph.rb"
12
+
13
+ # require all the models and libraries
14
+ libs= Dir.glob(File.join( project_root, "lib",'**', "*rb"))
15
+ result = libs.reverse.collect { |file| [file, require( file )] }
16
+
17
+ logger = Logger.new '/dev/stdout'
18
+ #REST::Graph.logger = logger
19
+ ActiveOrient::Model.logger = logger
20
+ ActiveOrient::OrientDB.logger = logger
21
+
22
+
23
+
24
+
@@ -0,0 +1,13 @@
1
+ ---
2
+ :orientdb:
3
+ :server: localhost
4
+ :port: 2480
5
+ :database: hc_database
6
+ :admin:
7
+ :user: hctw
8
+ :pass: hc
9
+ :auth:
10
+ :user: topo
11
+ :pass: focus
12
+
13
+ # hfx: 101
@@ -0,0 +1,220 @@
1
+ module ActiveOrient
2
+ require 'active_model'
3
+ #
4
+ # Base class for tableless IB data Models, extends ActiveModel API
5
+ class Base
6
+ extend ActiveModel::Naming
7
+ extend ActiveModel::Callbacks
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Serialization
10
+ include ActiveModel::Serializers::Xml
11
+ include ActiveModel::Serializers::JSON
12
+
13
+
14
+ ##Every Rest::Base-Object is stored in the @@rid_store
15
+ ## The Objects are just references to the @@rid_store.
16
+ ## any Change of the Object is thus synchonized to any allocated variable
17
+ #
18
+ @@rid_store = Hash.new
19
+
20
+ def self.display_riid
21
+ @@rid_store
22
+ end
23
+ def self.remove_riid obj
24
+ @@rid_store[obj.riid]=nil
25
+ end
26
+ def self.get_riid link
27
+
28
+ end
29
+ def self.store_riid obj
30
+ if obj.rid.present? && obj.riid.all?{|x| x.present? && x>=0} # only positive values are stored
31
+ ## return the presence of a stored object as true by the block
32
+ ## the block is only executed if the presence is confirmed
33
+ ## Nothing is returned from the class-method
34
+ if @@rid_store[obj.riid].present?
35
+ yield if block_given?
36
+ end
37
+ @@rid_store[obj.riid] = obj
38
+ @@rid_store[obj.riid] # return_value
39
+ else
40
+ obj # no rid-value: just return the obj
41
+ end
42
+ end
43
+
44
+
45
+ define_model_callbacks :initialize
46
+
47
+ mattr_accessor :logger
48
+ # If a opts hash is given, keys are taken as attribute names, values as data.
49
+ # The model instance fields are then set automatically from the opts Hash.
50
+ def initialize attributes={}, opts={}
51
+ logger.progname= "ActiveOrient::Base#initialize"
52
+ #possible_link_array_candidates = link_candidates = Hash.new
53
+ @metadata = HashWithIndifferentAccess.new
54
+ # @edges = HashWithIndifferentAccess.new
55
+
56
+ run_callbacks :initialize do
57
+ # puts "initialize::attributes: #{attributes.inspect}"
58
+
59
+ attributes.keys.each do | att |
60
+ unless att[0] == "@" # @ identifies Metadata-attributes
61
+ att = att.to_sym if att.is_a?(String)
62
+ unless self.class.instance_methods.detect{|x| x == att }
63
+ self.class.define_property att, nil
64
+ # logger.debug { "property #{att.to_s} assigned to #{self.class.to_s}" }
65
+ else
66
+ # logger.info{ "property #{att.to_s} NOT assigned " }
67
+ end
68
+ end
69
+ end
70
+
71
+ if attributes['@type'] == 'd' # document
72
+ @metadata[ :type ] = attributes.delete '@type'
73
+ @metadata[ :class ] = attributes.delete '@class'
74
+ @metadata[ :version ] = attributes.delete '@version'
75
+ @metadata[ :fieldTypes ] = attributes.delete '@fieldTypes'
76
+ if attributes.has_key?( '@rid' )
77
+ rid = attributes.delete '@rid'
78
+ cluster, record = rid[1,rid.size].split(':')
79
+ @metadata[ :cluster ] = cluster.to_i
80
+ @metadata[ :record ] = record.to_i
81
+ end
82
+
83
+ #### edges -- remove in_ and out_ and de-capitalize the remaining edge
84
+ if @metadata[ :fieldTypes ].present? && (@metadata[ :fieldTypes ] =~ /=g/)
85
+ edges = @metadata['fieldTypes'].split(',').find_all{|x| x=~/=g/}.map{|x| x.split('=').first}
86
+ edges.each do |edge|
87
+ operator, *base_edge = edge.split('_')
88
+ base_edge = base_edge.join('_')
89
+ unless self.class.instance_methods.detect{|x| x == base_edge }
90
+ ## define two methods: out_{Edge}/{in_Edge} -> edge.
91
+ self.class.define_property base_edge, nil
92
+ self.class.send :alias_method, base_edge.underscore, edge #
93
+ # logger.debug { "#{link}:: edge #{edge} assigned to #{self.class.to_s} and remaped to #{base_edge.underscore}" }
94
+
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+
101
+ self.attributes = attributes # set_attribute_defaults is now after_init callback
102
+ end
103
+ ActiveOrient::Base.store_riid self
104
+ end
105
+
106
+ # ActiveModel API (for serialization)
107
+
108
+ def attributes
109
+ @attributes ||= HashWithIndifferentAccess.new
110
+ end
111
+
112
+ def attributes= attrs
113
+ attrs.keys.each { |key| self.send("#{key}=", attrs[key]) }
114
+ end
115
+
116
+ # ActiveModel-style read/write_attribute accessors
117
+ # Here we define the autoload mechanism
118
+ def [] key
119
+
120
+ iv= attributes[key.to_sym]
121
+ # iv.from_orient unless iv.nil?
122
+ if iv.is_a?(String) && iv.rid? #&& @metadata[:fieldTypes].present? && @metadata[:fieldTypes].include?( key.to_s+"=x" )
123
+ # puts "autoload: #{iv}"
124
+ ActiveOrient::Model.autoload_object iv
125
+ elsif iv.is_a?(Array) # && @metadata[:fieldTypes].present? && @metadata[:fieldTypes].match( key.to_s+"=[znmgx]" )
126
+ # puts "autoload: #{iv.inspect}"
127
+ OrientSupport::Array.new self, *iv.map{|y| (y.is_a?(String) && y.rid?) ? ActiveOrient::Model.autoload_object( y ) : y }
128
+ else
129
+
130
+ iv
131
+ end
132
+ end
133
+
134
+ def update_attribute key, value
135
+ @attributes[key] = value
136
+ end
137
+ =begin
138
+ Here we define how the attributes are initialized
139
+ Key and val are set by the RestCliend
140
+ =end
141
+ def []= key, val
142
+ val = val.rid if val.is_a? ActiveOrient::Model
143
+ # if val.is_a?(Array) # && @metadata[:fieldTypes].present? && @metadata[:fieldTypes].include?( key.to_s+"=n" )
144
+ # if @metadata[ :fieldTypes ] =~ /out=x,in=x/
145
+ # puts "VAL is a ARRAY"
146
+ # else
147
+ # puts "METADATA: #{ @metadata[ :fieldTypes ]} "
148
+ # end
149
+ # val# = val.map{|x| if val.is_a? ActiveOrient::Model then val.rid else val end }
150
+ # end
151
+ attributes[key.to_sym] = case val
152
+ when Array
153
+ if val.first.is_a?(Hash)
154
+ v=val.map do |x|
155
+ if x.is_a?( Hash )
156
+ HashWithIndifferentAccess.new(x)
157
+ else
158
+ x
159
+ end
160
+ end
161
+ OrientSupport::Array.new( self, *v )
162
+ else
163
+ OrientSupport::Array.new( self, *val )
164
+ end
165
+ when Hash
166
+ HashWithIndifferentAccess.new(val)
167
+ else
168
+ val
169
+ end
170
+
171
+ end
172
+
173
+ def to_model
174
+ self
175
+ end
176
+
177
+
178
+
179
+ ### Noop methods mocking ActiveRecord::Base macros
180
+
181
+ def self.attr_protected *args
182
+ end
183
+
184
+ def self.attr_accessible *args
185
+ end
186
+
187
+ ### ActiveRecord::Base association API mocks
188
+
189
+ def self.belongs_to model, *args
190
+ attr_accessor model
191
+ end
192
+
193
+ def self.has_one model, *args
194
+ attr_accessor model
195
+ end
196
+
197
+ def self.has_many models, *args
198
+ attr_accessor models
199
+
200
+ define_method(models) do
201
+ self.instance_variable_get("@#{models}") ||
202
+ self.instance_variable_set("@#{models}", [])
203
+ end
204
+ end
205
+
206
+ def self.find *args
207
+ []
208
+ end
209
+
210
+ ### ActiveRecord::Base callback API mocks
211
+
212
+ define_model_callbacks :initialize, :only => :after
213
+
214
+ ### ActiveRecord::Base misc
215
+
216
+ def self.serialize *properties
217
+ end
218
+
219
+ end # Model
220
+ end # module