active-orient 0.5 → 0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -2
  3. data/README.md +78 -35
  4. data/VERSION +1 -1
  5. data/active-orient.gemspec +4 -4
  6. data/bin/active-orient-console +8 -5
  7. data/config/boot.rb +2 -4
  8. data/config/config.yml +1 -1
  9. data/config/connect.yml +2 -2
  10. data/examples/time_graph.md +162 -0
  11. data/gratefuldeadconcerts.md +94 -0
  12. data/lib/active-orient.rb +4 -2
  13. data/lib/base.rb +53 -20
  14. data/lib/base_properties.rb +2 -3
  15. data/lib/class_utils.rb +3 -4
  16. data/lib/database_utils.rb +14 -5
  17. data/lib/init.rb +11 -1
  18. data/lib/model/edge.rb +12 -10
  19. data/lib/model/model.rb +17 -3
  20. data/lib/model/the_class.rb +60 -40
  21. data/lib/model/the_record.rb +63 -51
  22. data/lib/model/vertex.rb +114 -10
  23. data/lib/orient.rb +24 -33
  24. data/lib/orientdb_private.rb +31 -31
  25. data/lib/other.rb +55 -5
  26. data/lib/rest/change.rb +17 -4
  27. data/lib/rest/create.rb +38 -24
  28. data/lib/rest/delete.rb +3 -2
  29. data/lib/rest/operations.rb +37 -27
  30. data/lib/rest/read.rb +2 -2
  31. data/lib/rest/rest.rb +4 -3
  32. data/lib/support.rb +17 -16
  33. data/linkmap.md +75 -0
  34. data/namespace.md +111 -0
  35. data/rails.md +125 -0
  36. data/rails/activeorient.rb +53 -0
  37. data/{examples/time_graph/config → rails}/config.yml +3 -1
  38. data/{examples/time_graph/config → rails}/connect.yml +2 -2
  39. data/usecase_oo.md +3 -1
  40. metadata +21 -38
  41. data/examples/createTime.rb +0 -91
  42. data/examples/time_graph/Gemfile +0 -21
  43. data/examples/time_graph/Guardfile +0 -26
  44. data/examples/time_graph/README.md +0 -129
  45. data/examples/time_graph/bin/active-orient-console +0 -35
  46. data/examples/time_graph/config/boot.rb +0 -119
  47. data/examples/time_graph/config/init_db.rb +0 -59
  48. data/examples/time_graph/createTime.rb +0 -51
  49. data/examples/time_graph/lib/createTime.rb +0 -82
  50. data/examples/time_graph/model/day_of.rb +0 -3
  51. data/examples/time_graph/model/e.rb +0 -6
  52. data/examples/time_graph/model/edge.rb +0 -53
  53. data/examples/time_graph/model/monat.rb +0 -19
  54. data/examples/time_graph/model/stunde.rb +0 -16
  55. data/examples/time_graph/model/tag.rb +0 -29
  56. data/examples/time_graph/model/time_base.rb +0 -6
  57. data/examples/time_graph/model/time_of.rb +0 -4
  58. data/examples/time_graph/model/v.rb +0 -3
  59. data/examples/time_graph/model/vertex.rb +0 -32
  60. data/examples/time_graph/spec/lib/create_time_spec.rb +0 -50
  61. data/examples/time_graph/spec/rest_helper.rb +0 -37
  62. data/examples/time_graph/spec/spec_helper.rb +0 -46
  63. data/usecase.md +0 -104
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5968de1064555bed8ecadc417fbad4f4af9c78d1
4
- data.tar.gz: 3f06f99417522ab20a776412f5b2eca1295664f2
3
+ metadata.gz: 1c3fb207d23e5c1cd30e95105075370967fb4a6b
4
+ data.tar.gz: 6f606ff9a666368ddcaa51dd0e3ca7f7edf3bfa2
5
5
  SHA512:
