architect4r 0.4.3 → 0.4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|