Parsistence 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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).fetch do |cars, error|
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
- **eq:** Check if equal the passed in values.
70
-
71
- **notEq:** Check if NOT equal to the passed in values.
72
-
73
- **gt:** Check if greater than the passed in values.
74
-
75
- **lt:** Check if less than the passed in values.
76
-
77
- **gte:** Check if greater or equal to than the passed in values.
78
-
79
- **lte:** Check if less than or equal to the passed in values.
80
-
81
- **order:** Order by one or more fields. Specify :asc or :desc.
82
-
83
- **limit:** Limit is slightly different...it takes either one argument (limit) or two (offset, limit).
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
- relations :author
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|
@@ -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
- if fields.include?(method)
29
- return getField(method)
30
- elsif fields.map { |f| "#{f}=".include?(method)}
31
- method = method.split("=")[0]
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
- elsif relations.include?(method)
31
+ # Getters
32
+ elsif relations.include? method
34
33
  return getRelation(method)
35
- elsif relations.map {|r| "#{r}=".include?(method)}
36
- method = method.split("=")[0]
37
- return setRelation(method, args.first)
38
- elsif @PFObject.respond_to?(method)
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
- return @PFObject.objectForKey(field) if relations.include? field.to_sym
68
- raise "Parsistence Exception: Invalid relation name #{field} for object #{self.class.to_s}"
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
- # return setRelation(field, value) # This SHOULD work
74
-
75
- relation = @PFObject.relationforKey(field)
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
- return relation.addObject(value) if relations.include? field.to_sym
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 self.respond_to? "#{k}="
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
- saved = @PFObject.save
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(:get_presenceValidations)
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
- @errors[field] = "#{field} can't be blank" if presenceValidations.include?(field) && value.nil? || value == ""
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 validates_presence_of(*args)
160
- args.each {|arg| validate_presence(arg)}
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 get_presenceValidations
164
- @presenceValidations ||= []
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)
@@ -1,21 +1,43 @@
1
1
  module Parsistence
2
2
  module Model
3
3
  module ClassMethods
4
- QUERY_STUBS = [ :fetch, :where, :first, :limit, :order, :eq, :notEq, :lt, :gt, :lte, :gte ] # :limit is different
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
- return self.limit(args.first) if args.length == 1
9
- return self.limit(args.first, args.last)
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 block
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Parsistence
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
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.2.1
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-05 00:00:00.000000000 Z
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