6
- metadata.gz: 05ae6ba2fd2e933661e6f36fc1db77bef5ecd944b90f490c4d8d49d737b97aaf82ac61c0bcdff4055ac393fde2fe70e54228a30afdbef28d61134f0081f84779
7
- data.tar.gz: 854f1efe44dd9a4056b5a37d882ed887487f7b7d734447c5d289648b118444e126352da92d2bf74935ce304f4eeecc92faed329f80a54fb85fbdb0a2b0f394ef
6
+ metadata.gz: 371a9c4ad68cad3f4efc701c3965e1f946bce6f610b4ea7245f3f168a6417185dc7829395387a07f97e55f92c02829a7e72999f824ffffff92e99f17090e1113
7
+ data.tar.gz: 2f4c7e0a6a74a34c5f605ae6b9ee094eb4c2ff51827c1beb5d77be04caceba6c7ed2149edd093be0ee9b9004afa6bdc4fdc203d4c1e5122d648c7b87aebfb961
data/Gemfile CHANGED
@@ -1,7 +1,8 @@
1
1
  source "https://rubygems.org"
2
2
  gemspec
3
- gem 'activesupport' , "~>4.2"
4
- gem 'activemodel', "~>4.2"
3
+ gem 'activesupport' # , "~>4.2"
4
+ gem 'activemodel' #, "~>4.2"
5
+ #gem 'activemodel-serializers-xml'
5
6
  gem 'rest-client' , :git => 'git://github.com/rest-client/rest-client.git'
6
7
  gem 'nokogiri', '~> 1.6.6' #, :git => 'git://github.com/sparklemotion/nokogiri.git'
7
8
  gem 'orientdb' , :path => '/home/topo/orientdb-jruby' , :platforms => :jruby
data/README.md CHANGED
@@ -2,17 +2,33 @@
2
2
  Use OrientDB to persistently store dynamic Ruby-Objects and use database queries to manage even very large
3
3
  datasets.
4
4
 
5
- You need a ruby 2.3 or a jruby 9.1x Installation and a working OrientDB-Instance (Version 2.2 prefered).
5
+ #### Other Documents
6
+ - [Experiments with Joins / Linkmaps ](./linkmap.md)
7
+
8
+ - [Experiments with the GratefulDeadConcerts Sample Database](./gratefuldeadconcerts.md)
9
+
10
+ - [Namespace Support](./namespace.md)
11
+
12
+ - [TimeGraph Implementation](examples/time_graph.md)
13
+
14
+ - [Rails 5-Integration](./rails.md)
15
+
16
+ You need a ruby 2.3, 2.4 or a jruby 9.1x Installation and a working OrientDB-Instance (Version 2.2 prefered).
6
17
  The jruby-part is experimental.
7
18
 
8
- For a quick start, clone the project, run bundle install & bundle update, update config/connect.yml, create the documentation by calling »rdoc«
9
- and start an irb-session:
19
+ ### Quick Start
20
+
21
+ - clone the project,
22
+ - run bundle install & bundle update,
23
+ - update config/connect.yml,
24
+ - create the documentation by calling »rdoc«
25
+ - start an irb-session by calling
10
26
  ```
11
27
  cd bin
12
28
  ./active-orient-console test # or d)develpoment, p)roduction environment as defined in config/connect.yml
13
29
  ```
14
30
 
15
- »ORD« is the Database-Instance itself. If the Database noticed is not present, it is created on startup.
31
+ «ORD» or «DB» is the Database-Instance itself. If the Database noticed is not present, it is created on startup.
16
32
  A simple SQL-Query is submitted by providing a Block to »execute«
17
33
  ```ruby
18
34
  result = ORD.execute { "select * from Stock" }
@@ -71,9 +87,10 @@ All database-classes are preallocated after connecting to the database. Thus you
71
87
 
72
88
  If the "rid" is known, any Object can be retrieved and correctly allocated by
73
89
  ```ruby
