Parsistence 0.2.1 → 0.3.0
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/README.md +97 -17
- data/lib/Parsistence/Model.rb +130 -35
- data/lib/Parsistence/Query.rb +31 -8
- data/lib/Parsistence/Relation.rb +28 -0
- data/lib/Parsistence/User.rb +11 -1
- data/lib/Parsistence/version.rb +1 -1
- metadata +3 -2
data/README.md
CHANGED
@@ -52,7 +52,7 @@ users.map {|u| u.objectId}.include?(user.objectId) #=> true
|
|
52
52
|
Queries use a somewhat different pattern than ActiveRecord but are relatively familiar. They are most like persistence.js.
|
53
53
|
|
54
54
|
```ruby
|
55
|
-
Car.eq(license: "ABC-123", model: "Camry").order(year: :desc).limit(25).
|
55
|
+
Car.eq(license: "ABC-123", model: "Camry").order(year: :desc).limit(25).fetchAll do |cars, error|
|
56
56
|
if cars
|
57
57
|
cars.each do |car|
|
58
58
|
# `car` is an instance of your `Car` model here.
|
@@ -66,21 +66,101 @@ Chain multiple conditions together, even the same condition type multiple times,
|
|
66
66
|
####Available Conditions
|
67
67
|
(note: each condition can take multiple comma-separated fields and values)
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
69
|
+
<table>
|
70
|
+
<tr>
|
71
|
+
<th>Method</th>
|
72
|
+
<th>Effect</th>
|
73
|
+
<th>Example</th>
|
74
|
+
</tr>
|
75
|
+
|
76
|
+
<tr>
|
77
|
+
<td>eq</td>
|
78
|
+
<td>Equal to</td>
|
79
|
+
<td>
|
80
|
+
<pre>
|
81
|
+
Tree.eq(name: "Fir").fetchAll do |trees|
|
82
|
+
...
|
83
|
+
end</pre>
|
84
|
+
</td>
|
85
|
+
</tr>
|
86
|
+
|
87
|
+
<tr>
|
88
|
+
<td>notEq</td>
|
89
|
+
<td>NOT equal to</td>
|
90
|
+
<td>
|
91
|
+
<pre>
|
92
|
+
Tree.notEq(name: "Fir").fetchAll do |trees|
|
93
|
+
...
|
94
|
+
end</pre>
|
95
|
+
</td>
|
96
|
+
</tr>
|
97
|
+
|
98
|
+
<tr>
|
99
|
+
<td>gt</td>
|
100
|
+
<td>Greater than</td>
|
101
|
+
<td>
|
102
|
+
<pre>
|
103
|
+
Tree.gt(height: 10).fetchAll do |trees|
|
104
|
+
...
|
105
|
+
end</pre>
|
106
|
+
</td>
|
107
|
+
</tr>
|
108
|
+
|
109
|
+
<tr>
|
110
|
+
<td>lt</td>
|
111
|
+
<td>Less than</td>
|
112
|
+
<td>
|
113
|
+
<pre>
|
114
|
+
Tree.lt(height: 10).fetchAll do |trees|
|
115
|
+
...
|
116
|
+
end</pre>
|
117
|
+
</td>
|
118
|
+
</tr>
|
119
|
+
|
120
|
+
<tr>
|
121
|
+
<td>gte</td>
|
122
|
+
<td>Greater than or equal to</td>
|
123
|
+
<td>
|
124
|
+
<pre>
|
125
|
+
Tree.gte(height: 10).fetchAll do |trees|
|
126
|
+
...
|
127
|
+
end</pre>
|
128
|
+
</td>
|
129
|
+
</tr>
|
130
|
+
|
131
|
+
<tr>
|
132
|
+
<td>lte</td>
|
133
|
+
<td>Less than or equal to</td>
|
134
|
+
<td>
|
135
|
+
<pre>
|
136
|
+
Tree.lte(height: 10).fetchAll do |trees|
|
137
|
+
...
|
138
|
+
end</pre>
|
139
|
+
</td>
|
140
|
+
</tr>
|
141
|
+
|
142
|
+
<tr>
|
143
|
+
<td>order</td>
|
144
|
+
<td>Order by one or more fields (:asc/:desc).</td>
|
145
|
+
<td>
|
146
|
+
<pre>
|
147
|
+
Tree.order(height: :asc).fetchAll do |trees|
|
148
|
+
...
|
149
|
+
end</pre>
|
150
|
+
</td>
|
151
|
+
</tr>
|
152
|
+
|
153
|
+
<tr>
|
154
|
+
<td>limit</td>
|
155
|
+
<td>Limit and offset.</td>
|
156
|
+
<td>
|
157
|
+
<pre>
|
158
|
+
Tree.limit(25, 10).fetchAll do |trees|
|
159
|
+
...
|
160
|
+
end</pre>
|
161
|
+
</td>
|
162
|
+
</tr>
|
163
|
+
</table>
|
84
164
|
|
85
165
|
### Relationships
|
86
166
|
|
@@ -92,7 +172,7 @@ class Post
|
|
92
172
|
|
93
173
|
fields :title, :body, :author
|
94
174
|
|
95
|
-
|
175
|
+
belongs_to :author # Must be a "pointer" object on Parse.com
|
96
176
|
end
|
97
177
|
|
98
178
|
Author.where(name: "Jamon Holmgren").fetchOne do |fetchedAuthor, error|
|
data/lib/Parsistence/Model.rb
CHANGED
@@ -11,32 +11,30 @@ module Parsistence
|
|
11
11
|
self.PFObject = PFObject.objectWithClassName(self.class.to_s)
|
12
12
|
end
|
13
13
|
|
14
|
-
# setupRelations unless pf
|
15
|
-
|
16
14
|
self
|
17
15
|
end
|
18
|
-
|
19
|
-
# This code is to correct for a bug where relations aren't initialized when creating a new instance
|
20
|
-
# def setupRelations
|
21
|
-
# relations.each do |r|
|
22
|
-
# self.send("#{r}=", @PFObject.relationforKey(r))
|
23
|
-
# end
|
24
|
-
# end
|
25
16
|
|
26
17
|
def method_missing(method, *args, &block)
|
27
18
|
method = method.to_sym
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
19
|
+
setter = false
|
20
|
+
|
21
|
+
if method.to_s.include?("=")
|
22
|
+
setter = true
|
23
|
+
method = method.split("=")[0].to_sym
|
24
|
+
end
|
25
|
+
|
26
|
+
# Setters
|
27
|
+
if relations.include?(method) && setter
|
28
|
+
return setRelation(method, args.first)
|
29
|
+
elsif fields.include?(method) && setter
|
32
30
|
return setField(method, args.first)
|
33
|
-
|
31
|
+
# Getters
|
32
|
+
elsif relations.include? method
|
34
33
|
return getRelation(method)
|
35
|
-
elsif
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
return @PFObject.send(method, *args, &block)
|
34
|
+
elsif fields.include? method
|
35
|
+
return getField(method)
|
36
|
+
elsif self.PFObject.respond_to?(method)
|
37
|
+
return self.PFObject.send(method, *args, &block)
|
40
38
|
else
|
41
39
|
super
|
42
40
|
end
|
@@ -64,18 +62,33 @@ module Parsistence
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def getRelation(field)
|
67
|
-
|
68
|
-
|
65
|
+
if has_many.include?(field.to_sym)
|
66
|
+
relation = @PFObject.objectForKey(field) if relations.include? field.to_sym
|
67
|
+
# This is not implemented yet
|
68
|
+
# return @relation[field] ||= begin
|
69
|
+
# r = Relation.new(relation)
|
70
|
+
# r.klass = self
|
71
|
+
# r.belongs_to = true
|
72
|
+
# r
|
73
|
+
# end
|
74
|
+
raise "Parsistence Exception: has_many relationships aren't implemented yet. Use a regular query instead."
|
75
|
+
elsif belongs_to.include?(field.to_sym)
|
76
|
+
return self.getField(field)
|
77
|
+
else
|
78
|
+
raise "Parsistence Exception: Invalid relation name #{field} for object #{self.class.to_s}"
|
79
|
+
end
|
69
80
|
end
|
70
81
|
|
71
82
|
def setRelation(field, value)
|
72
83
|
value = value.PFObject if value.respond_to? :PFObject # unwrap object
|
73
|
-
|
74
|
-
|
75
|
-
|
84
|
+
if has_many.include?(field.to_sym)
|
85
|
+
relation = @PFObject.relationforKey(field)
|
86
|
+
return relation.addObject(value) if relations.include? field.to_sym
|
87
|
+
elsif belongs_to.include?(field.to_sym)
|
88
|
+
return setField(field, value)
|
89
|
+
end
|
76
90
|
|
77
|
-
|
78
|
-
raise "Parsistence Exception: Invalid relation name #{field} for object #{self.class.to_s}" unless relations.include? relation.to_sym
|
91
|
+
raise "Parsistence Exception: Invalid relation name #{field} for object #{self.class.to_s}"
|
79
92
|
end
|
80
93
|
|
81
94
|
def attributes
|
@@ -88,7 +101,9 @@ module Parsistence
|
|
88
101
|
|
89
102
|
def attributes=(hashValue)
|
90
103
|
hashValue.each do |k, v|
|
91
|
-
if
|
104
|
+
if v.respond_to?(:each) && !v.is_a?(PFObject)
|
105
|
+
self.attributes = v
|
106
|
+
elsif self.respond_to? "#{k}="
|
92
107
|
self.send("#{k}=", v)
|
93
108
|
else
|
94
109
|
setField(k, v) unless k.nil?
|
@@ -99,11 +114,17 @@ module Parsistence
|
|
99
114
|
def save
|
100
115
|
saved = false
|
101
116
|
unless before_save == false
|
117
|
+
reset_errors
|
102
118
|
self.attributes.each do |field, value|
|
103
119
|
validateField field, value
|
104
120
|
end
|
105
121
|
|
106
|
-
|
122
|
+
if @errors && @errors.length > 0
|
123
|
+
saved = false
|
124
|
+
else
|
125
|
+
saved = @PFObject.save
|
126
|
+
end
|
127
|
+
|
107
128
|
after_save if saved
|
108
129
|
end
|
109
130
|
saved
|
@@ -114,18 +135,52 @@ module Parsistence
|
|
114
135
|
|
115
136
|
# Validations
|
116
137
|
def presenceValidations
|
117
|
-
self.class.send(:
|
138
|
+
self.class.send(:get_presence_validations)
|
139
|
+
end
|
140
|
+
|
141
|
+
def presenceValidationMessages
|
142
|
+
self.class.send(:get_presence_validation_messages)
|
143
|
+
end
|
144
|
+
|
145
|
+
def has_many
|
146
|
+
self.class.send(:get_has_many)
|
147
|
+
end
|
148
|
+
|
149
|
+
def belongs_to
|
150
|
+
self.class.send(:get_belongs_to)
|
118
151
|
end
|
119
152
|
|
120
153
|
def validateField(field, value)
|
121
154
|
@errors ||= {}
|
122
|
-
|
155
|
+
if presenceValidations.include?(field) && value.nil? || value == ""
|
156
|
+
messages = presenceValidationMessages
|
157
|
+
if messages.include?(field)
|
158
|
+
@errors[field] = messages[field]
|
159
|
+
else
|
160
|
+
@errors[field] = "#{field} can't be blank"
|
161
|
+
end
|
162
|
+
end
|
123
163
|
end
|
124
164
|
|
125
165
|
def errorForField(field)
|
126
166
|
@errors[field] || false
|
127
167
|
end
|
128
168
|
|
169
|
+
def errors
|
170
|
+
@errors
|
171
|
+
end
|
172
|
+
|
173
|
+
def valid?
|
174
|
+
self.errors.nil? || self.errors.length == 0
|
175
|
+
end
|
176
|
+
|
177
|
+
def invalid?
|
178
|
+
!self.valid?
|
179
|
+
end
|
180
|
+
|
181
|
+
def reset_errors
|
182
|
+
@errors = nil
|
183
|
+
end
|
129
184
|
|
130
185
|
module ClassMethods
|
131
186
|
def fields(*args)
|
@@ -139,7 +194,7 @@ module Parsistence
|
|
139
194
|
end
|
140
195
|
|
141
196
|
def get_fields
|
142
|
-
@fields
|
197
|
+
@fields ||= []
|
143
198
|
end
|
144
199
|
|
145
200
|
def relations(*args)
|
@@ -156,12 +211,52 @@ module Parsistence
|
|
156
211
|
@relations ||= []
|
157
212
|
end
|
158
213
|
|
159
|
-
def
|
160
|
-
|
214
|
+
def has_many(field, args={})
|
215
|
+
relation(field)
|
216
|
+
|
217
|
+
@has_many ||= []
|
218
|
+
@has_many << field
|
219
|
+
@has_many.uniq!
|
220
|
+
|
221
|
+
@has_many_attributes ||= {}
|
222
|
+
@has_many_attributes[field] = args
|
223
|
+
end
|
224
|
+
|
225
|
+
def get_has_many
|
226
|
+
@has_many ||= []
|
161
227
|
end
|
162
228
|
|
163
|
-
def
|
164
|
-
|
229
|
+
def belongs_to(field, args={})
|
230
|
+
relation(field)
|
231
|
+
|
232
|
+
@belongs_to ||= []
|
233
|
+
@belongs_to << field
|
234
|
+
@belongs_to.uniq!
|
235
|
+
|
236
|
+
@belongs_to_attributes ||= {}
|
237
|
+
@belongs_to_attributes[field] = args
|
238
|
+
end
|
239
|
+
|
240
|
+
def get_belongs_to
|
241
|
+
@belongs_to ||= []
|
242
|
+
end
|
243
|
+
|
244
|
+
def get_belongs_to_attributes(field)
|
245
|
+
@belongs_to_attributes[field] ||= { class_name: field }
|
246
|
+
end
|
247
|
+
|
248
|
+
def validates_presence_of(field, opts={})
|
249
|
+
@presenceValidationMessages ||= {}
|
250
|
+
@presenceValidationMessages[field] = opts[:message] if opts[:message]
|
251
|
+
validate_presence(field)
|
252
|
+
end
|
253
|
+
|
254
|
+
def get_presence_validations
|
255
|
+
@presenceValidations ||= {}
|
256
|
+
end
|
257
|
+
|
258
|
+
def get_presence_validation_messages
|
259
|
+
@presenceValidationMessages ||= {}
|
165
260
|
end
|
166
261
|
|
167
262
|
def validate_presence(field)
|
data/lib/Parsistence/Query.rb
CHANGED
@@ -1,21 +1,43 @@
|
|
1
1
|
module Parsistence
|
2
2
|
module Model
|
3
3
|
module ClassMethods
|
4
|
-
QUERY_STUBS = [ :
|
4
|
+
QUERY_STUBS = [ :where, :first, :limit, :order, :eq, :notEq, :lt, :gt, :lte, :gte ] # :limit is different
|
5
|
+
|
6
|
+
def fetchAll(&block)
|
7
|
+
q = Parsistence::Query.new
|
8
|
+
q.klass = self
|
9
|
+
return q.fetchAll &block
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetchOne(&block)
|
13
|
+
q = Parsistence::Query.new
|
14
|
+
q.klass = self
|
15
|
+
q.limit(1).fetchAll &block
|
16
|
+
end
|
17
|
+
|
18
|
+
def all(&block)
|
19
|
+
fetchAll(&block)
|
20
|
+
end
|
5
21
|
|
6
22
|
def method_missing(method, *args, &block)
|
7
|
-
if method == :limit
|
8
|
-
|
9
|
-
|
23
|
+
if method == :limit && args.length == 2
|
24
|
+
q = Parsistence::Query.new
|
25
|
+
q.klass = self
|
26
|
+
return q.send(method, args[0], args[1])
|
27
|
+
elsif QUERY_STUBS.include? method.to_sym && args.length == 0
|
28
|
+
q = Parsistence::Query.new
|
29
|
+
q.klass = self
|
30
|
+
return q.send(method, &block) if block_given?
|
31
|
+
return q.send(method)
|
10
32
|
elsif QUERY_STUBS.include? method.to_sym
|
11
33
|
q = Parsistence::Query.new
|
12
34
|
q.klass = self
|
13
|
-
return q.send(method, args.first, &block) if
|
35
|
+
return q.send(method, args.first, &block) if block_given?
|
14
36
|
return q.send(method, args.first)
|
15
37
|
elsif method.start_with?("find_by_")
|
16
|
-
attribute = method.gsub("find_by_", "")
|
17
|
-
cond[attribute] = args.first
|
18
|
-
return self.limit(1).where(cond, block)
|
38
|
+
# attribute = method.gsub("find_by_", "")
|
39
|
+
# cond[attribute] = args.first
|
40
|
+
# return self.limit(1).where(cond, block)
|
19
41
|
elsif method.start_with?("find_all_by_")
|
20
42
|
# attribute = method.gsub("find_all_by_", "")
|
21
43
|
# cond[attribute] = args.first
|
@@ -218,6 +240,7 @@ module Parsistence
|
|
218
240
|
fields.each do |field|
|
219
241
|
@includes << field
|
220
242
|
end
|
243
|
+
self
|
221
244
|
end
|
222
245
|
end
|
223
246
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# module Parsistence
|
2
|
+
# class Relation
|
3
|
+
# attr_accessor :PFRelation, :belongs_to, :klass
|
4
|
+
|
5
|
+
# def initialize(pf_relation)
|
6
|
+
# self.PFRelation = pf_relation
|
7
|
+
|
8
|
+
# end
|
9
|
+
|
10
|
+
# def fetch(&block)
|
11
|
+
# if self.belongs_to
|
12
|
+
# self.PFRelation.fetchIfNeededInBackgroundWithBlock do |result, error|
|
13
|
+
# if result
|
14
|
+
# result = self.klass.new(result)
|
15
|
+
# end
|
16
|
+
|
17
|
+
# block.call(result, error)
|
18
|
+
# end
|
19
|
+
# else
|
20
|
+
# self.PFRelation.
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
|
24
|
+
# def fetchAll(&block)
|
25
|
+
# self.fetch(block)
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
# end
|
data/lib/Parsistence/User.rb
CHANGED
@@ -6,6 +6,16 @@ module Parsistence
|
|
6
6
|
|
7
7
|
RESERVED_KEYS = [:objectId, :username, :password, :email]
|
8
8
|
|
9
|
+
def initialize(pf=nil)
|
10
|
+
if pf
|
11
|
+
self.PFObject = pf
|
12
|
+
else
|
13
|
+
self.PFObject = PFObject.objectWithClassName(self.class.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
9
19
|
def PFObject=(value)
|
10
20
|
@PFObject = value
|
11
21
|
@PFUser = @PFObject
|
@@ -21,7 +31,7 @@ module Parsistence
|
|
21
31
|
users = query.findObjects
|
22
32
|
users
|
23
33
|
end
|
24
|
-
|
34
|
+
|
25
35
|
def currentUser
|
26
36
|
PFUser.currentUser
|
27
37
|
end
|
data/lib/Parsistence/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Parsistence
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-09-
|
14
|
+
date: 2012-09-12 00:00:00.000000000 Z
|
15
15
|
dependencies: []
|
16
16
|
description: Your models on RubyMotion and Parse in a persistence.js style pattern.
|
17
17
|
email:
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- lib/Parsistence.rb
|
31
31
|
- lib/Parsistence/Model.rb
|
32
32
|
- lib/Parsistence/Query.rb
|
33
|
+
- lib/Parsistence/Relation.rb
|
33
34
|
- lib/Parsistence/User.rb
|
34
35
|
- lib/Parsistence/version.rb
|
35
36
|
homepage: https://github.com/clearsightstudio/Parsistence
|