architect4r 0.3.2 → 0.3.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- architect4r (0.3.2)
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.7)
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.1)
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
@@ -1,4 +1,4 @@
1
- guard 'rspec' do
1
+ guard 'rspec', :all_after_pass => false, :version => 2 do
2
2
  # Check for changes in classes
3
3
  watch(%r{^lib/architect4r/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
4
 
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 => Time)
94
- property(:created_at, :cast_to => Time)
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', Time.now)
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
 
@@ -1,3 +1,3 @@
1
1
  module Architect4r
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3.1"
3
3
  end
@@ -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: 23
4
+ hash: 89
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 2
10
- version: 0.3.2
9
+ - 3
10
+ - 1
11
+ version: 0.3.3.1
11
12
  platform: ruby
12
13
  authors:
13
14
  - Maximilian Schulz