74
- the_object = ActiveOrient::Model.autoload_object "xx:yy" # or "#xx:yy"
90
+  the_object = V.autoload_object "xx:yy" # or "#xx:yy"
75
91
  ---> {ActiveOrient::Model} Object
76
92
  ```
93
+ The database-class «V» is present in any case. Any model-class can be used, even the parent »ActiveOrient::Model«
77
94
 
78
95
  #### Properties
79
96
  The schemaless mode has many limitations. ActiveOrient offers a Ruby way to define Properties and Indexes
@@ -126,6 +143,12 @@ A »normal« Query is submitted via
126
143
 
127
144
  ```
128
145
 
146
+ To update several records, a class-method »update_all« is defined.
147
+ ```ruby
148
+ M.update_all connected: false # add a property »connected» to each record
149
+ M.update_all set:{ connected: true }, where: "symbol containsText 'S'"
150
+ ```
151
+
129
152
  Graph-support:
130
153
 
131
154
  ```ruby
@@ -195,10 +218,32 @@ Edges provide bidirectional Links. They are easily handled
195
218
  the_edge = TheEdge.create attributes: {transform_to: 'very bad'},
196
219
  from: start,
197
220
  to: the_end
221
+ ```
222
+ Edges are connected to vertices by »in« and »out«-Methods.
223
+ Inherence is supported.
224
+
225
+ i.e.
226
+ ```ruby
227
+ ORD.create_class( top_edge ) { THE_EDGE }
228
+ ORD.create_class( on_top_edge ) { TOP_EDGE }
229
+
230
+ ON_TOP_Edge.create from: start, to: the_end
231
+ start.reload!
232
+ start.out :the_edge
233
+ => [#<TOP_EDGE:0x00000001d92f28 @metadata= ... ]
234
+ ```
235
+
236
+ Edge-links are displayed and retrieved by
237
+ ```ruby
238
+ start.edges # :in | :out | :all
239
+ => ["#73:0"]
240
+
241
+ start.edges(:out).map &:from_orient
242
+ => [#<TOP_EDGE:0x00000001d92f28 @metadata= ... ]
198
243
 
199
- (...)
200
- the_edge.delete # To delete the edge
201
244
  ```
245
+
246
+
202
247
  The create-Method od Edge-Classes takes a block. Then all statements are transmitted in batch-mode.
203
248
  Assume, Vertex1 and Vertex2 are Vertex-Classes and TheEdge is an Edge-Class, then
204
249
  ```ruby
@@ -214,31 +259,6 @@ Assume, Vertex1 and Vertex2 are Vertex-Classes and TheEdge is an Edge-Class, the
214
259
  ```
215
260
  connects the vertices and provides a variable "key" and a common "study" attribute to each edge.
216
261
 
217
- There is a basic support for traversals through a graph.
218
- The Edges are accessed by their names (downcase).
219
- ```ruby
220
- start = TheVertex.where: {something: "nice"}
221
- start[0].e1[0]
222
- --> #<E1:0x000000041e4e30
223
- @metadata={"type"=>"d", "class"=>"E1", "version"=>60, "fieldTypes"=>"out=x,in=x", "cluster"=>16, "record"=>43},
224
- @attributes={"out"=>"#31:23", "in"=>"#31:15", "transform_to"=>"very bad" }>
225
- ```
226
-
227
- The Attributes "in" and "out" can be used to move across the graph
228
-
229
- ```ruby
230
- start[0].e1[0].out.something
231
- # ---> "not_nice"
232
- start[0].e1[0].in.something
233
- # ---> "nice"
234
- ```
235
-
236
- (Experimental) In alternative you can "humanize" your code in the following way:
237
-
238
- ```ruby
239
- Vertex.add_edge_link name: "ends", edge: TheEdge
240
- start.ends.something # <-- Similar output as start[0].e1[0].out.something
241
- ```
242
262
 
243
263
  #### Queries
244
264
 
@@ -312,15 +332,15 @@ this executes the query and returns the adressed rid's, which are eventually ret
312
332
  #### Match
