architect4r 0.4.3 → 0.4.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/ReleaseNotes.md +5 -0
- data/lib/architect4r/core/cypher_methods.rb +84 -86
- data/lib/architect4r/core/node_methods.rb +59 -61
- data/lib/architect4r/core/relationship_methods.rb +63 -66
- data/lib/architect4r/model/connection.rb +2 -6
- data/lib/architect4r/model/persistency.rb +40 -48
- data/lib/architect4r/model/properties.rb +60 -69
- data/lib/architect4r/model/queries.rb +0 -4
- data/lib/architect4r/model/relationships.rb +2 -6
- data/lib/architect4r/version.rb +1 -1
- metadata +4 -3
data/ReleaseNotes.md
CHANGED
@@ -3,106 +3,104 @@ module Architect4r
|
|
3
3
|
module CypherMethods
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
module InstanceMethods
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
nil
|
26
|
-
else
|
27
|
-
raise Architect4r::InvalidCypherQuery.new(query)
|
28
|
-
end
|
29
|
-
elsif response.code == 500
|
30
|
-
raise Architect4r::InvalidCypherQuery.new(query)
|
31
|
-
elsif response.code == 204
|
7
|
+
def execute_cypher(query)
|
8
|
+
query = self.interpolate_node_model_root_references(query)
|
9
|
+
|
10
|
+
Architect4r.logger.debug("[Architect4r][execute_cypher] QUERY: #{query}")
|
11
|
+
|
12
|
+
url = prepend_base_url("/cypher")
|
13
|
+
response = Typhoeus::Request.post(url,
|
14
|
+
:headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' },
|
15
|
+
:body => { 'query' => query }.to_json)
|
16
|
+
|
17
|
+
msg = JSON.parse(response.body)
|
18
|
+
|
19
|
+
Architect4r.logger.debug("[Architect4r][execute_cypher] CODE: #{response.code} => #{msg.inspect}")
|
20
|
+
|
21
|
+
# Check if there might be an error with the query
|
22
|
+
if response.code == 400
|
23
|
+
if msg['exception'].to_s.match /org.neo4j.graphdb.NotFoundException/
|
32
24
|
nil
|
33
25
|
else
|
34
|
-
|
26
|
+
raise Architect4r::InvalidCypherQuery.new(query)
|
35
27
|
end
|
28
|
+
elsif response.code == 500
|
29
|
+
raise Architect4r::InvalidCypherQuery.new(query)
|
30
|
+
elsif response.code == 204
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
msg
|
36
34
|
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def cypher_query(query, transform=true)
|
38
|
+
# Get data from server
|
39
|
+
data = execute_cypher(query)
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# Create native ruby objects
|
45
|
-
data['data'].map! do |set|
|
46
|
-
set.map { |item| convert_if_possible(item) }
|
47
|
-
end
|
48
|
-
|
49
|
-
# Transform to hash form
|
50
|
-
if transform
|
51
|
-
transform_cypher_result_to_hash(data)
|
52
|
-
else
|
53
|
-
data
|
54
|
-
end
|
41
|
+
Architect4r.logger.debug("[Architect4r][cypher_query] #{data.inspect}")
|
42
|
+
|
43
|
+
# Create native ruby objects
|
44
|
+
data['data'].map! do |set|
|
45
|
+
set.map { |item| convert_if_possible(item) }
|
55
46
|
end
|
56
47
|
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
48
|
+
# Transform to hash form
|
49
|
+
if transform
|
50
|
+
transform_cypher_result_to_hash(data)
|
51
|
+
else
|
52
|
+
data
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Convert the columnized result array to a hashes within an array
|
57
|
+
#
|
58
|
+
# The input would look like:
|
59
|
+
#
|
60
|
+
# { 'data' => [['r1', 'n1'], ['r2', 'n2'], …], 'columns' => ['rel', 'node']}
|
61
|
+
#
|
62
|
+
# And it would be transformed to:
|
63
|
+
# [ { 'rel' => 'r1', 'node' => 'n1' }, { 'rel' => 'r2', 'node' => 'n2' } ]
|
64
|
+
#
|
65
|
+
def transform_cypher_result_to_hash(input)
|
66
|
+
results = []
|
67
|
+
input['data'].each_with_index do |row, ri|
|
68
|
+
result_row = {}
|
69
|
+
input['columns'].each_with_index do |column, ci|
|
70
|
+
result_row[column] = row[ci]
|
74
71
|
end
|
75
|
-
results
|
72
|
+
results << result_row
|
76
73
|
end
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
74
|
+
results
|
75
|
+
end
|
76
|
+
|
77
|
+
# Parses a cypher query and replaces all placeholders for model roots
|
78
|
+
# with the neo4j ids. It should make development faster, as you can
|
79
|
+
# skip manual id retrieval:
|
80
|
+
#
|
81
|
+
# So instead of writing:
|
82
|
+
#
|
83
|
+
# "start s=node(#{Person.model_root.id}) match s-->d return d"
|
84
|
+
#
|
85
|
+
# you can write:
|
86
|
+
#
|
87
|
+
# "start s=node(:person_root) match s-->d return d"
|
88
|
+
#
|
89
|
+
def interpolate_node_model_root_references(query)
|
90
|
+
query.scan(/node\((:[^)]*_root)\)/i).flatten.uniq.each do |str|
|
91
|
+
model_name = str.match(/^:(.*)_root$/)[1].to_s.classify
|
92
|
+
if model_name.length > 0
|
93
|
+
# As const_defined? and const_get to not support namespaces, we have to use eval :(
|
94
|
+
begin
|
95
|
+
query.gsub!(str, eval("#{model_name}.model_root.id.to_s"))
|
96
|
+
rescue NoMethodError => ex
|
97
|
+
nil
|
100
98
|
end
|
101
99
|
end
|
102
|
-
query
|
103
100
|
end
|
104
|
-
|
101
|
+
query
|
105
102
|
end
|
103
|
+
|
106
104
|
end
|
107
105
|
end
|
108
106
|
end
|
@@ -3,75 +3,73 @@ module Architect4r
|
|
3
3
|
module NodeMethods
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
6
|
+
def create_node(properties)
|
7
|
+
# Send request
|
8
|
+
response = Typhoeus::Request.post(prepend_base_url('/node'),
|
9
|
+
:headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' },
|
10
|
+
:body => properties.to_json)
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
# Evaluate response
|
13
|
+
response.code == 201 ? JSON.parse(response.body) : nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_node(id)
|
17
|
+
# Example response for a node
|
18
|
+
# extensions: {}
|
19
|
+
#
|
20
|
+
# paged_traverse: http://localhost:7475/db/data/node/0/paged/traverse/{returnType}{?pageSize,leaseTime}
|
21
|
+
# self: http://localhost:7475/db/data/node/0
|
22
|
+
# property: http://localhost:7475/db/data/node/0/properties/{key}
|
23
|
+
# data: {}
|
24
|
+
#
|
25
|
+
# incoming_typed_relationships: http://localhost:7475/db/data/node/0/relationships/in/{-list|&|types}
|
26
|
+
# outgoing_typed_relationships: http://localhost:7475/db/data/node/0/relationships/out/{-list|&|types}
|
27
|
+
# incoming_relationships: http://localhost:7475/db/data/node/0/relationships/in
|
28
|
+
# all_relationships: http://localhost:7475/db/data/node/0/relationships/all
|
29
|
+
# create_relationship: http://localhost:7475/db/data/node/0/relationships
|
30
|
+
# traverse: http://localhost:7475/db/data/node/0/traverse/{returnType}
|
31
|
+
# properties: http://localhost:7475/db/data/node/0/properties
|
32
|
+
# all_typed_relationships: http://localhost:7475/db/data/node/0/relationships/all/{-list|&|types}
|
33
|
+
# outgoing_relationships: http://localhost:7475/db/data/node/0/relationships/out
|
17
34
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# self: http://localhost:7475/db/data/node/0
|
24
|
-
# property: http://localhost:7475/db/data/node/0/properties/{key}
|
25
|
-
# data: {}
|
26
|
-
#
|
27
|
-
# incoming_typed_relationships: http://localhost:7475/db/data/node/0/relationships/in/{-list|&|types}
|
28
|
-
# outgoing_typed_relationships: http://localhost:7475/db/data/node/0/relationships/out/{-list|&|types}
|
29
|
-
# incoming_relationships: http://localhost:7475/db/data/node/0/relationships/in
|
30
|
-
# all_relationships: http://localhost:7475/db/data/node/0/relationships/all
|
31
|
-
# create_relationship: http://localhost:7475/db/data/node/0/relationships
|
32
|
-
# traverse: http://localhost:7475/db/data/node/0/traverse/{returnType}
|
33
|
-
# properties: http://localhost:7475/db/data/node/0/properties
|
34
|
-
# all_typed_relationships: http://localhost:7475/db/data/node/0/relationships/all/{-list|&|types}
|
35
|
-
# outgoing_relationships: http://localhost:7475/db/data/node/0/relationships/out
|
36
|
-
|
37
|
-
# Handle cases where id might be a url
|
38
|
-
|
39
|
-
response = Typhoeus::Request.get(node_url(id), :headers => { 'Accept' => 'application/json' })
|
40
|
-
response.code == 200 ? JSON.parse(response.body) : nil
|
41
|
-
end
|
35
|
+
# Handle cases where id might be a url
|
36
|
+
|
37
|
+
response = Typhoeus::Request.get(node_url(id), :headers => { 'Accept' => 'application/json' })
|
38
|
+
response.code == 200 ? JSON.parse(response.body) : nil
|
39
|
+
end
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
def update_node(id, properties)
|
42
|
+
# Handle urls
|
43
|
+
url = id.to_i == 0 ? id : node_url(id)
|
46
44
|
|
47
|
-
|
48
|
-
|
45
|
+
# Append the properties
|
46
|
+
url += "/properties"
|
49
47
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
# Delete node itself
|
63
|
-
response = Typhoeus::Request.delete(node_url(id), :headers => { 'Accept' => 'application/json' })
|
64
|
-
response.code == 204 ? true : false
|
65
|
-
end
|
66
|
-
|
67
|
-
def root
|
68
|
-
get_node(get('/')['reference_node'])
|
48
|
+
response = Typhoeus::Request.put(url,
|
49
|
+
:headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' },
|
50
|
+
:body => properties.to_json)
|
51
|
+
response.code == 204 ? true : false
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete_node(id)
|
55
|
+
# Delete all relationships
|
56
|
+
get_node_relationships(id, :all).each do |rel|
|
57
|
+
delete_relationship(rel)
|
69
58
|
end
|
70
59
|
|
71
|
-
|
72
|
-
|
73
|
-
|
60
|
+
# Delete node itself
|
61
|
+
response = Typhoeus::Request.delete(node_url(id), :headers => { 'Accept' => 'application/json' })
|
62
|
+
response.code == 204 ? true : false
|
74
63
|
end
|
64
|
+
|
65
|
+
def root
|
66
|
+
get_node(get('/')['reference_node'])
|
67
|
+
end
|
68
|
+
|
69
|
+
def node_id(input)
|
70
|
+
node_url(input).match(/node\/(\d+)$/i)[1].to_i
|
71
|
+
end
|
72
|
+
|
75
73
|
end
|
76
74
|
end
|
77
75
|
end
|
@@ -3,80 +3,77 @@ module Architect4r
|
|
3
3
|
module RelationshipMethods
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
6
|
+
def create_relationship(start_node, end_node, type, properties={})
|
7
|
+
# POST http://localhost:7474/db/data/node/3/relationships
|
8
|
+
# {"to" : "http://localhost:7474/db/data/node/4", "type" : "LOVES"}
|
9
|
+
# 201: Created
|
10
|
+
# Location: http://localhost:7474/db/data/relationship/2
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
# {"to" : "http://localhost:7474/db/data/node/4", "type" : "LOVES"}
|
11
|
-
# 201: Created
|
12
|
-
# Location: http://localhost:7474/db/data/relationship/2
|
13
|
-
|
14
|
-
# Add the destination node and type to the properties
|
15
|
-
properties = { 'to' => node_url(end_node), 'type' => type.to_s, 'data' => properties }
|
16
|
-
|
17
|
-
# Send request
|
18
|
-
response = Typhoeus::Request.post(node_url(start_node) + "/relationships",
|
19
|
-
:headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' },
|
20
|
-
:body => properties.to_json)
|
21
|
-
|
22
|
-
# Evaluate response
|
23
|
-
response.code == 201 ? JSON.parse(response.body) : nil
|
24
|
-
end
|
12
|
+
# Add the destination node and type to the properties
|
13
|
+
properties = { 'to' => node_url(end_node), 'type' => type.to_s, 'data' => properties }
|
25
14
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
15
|
+
# Send request
|
16
|
+
response = Typhoeus::Request.post(node_url(start_node) + "/relationships",
|
17
|
+
:headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' },
|
18
|
+
:body => properties.to_json)
|
30
19
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
# Create typ filter
|
54
|
-
types = types.map { |e| URI.escape(e) }.join('&')
|
55
|
-
|
56
|
-
# Send request
|
57
|
-
url = node_url(node) + "/relationships/#{direction}/#{types}"
|
58
|
-
response = Typhoeus::Request.get(url, :headers => { 'Accept' => 'application/json' })
|
59
|
-
response.code == 200 ? JSON.parse(response.body) : []
|
60
|
-
end
|
20
|
+
# Evaluate response
|
21
|
+
response.code == 201 ? JSON.parse(response.body) : nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_relationship(relationship)
|
25
|
+
response = Typhoeus::Request.get(relationship_url(relationship), :headers => { 'Accept' => 'application/json' })
|
26
|
+
response.code == 200 ? JSON.parse(response.body) : nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete_relationship(relationship)
|
30
|
+
response = Typhoeus::Request.delete(relationship_url(relationship), :headers => { 'Accept' => 'application/json' })
|
31
|
+
response.code == 204 ? true : false
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_node_relationships(node, direction = :all, *types)
|
35
|
+
# GET http://localhost:7474/db/data/node/6/relationships/all
|
36
|
+
# GET http://localhost:7474/db/data/node/11/relationships/in
|
37
|
+
# GET http://localhost:7474/db/data/node/16/relationships/out
|
38
|
+
# GET http://localhost:7474/db/data/node/21/relationships/all/LIKES&HATES
|
39
|
+
# 200: OK
|
61
40
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
41
|
+
# Set direction
|
42
|
+
direction = case direction.to_s
|
43
|
+
when 'incoming'
|
44
|
+
'in'
|
45
|
+
when 'outgoing'
|
46
|
+
'out'
|
47
|
+
else
|
48
|
+
'all'
|
70
49
|
end
|
71
50
|
|
72
|
-
|
73
|
-
|
74
|
-
# 200: OK
|
75
|
-
response = Typhoeus::Request.get(prepend_base_url('/relationship/types'), :headers => { 'Accept' => 'application/json' })
|
76
|
-
response.code == 200 ? JSON.parse(response.body) : []
|
77
|
-
end
|
51
|
+
# Create typ filter
|
52
|
+
types = types.map { |e| URI.escape(e) }.join('&')
|
78
53
|
|
54
|
+
# Send request
|
55
|
+
url = node_url(node) + "/relationships/#{direction}/#{types}"
|
56
|
+
response = Typhoeus::Request.get(url, :headers => { 'Accept' => 'application/json' })
|
57
|
+
response.code == 200 ? JSON.parse(response.body) : []
|
58
|
+
end
|
59
|
+
|
60
|
+
def update_relationship(id, properties)
|
61
|
+
# PUT http://localhost:7474/db/data/relationship/0/properties
|
62
|
+
# 204: No Content
|
63
|
+
url = relationship_url(id) + '/properties'
|
64
|
+
response = Typhoeus::Request.put(url,
|
65
|
+
:headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' },
|
66
|
+
:body => properties.to_json)
|
67
|
+
response.code == 204 ? true : false
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_relationship_types
|
71
|
+
# GET http://localhost:7474/db/data/relationship/types
|
72
|
+
# 200: OK
|
73
|
+
response = Typhoeus::Request.get(prepend_base_url('/relationship/types'), :headers => { 'Accept' => 'application/json' })
|
74
|
+
response.code == 200 ? JSON.parse(response.body) : []
|
79
75
|
end
|
76
|
+
|
80
77
|
end
|
81
78
|
end
|
82
79
|
end
|
@@ -3,65 +3,57 @@ module Architect4r
|
|
3
3
|
module Persistency
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
# Creates the document in the db. Raises an exception
|
7
|
+
# if the document is not created properly.
|
8
|
+
def create!(options = {})
|
9
|
+
self.fail_validate!(self) unless self.create(options)
|
8
10
|
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# if the document is not created properly.
|
14
|
-
def create!(options = {})
|
15
|
-
self.fail_validate!(self) unless self.create(options)
|
16
|
-
end
|
17
|
-
|
18
|
-
def save(options = {})
|
19
|
-
self.new? ? create(options) : update(options)
|
20
|
-
end
|
12
|
+
def save(options = {})
|
13
|
+
self.new? ? create(options) : update(options)
|
14
|
+
end
|
21
15
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
16
|
+
def save!
|
17
|
+
self.class.fail_validate!(self) unless self.save
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def id
|
22
|
+
@id ||= if raw_data && raw_data['self'].present?
|
23
|
+
raw_data['self'].split('/').last.to_i
|
24
|
+
else
|
25
|
+
nil
|
33
26
|
end
|
34
|
-
|
35
|
-
|
27
|
+
end
|
28
|
+
alias :to_key :id
|
29
|
+
alias :to_param :id
|
36
30
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
31
|
+
def new?
|
32
|
+
# Persisted objects always have an id.
|
33
|
+
id.nil?
|
34
|
+
end
|
35
|
+
alias :new_record? :new?
|
42
36
|
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
def destroyed?
|
38
|
+
!!@_destroyed
|
39
|
+
end
|
46
40
|
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
def persisted?
|
42
|
+
!new? && !destroyed?
|
43
|
+
end
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
45
|
+
# Update the document's attributes and save. For example:
|
46
|
+
def update_attributes(hash)
|
47
|
+
update_attributes_without_saving hash
|
48
|
+
save
|
49
|
+
end
|
56
50
|
|
57
|
-
|
51
|
+
protected
|
58
52
|
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
|
53
|
+
def perform_validations(options = {})
|
54
|
+
(options[:validate].presence || true) ? valid? : true
|
63
55
|
end
|
64
|
-
|
56
|
+
|
65
57
|
module ClassMethods
|
66
58
|
|
67
59
|
def create(*args, &block)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Architect4r
|
2
|
-
|
3
2
|
module Model
|
4
|
-
|
5
3
|
module Properties
|
6
4
|
extend ActiveSupport::Concern
|
7
5
|
|
@@ -10,78 +8,74 @@ module Architect4r
|
|
10
8
|
self.properties ||= {}
|
11
9
|
end
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
11
|
+
def parse_properties(properties = {})
|
12
|
+
@properties_data = {}
|
13
|
+
update_attributes_without_saving(properties)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return a hash of all properties which can be transformed into json
|
17
|
+
# Remove all nil values, as those cannot be stored in the graph
|
18
|
+
def _to_database_hash
|
19
|
+
@properties_data.merge('architect4r_type' => self.class.name).
|
20
|
+
reject { |key, value| value.nil? }
|
21
|
+
end
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
23
|
+
# Read the casted value of an attribute defined with a property.
|
24
|
+
#
|
25
|
+
# ==== Returns
|
26
|
+
# Object:: the casted attibutes value.
|
27
|
+
def read_attribute(property, locale = nil)
|
28
|
+
property = "#{property}_#{locale}" if locale
|
29
|
+
@properties_data[property.to_s]
|
30
|
+
end
|
34
31
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
%w[ true 1 t ].include?(value.to_s.downcase)
|
64
|
-
end
|
32
|
+
# Store a casted value in the current instance of an attribute defined
|
33
|
+
# with a property and update dirty status
|
34
|
+
def write_attribute(property, value, locale = nil)
|
35
|
+
# retrieve options for the attribute
|
36
|
+
opts = self.class.properties[property.to_s]
|
37
|
+
|
38
|
+
# Check if we should store a localized version of the data
|
39
|
+
property = "#{property}_#{locale}" if locale
|
40
|
+
|
41
|
+
# TODO: Mark dirty attribute tracking
|
42
|
+
|
43
|
+
# Cast the value before storing it
|
44
|
+
cast_to = opts && opts[:cast_to] || Object
|
45
|
+
|
46
|
+
@properties_data[property.to_s] = if value.nil?
|
47
|
+
nil
|
48
|
+
elsif cast_to == String
|
49
|
+
value.to_s
|
50
|
+
elsif cast_to == Integer
|
51
|
+
value.to_i
|
52
|
+
elsif cast_to == Float
|
53
|
+
value.to_f
|
54
|
+
elsif cast_to == DateTime
|
55
|
+
value.to_datetime
|
56
|
+
elsif cast_to == TrueClass or cast_to == FalseClass
|
57
|
+
if value.kind_of?(Integer)
|
58
|
+
value == 1
|
65
59
|
else
|
66
|
-
value
|
60
|
+
%w[ true 1 t ].include?(value.to_s.downcase)
|
67
61
|
end
|
62
|
+
else
|
63
|
+
value
|
68
64
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
65
|
+
end
|
66
|
+
|
67
|
+
def update_attributes_without_saving(hash)
|
68
|
+
return if hash.nil?
|
69
|
+
hash.each do |key, value|
|
70
|
+
if self.respond_to?("#{key}=")
|
71
|
+
self.send("#{key}=", value)
|
72
|
+
else
|
73
|
+
@properties_data[key] = value
|
78
74
|
end
|
79
75
|
end
|
80
|
-
alias :attributes= :update_attributes_without_saving
|
81
|
-
|
82
|
-
|
83
76
|
end
|
84
|
-
|
77
|
+
alias :attributes= :update_attributes_without_saving
|
78
|
+
|
85
79
|
module ClassMethods
|
86
80
|
|
87
81
|
# Allow setting properties
|
@@ -163,9 +157,6 @@ module Architect4r
|
|
163
157
|
end
|
164
158
|
|
165
159
|
end
|
166
|
-
|
167
160
|
end
|
168
|
-
|
169
161
|
end
|
170
|
-
|
171
162
|
end
|
@@ -3,12 +3,8 @@ module Architect4r
|
|
3
3
|
module Relationships
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
def links
|
9
|
-
@links_query_interface = LinksQueryInterface.new(self)
|
10
|
-
end
|
11
|
-
|
6
|
+
def links
|
7
|
+
@links_query_interface = LinksQueryInterface.new(self)
|
12
8
|
end
|
13
9
|
|
14
10
|
end
|
data/lib/architect4r/version.rb
CHANGED
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: 97
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
9
|
- 3
|
10
|
-
|
10
|
+
- 1
|
11
|
+
version: 0.4.3.1
|
11
12
|
platform: ruby
|
12
13
|
authors:
|
13
14
|
- Maximilian Schulz
|
@@ -15,7 +16,7 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2012-
|
19
|
+
date: 2012-03-03 00:00:00 Z
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: activemodel
|