architect4r 0.3.2 → 0.3.3.1
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.
- data/Gemfile.lock +4 -4
- data/Guardfile +1 -1
- data/README.md +13 -1
- data/ReleaseNotes.md +11 -0
- data/lib/architect4r/core/cypher_methods.rb +18 -0
- data/lib/architect4r/model/properties.rb +9 -4
- data/lib/architect4r/version.rb +1 -1
- data/spec/core/cypher_methods_spec.rb +41 -0
- data/spec/model/properties_spec.rb +35 -0
- data/spec/spec_helper.rb +1 -0
- metadata +4 -3
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
architect4r (0.3.
|
4
|
+
architect4r (0.3.3.1)
|
5
5
|
activemodel (~> 3.0)
|
6
6
|
json (~> 1.5)
|
7
7
|
typhoeus (~> 0.2)
|
@@ -18,15 +18,15 @@ GEM
|
|
18
18
|
builder (3.0.0)
|
19
19
|
diff-lcs (1.1.3)
|
20
20
|
growl (1.0.3)
|
21
|
-
guard (0.8.
|
21
|
+
guard (0.8.8)
|
22
22
|
thor (~> 0.14.6)
|
23
23
|
guard-rspec (0.5.0)
|
24
24
|
guard (>= 0.8.4)
|
25
25
|
i18n (0.6.0)
|
26
26
|
json (1.6.1)
|
27
|
-
mime-types (1.17.
|
27
|
+
mime-types (1.17.2)
|
28
28
|
multi_json (1.0.3)
|
29
|
-
rake (0.9.2)
|
29
|
+
rake (0.9.2.2)
|
30
30
|
rb-fsevent (0.4.3.1)
|
31
31
|
rspec (2.7.0)
|
32
32
|
rspec-core (~> 2.7.0)
|
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,18 @@
|
|
3
3
|
Architect4r is intended as an easy ruby wrapper for the neo4j graph db
|
4
4
|
REST API. There are other solutions such as neo4j.rb if you are working
|
5
5
|
in a java environment or neography which provides another working wrapper
|
6
|
-
for the REST API.
|
6
|
+
for the REST API. Both solutions are far more feature complete and allow
|
7
|
+
you to do pretty advanced queries on the graph.
|
8
|
+
|
9
|
+
Architect4r is trying to go another route. Instead of using the native
|
10
|
+
graph traversal engine it requires you to write your queries in recently
|
11
|
+
implemented cypher query language. The language is well documented at the
|
12
|
+
official neo4j documentation (http://docs.neo4j.org/chunked/milestone/).
|
13
|
+
Just that you know what you are dealing with… a little example:
|
14
|
+
|
15
|
+
start s=node(1) match s-[:friends]-d return d order by d.name skip 0 limit 20
|
16
|
+
|
17
|
+
But please read the docs for more info.
|
7
18
|
|
8
19
|
Requirements
|
9
20
|
------------
|
@@ -25,6 +36,7 @@ Quick Start
|
|
25
36
|
# Properties
|
26
37
|
property :name, :cast_to => String, :localize => true
|
27
38
|
property :name, :cast_to => String, :localize => :de
|
39
|
+
timestamps!
|
28
40
|
|
29
41
|
# Validations
|
30
42
|
validates :name, :presence => true
|
data/ReleaseNotes.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Release Notes
|
2
2
|
|
3
|
+
## v0.3.3
|
4
|
+
|
5
|
+
* Add magic timestamp! property for tracking timestamps
|
6
|
+
|
7
|
+
By putting timestamps! into your model, it tracks the creation date and
|
8
|
+
time in created\_at and updates in updated\_at
|
9
|
+
|
10
|
+
* Allow referencing model_roots in cypher queries.
|
11
|
+
|
12
|
+
If you have a model User the reference key would be :user_root
|
13
|
+
|
3
14
|
## v0.3.2
|
4
15
|
|
5
16
|
* Support for carrierwave file upload mechanism
|
@@ -6,6 +6,9 @@ module Architect4r
|
|
6
6
|
module InstanceMethods
|
7
7
|
|
8
8
|
def execute_cypher(query)
|
9
|
+
|
10
|
+
query = self.interpolate_node_model_root_references(query)
|
11
|
+
|
9
12
|
url = prepend_base_url("/ext/CypherPlugin/graphdb/execute_query")
|
10
13
|
response = Typhoeus::Request.post(url,
|
11
14
|
:headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' },
|
@@ -41,6 +44,21 @@ module Architect4r
|
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
47
|
+
def interpolate_node_model_root_references(query)
|
48
|
+
query.scan(/node\((:[^)]*_root)\)/i).flatten.uniq.each do |str|
|
49
|
+
model_name = str.match(/^:(.*)_root$/)[1].to_s.classify
|
50
|
+
if model_name.length > 0
|
51
|
+
# As const_defined? and const_get to not support namespaces, we have to use eval :(
|
52
|
+
begin
|
53
|
+
query.gsub!(str, eval("#{model_name}.model_root.id.to_s"))
|
54
|
+
rescue NoMethodError => ex
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
query
|
60
|
+
end
|
61
|
+
|
44
62
|
end
|
45
63
|
end
|
46
64
|
end
|
@@ -54,6 +54,8 @@ module Architect4r
|
|
54
54
|
value.to_i
|
55
55
|
elsif cast_to == Float
|
56
56
|
value.to_f
|
57
|
+
elsif cast_to == DateTime
|
58
|
+
value.to_datetime
|
57
59
|
elsif cast_to == TrueClass or cast_to == FalseClass
|
58
60
|
if value.kind_of?(Integer)
|
59
61
|
value == 1
|
@@ -90,12 +92,15 @@ module Architect4r
|
|
90
92
|
end
|
91
93
|
|
92
94
|
def timestamps!
|
93
|
-
property(:updated_at, :cast_to =>
|
94
|
-
property(:created_at, :cast_to =>
|
95
|
+
property(:updated_at, :cast_to => DateTime)
|
96
|
+
property(:created_at, :cast_to => DateTime)
|
97
|
+
|
98
|
+
set_callback :create, :before do |object|
|
99
|
+
write_attribute('created_at', DateTime.now)
|
100
|
+
end
|
95
101
|
|
96
102
|
set_callback :save, :before do |object|
|
97
|
-
write_attribute('updated_at',
|
98
|
-
write_attribute('created_at', Time.now) if object.new?
|
103
|
+
write_attribute('updated_at', DateTime.now)
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
data/lib/architect4r/version.rb
CHANGED
@@ -26,4 +26,45 @@ describe Architect4r::Server do
|
|
26
26
|
|
27
27
|
end
|
28
28
|
|
29
|
+
describe :interpolate_node_model_root_references do
|
30
|
+
|
31
|
+
it "should return the original query if there is nothing to interpolate" do
|
32
|
+
result = subject.interpolate_node_model_root_references("start node(0) match something")
|
33
|
+
result.should == "start node(0) match something"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should find and replace a single reference" do
|
37
|
+
Person.should_receive(:model_root).and_return(stub(:id => 1))
|
38
|
+
result = subject.interpolate_node_model_root_references("start node(:person_root) match something")
|
39
|
+
result.should == "start node(1) match something"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should find and replace multiple references" do
|
43
|
+
Person.should_receive(:model_root).and_return(stub(:id => 1))
|
44
|
+
Ship.should_receive(:model_root).and_return(stub(:id => 2))
|
45
|
+
result = subject.interpolate_node_model_root_references("start p=node(:person_root), s=node(:ship_root) match something")
|
46
|
+
result.should == "start p=node(1), s=node(2) match something"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should find and replace multiple references to the same root" do
|
50
|
+
Person.should_receive(:model_root).and_return(stub(:id => 1))
|
51
|
+
result = subject.interpolate_node_model_root_references("start p=node(:person_root), s=node(:person_root) match something")
|
52
|
+
result.should == "start p=node(1), s=node(1) match something"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should support namespaced models" do
|
56
|
+
module MyNamespace; class UserNode; end; end
|
57
|
+
MyNamespace::UserNode.should_receive(:model_root).and_return(stub(:id => 11))
|
58
|
+
result = subject.interpolate_node_model_root_references("start s=node(:my_namespace/user_node_root) match something")
|
59
|
+
result.should == "start s=node(11) match something"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should support camel case models" do
|
63
|
+
SomeDatabaseModelNode.should_receive(:model_root).and_return(stub(:id => 12))
|
64
|
+
result = subject.interpolate_node_model_root_references("start s=node(:some_database_model_node_root) match something")
|
65
|
+
result.should == "start s=node(12) match something"
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
29
70
|
end
|
@@ -162,4 +162,39 @@ describe "Model properties based on test class Person" do
|
|
162
162
|
|
163
163
|
end
|
164
164
|
|
165
|
+
describe "automatic tracking of create and update timestamps" do
|
166
|
+
|
167
|
+
subject { Person.new(:name => 'Person with timestamps', :human => false) }
|
168
|
+
|
169
|
+
it "should allow setting timestamps" do
|
170
|
+
subject.should respond_to(:created_at)
|
171
|
+
subject.should respond_to(:updated_at)
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should create the timestamps only after creation" do
|
175
|
+
subject.created_at.should be_nil
|
176
|
+
subject.updated_at.should be_nil
|
177
|
+
subject.save
|
178
|
+
subject.created_at.should be_a(DateTime)
|
179
|
+
subject.updated_at.should be_a(DateTime)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should keep the created_at timestamp untouched after creation" do
|
183
|
+
subject.save
|
184
|
+
the_stamp = subject.created_at
|
185
|
+
subject.vita = "Some random info"
|
186
|
+
subject.save
|
187
|
+
subject.created_at.should == the_stamp
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should update the updated_at timestamp" do
|
191
|
+
subject.save
|
192
|
+
the_stamp = subject.updated_at
|
193
|
+
subject.vita = "Some random info"
|
194
|
+
subject.save
|
195
|
+
subject.updated_at.should > the_stamp
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
165
200
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -41,6 +41,7 @@ class Person < Architect4r::Model::Node
|
|
41
41
|
property :birthday, :cast_to => Date
|
42
42
|
property :age_when_enlightend, :cast_to => Integer
|
43
43
|
property :note, :cast_to => String, :localize => true
|
44
|
+
timestamps!
|
44
45
|
|
45
46
|
# Validations
|
46
47
|
validates :name, :presence => true, :length => { :minimum => 3, :allow_nil => true }
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: architect4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 89
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
|
9
|
+
- 3
|
10
|
+
- 1
|
11
|
+
version: 0.3.3.1
|
11
12
|
platform: ruby
|
12
13
|
authors:
|
13
14
|
- Maximilian Schulz
|