313
333
 
314
334
  A Match-Query starts at the given ActiveOrient::Model-Class. The where-cause narrows the sample to certain
315
- records. In the simplest version this can be returnd:
335
+ records. In the simplest version this can be returned:
316
336
 
317
337
  ```ruby
318
338
  ORD.create_class :Industry
319
339
  Industry.match where:{ name: "Communications" }
320
- => #<ActiveOrient::Model::Query:0x00000004309608 @metadata={"type"=>"d", "class"=>nil, "version"=>0, "fieldTypes"=>"Industries=x"}, @attributes={"Industries"=>"#21:1", (...)}>
340
+ => #<Query:0x00000004309608 @metadata={"type"=>"d", "class"=>nil, "version"=>0, "fieldTypes"=>"Industries=x"}, @attributes={"Industries"=>"#21:1", (...)}>
321
341
  ```
322
342
 
323
- The attributes are the return-Values of the Match-Query. Unless otherwise noted, the pluralized Model-Classname is used as attribute in the result-set.
343
+ The attributes are the return-Values of the Match-Query. Unless otherwise noted, the pluralized Model-Classname is used as attribute in the result-set. *Note* that the Match statement returns a »Query«-record. Its up to the usere, to transform the attributes to Model-Objects. This is done by the »to_orient« directive, ie. »xx.Industries.to_orient «
324
344
 
325
345
  ```ruby
326
346
  Industry.match where name: "Communications"
@@ -343,3 +363,26 @@ accessed starting at Industry defining
343
363
  The result-set has two attributes: Industries and Subcategories, pointing to the filtered datasets.
344
364
 
345
365
  By using subsequent »connect« and »statement« method-calls even complex Match-Queries can be constructed.
366
+
367
+
368
+ #### Other Documents
369
+ - [Experiments with Joins / Linkmaps ](./linkmap.md)
370
+
371
+ - [Experiment with the GratefulDeadConcerts Sample Database](./gratefuldeadconcerts.md)
372
+
373
+ - [Namespace Support](./namespace.md)
374
+
375
+ - [TimeGraph Implementation](examples/time_graph.md)
376
+
377
+
378
+ deactivated behavior: to turn it on, some work on base.rb is required
379
+ ```
380
+ start.the_edge # --> Array of "TheEdge"-instances connected to the vertex
381
+ start.the_edge.where transform_to: 'good' # -> empty array
382
+ start.the_edge.where transform_to: 'very bad' #--> previously connectd edge
383
+ start.something # 'nice'
384
+ end.something # 'not_nice'
385
+ start.the_edge.where( transform_to: 'very bad').in.something # => ["not_nice"]
386
+ (...)
387
+ the_edge.delete # To delete the edge
388
+ ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5
1
+ 0.6
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.email = ["topofocus@gmail.com"]
9
9
  s.homepage = 'https://github.com/topofocus/active-orient'
10
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'
11
+ s.summary = 'Pure ruby client for OrientDB(V.2.2) based on ActiveModel'
12
+ s.description = 'Persistent ORM for OrientDB(V.2.2), based on ActiveModel. Rails 5 compatible'
13
13
  s.platform = Gem::Platform::RUBY
14
14
  s.required_ruby_version = '>= 2.2.5'
15
15
  s.date = Time.now.strftime "%Y-%m-%d"
@@ -21,8 +21,8 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_development_dependency "bundler", "~> 1.8"
23
23
  s.add_development_dependency "rake", "~> 10.0"
24
- s.add_dependency 'activesupport', "~> 4.2"
25
- s.add_dependency 'activemodel', "~> 4.2"
24
+ s.add_dependency 'activesupport'#, "~> 4.2"
25
+ s.add_dependency 'activemodel'#, "~> 4.2"
26
26
  s.add_dependency 'rest-client'
27
27
 
28
28
  end
@@ -7,14 +7,14 @@
7
7
  require 'logger'
8
8
  LogLevel = Logger::WARN
9
9
  require File.expand_path(File.dirname(__FILE__) + "/../config/boot")
10
-
10
+
11
11
  require 'orientdb' if RUBY_PLATFORM == 'java'
12
12
  require 'yaml'
13
13
 
14
14
  puts "ORD points to the REST-Instance, Database: #{ActiveOrient.database}"
15
15
  puts "DB is the API-Instance of the database, DB.db gets the DB-Api-base " if RUBY_PLATFORM == 'java'
16
16
 
17
- puts '-'* 35
17
+ puts '-'* 45
18
18
  ns= case ActiveOrient::Model.namespace
19
19
  when Object
20
20
  "No Prefix, just ClassName#CamelCase"
@@ -22,11 +22,14 @@ ns= case ActiveOrient::Model.namespace
22
22
  ActiveOrient::Model.namespace.to_s + "{ClassName.camelcase}"
23
23
  end
24
24
  puts "Namespace for model-classes : #{ns}"
25
- puts "Allocated Classes (Hierarchy) ( Modelclasses are Camelized ):"
26
- puts '-'* 35
25
+ puts "Present Classes (Hierarchy) "
27
26
 
28
27
  puts ORD.class_hierarchy.to_yaml
29
-
28
+ puts ""
29
+ puts "Active Classes -> ActiveOrient ClassName"
30
+ puts '-'* 45
31
+ puts ActiveOrient::Model.allocated_classes.map{|x,y| "#{"%15s"% x} -> #{y.to_s}" }.join("\n")
32
+ puts '-'* 45
30
33
 
31
34
  include OrientDB
32
35
 
@@ -5,8 +5,6 @@ if RUBY_VERSION == 'java'
5
5
  end
6
6
  project_root = File.expand_path('../..', __FILE__)
7
7
  require "#{project_root}/lib/active-orient.rb"
8
- # mixin for define_namespace
9
- include ActiveOrient::Init
10
8
  begin
11
9
  connect_file = File.expand_path('../../config/connect.yml', __FILE__)
12
10
  config_file = File.expand_path('../../config/config.yml', __FILE__)
@@ -31,9 +29,9 @@ env = if e =~ /^p/
31
29
  puts "Using #{env}-environment"
32
30
 
33
31
  ActiveOrient::Model.model_dir = "#{project_root}/#{ configyml.present? ? configyml[:model_dir] : "model" }"
34
-
32
+ ActiveOrient::Model.keep_models_without_file = true
35
33
  # lib/init.rb
36
- define_namespace yml: configyml, namespace: @namespace
34
+ ActiveOrient::Init.define_namespace yml: configyml, namespace: @namespace
37
35
 
38
36
 
39
37
  log_file = if config_file.present?
@@ -6,5 +6,5 @@
6
6
  :namespace: :object
7
7
  ## model_dir: Path to model-files relative to the root of the application
8
8
  ## ie. app/model or model
9
- :model_dir: 'model'
9
+ :model_dir: 'lib/model'
10
10
 
@@ -4,9 +4,9 @@
4
4
  :port: 2480
5
5
  :logger: stdout # 'file' or 'stdout'
6
6
  :database:
7
- :development: DEV
7
+ :development: GratefulDeadConcerts
8
8
  :production: hcn_data
9
- :test: tempera
9
+ :test: temp
10
10
  :admin:
11
11
  :user: hctw
12
12
  :pass: hc
@@ -0,0 +1,162 @@
1
+ The Time-Graph Example is outsourced and lives as a seperate gem.
2
+
3
+ https://github.com/topofocus/orientdb_time_graph
4
+
5
+ from the readme:
6
+
7
+ # Time Graph
8
+
9
+ Simple Time Graph using ActiveOrient/OrientDB.
10
+
11
+ *Prerequisites* :
12
+ * Install and setup OrientDB
13
+ * Run "Bundle install" and "Bundle update"
14
+ * customize config/connect.yml
15
+
16
+ **or** start a new project and include the gem in the usual manner.
17
+
18
+ To play around, start the console by
19
+ ```
20
+ cd bin
21
+ ./active-orient-console t # test-modus
22
+ ```
23
+ The Database is automatically initialized and the following hierarchy is build:
24
+
25
+ ```ruby
26
+ - E # ruby-class
27
+ - - month_of TG::MONTH_OF
28
+ - - day_of TG::DAY_OF
29
+ - - time_of TG::TIME_OF
30
+ - - grid_of TG::GRID_OF
31
+ - V
32
+ - - time_base TG::TimeBase
33
+ - - - jahr TG::Jahr
34
+ - - - monat TG::Monat
35
+ - - - stunde TG::Stunde
36
+ - - - tag TG::Tag
37
+ ```
38
+ This Graph is realized
39
+
40
+ ```ruby
41
+ Jahr -- [Month_of] -- Monat --[DAY_OF]-- Tag --[TIME_OF]-- Stunde
42
+ ```
43
+ and populated by calling
44
+
45
+ ```ruby
46
+ TG::TimeGraph.populate( a single year or a range ) # default: 1900 .. 2050
47
+ ```
48
+ If only one year is specified, a Monat--Tag--Stunde-Grid is build, otherwise a Jahr--Monat--Tag one.
49
+ You can check the Status by calling
50
+
51
+ ```ruby
52
+ TG::TimeGraph.populate 2000 -2003
53
+ TG.info
54
+ -------------- TIME GRAPH ------------------
55
+ Allocated Years :
56
+ 2000; 2001; 2002; 2003
57
+
58
+ ```
59
+ In the Model-directory, customized methods simplify the usage of the graph.
60
+
61
+ Some Examples:
62
+ Assuming, you build a standard day-based grid
63
+
64
+ ```ruby
65
+
66
+ include TG # we can omit the TG prefix
67
+
68
+ Jahr[2000] # --> returns a single object
69
+ => #<TG::Jahr:0x00000004ced160 @metadata={"type"=>"d", "class"=>"jahr", "version"=>13, "fieldTypes"=>"out_month_of=g", "cluster"=>34, "record"=>101}, @d=nil, @attributes={"value"=>2000, "out_month_of"=>["#53:1209", "#54:1209", "#55:1209", "#56:1209", "#53:1210", "#54:1210", "#55:1210", "#56:1210", "#53:1211", "#54:1211", "#55:1211", "#56:1211"], "created_at"=>Fri, 09 Sep 2016 10:14:30 +0200}>
70
+
71
+
72
+ Jahr[2000 .. 2005].value # returns an array
73
+ => [2003, 2000, 2004, 2001, 2005, 2002]
74
+
75
+ Jahr[2000 .. 2005].monat(5..7).value # returns the result of the month-attribute (or method)
76
+ => [[5, 6, 7], [5, 6, 7], [5, 6, 7], [5, 6, 7], [5, 6, 7], [5, 6, 7]]
77
+
78
+ Jahr[2000].monat(4, 7).tag(4, 15,24 ).datum # adresses methods or attributes of the specified day's
79
+ => [["4.4.2000", "15.4.2000", "24.4.2000"], ["4.7.2000", "15.7.2000", "24.7.2000"]]
80
+ ## unfortunatly »Jahr[2000 .. 2015].monat( 3,5 ).tag( 4 ..6 ).datum « does not fits now
81
+ ## instead »Jahr[2000..2015].map{|y| y.monat( 3,5 ).tag( 4 ..6 ).datum } « does the job.
82
+ ```
83
+
84
+ To filter datasets in that way, anything represented is queried from the database. In contrast to
85
+ a pure ruby implementation, this works for small and large grid's.
86
+
87
+ Obviously, you can do neat ruby-array playings, which are limited to the usual sizes.
88
+ For example. As »TAG[31]« returns an array, the elements can be treated with ruby flavour:
89
+
90
+ ```ruby
91
+
92
+ Tag[31][2..4].datum # display three months with 31 days
93
+ => ["31.10.1901", "31.1.1902", "31.5.1902"]
94
+
95
+ ```
96
+ First all Tag-Objects with the Value 31 are queried. This gives »Jan, Mar, May ..«. Then one can inspect the array, in this case by slicing a range.
97
+
98
+ Not surprisingly, the first occurence of the day is not the earliest date in the grid. Its just the first one,
99
+ fetched from the database.
100
+
101
+ ``` ruby
102
+ Tag[1][1].datum
103
+ => "1.5.1900" # Tag[1][0] correctly fetches "1.1.1900"
104
+ Tag[1].last.datum
105
+ => "1.11.2050"
106
+ ## however,
107
+ Jahr[2050].monat(12).tag(1) # exists:
108
+ => [["1.12.2050"]]
109
+ ```
110
+
111
+ ## Horizontal Connections
112
+
113
+ Besides the hierarchically TimeGraph »Jahr <-->Monat <--> Tag <--> Stunde« the Vertices are connected
114
+ horizontally via »grid_to«-Edges. This enables an easy access to the neighbours.
115
+
116
+ On the TG::TimeBase-Level a method »environment« is implemented, that gathers the adjacent vertices
117
+ via traverse.
118
+
119
+ ``` ruby
120
+ start = TG::Jahr[2000].monat(4).tag(7).first.first
121
+ start.environment(3).datum
122
+ => ["4.4.2000", "5.4.2000", "6.4.2000", "7.4.2000", "8.4.2000", "9.4.2000", "10.4.2000"]
123
+
124
+ 2.3.1 :003 > start.environment(3,4).datum
125
+ => ["4.4.2000", "5.4.2000", "6.4.2000", "7.4.2000", "8.4.2000", "9.4.2000", "10.4.2000", "11.4.2000"]
126
+
127
+ start.environment(0,3).datum
128
+ => ["7.4.2000", "8.4.2000", "9.4.2000", "10.4.2000"]
129
+ ```
130
+
131
+
132
+
133
+ ## Diary
134
+
135
+ lets create a simple diary
136
+
137
+ ```ruby
138
+ include TG
139
+ TimeiGraph.populate 2016
140
+ ORD.create_vertex_class :termin
141
+ => Termin
142
+ ORD.create_edge_class :date_of
143
+ => DATE_OF
144
+ DATE_OF.uniq_index # put contrains to the edge-class, accept only one entry per item
145
+
146
+ DATE_OF.create from: Monat[8].tag(9).stunde(12),
147
+ to: Termin.create( short: 'Mittagessen',
148
+ long: 'Schweinshaxen essen mit Lieschen Müller',
149
+ location: 'Hofbauhaus, München' )
150
+ => #<DATE_OF:0x0000000334e038 (..) @attributes={"out"=>"#21:57", "in"=>"#41:0", (..)}>
151
+ # create some regular events
152
+ # attach breakfirst at 9 o clock from the 10th to the 21st Day in the current month
153
+ DATE_OF.create from: Monat[8].tag(10 .. 21).stunde( 9 ), to: Termin.create( :short => 'Frühstück' )
154
+ => #<DATE_OF:0x000000028d5688 @metadata={(..) "cluster"=>45, "record"=>8},
155
+ @attributes={"out"=>"#22:188", "in"=>"#42:0",(..)}>
156
+
157
+ t = Termin.where short: 'Frühstück'
158
+ t.in_date_of.out.first.datum
159
+ => ["10.8.2016 9:00", "11.8.2016 9:00", "12.8.2016 9:00", "13.8.2016 9:00", "14.8.2016 9:00", "15.8.2016 9:00", "16.8.2016 9:00", "17.8.2016 9:00", "18.8.2016 9:00", "19.8.2016 9:00", "20.8.2016 9:00", "21.8.2016 9:00"]
160
+
161
+ ```
162
+