motion_model 0.5.3 → 0.5.4

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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YmQ4MDAzNDMxNzQ2MDVhOWZkMDVhNjA0M2JhMWEwMGJmZWM4NTU1MQ==
5
- data.tar.gz: !binary |-
6
- M2UzM2UyYjcyY2JjOWUyMjNhZDRlZmQ1OGE0YTUzZDY5MzY2NDNmOA==
2
+ SHA1:
3
+ metadata.gz: 9fa1c9fe578bfec914279fad0ced2ff4f6df49a1
4
+ data.tar.gz: 9952292bdef965d7ab76ab1f8a8c906a2f69fd67
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZWUxMmM3OGU3ZWM5YzU5YTEwMzVmMWE3OWYwYmNkYzRkYzk2ZTRiM2UzZGYz
10
- ZGFiYTkyYzZiNGNlMjZjNmZlYThiMjM5YzRjNjQ1MTVmYWZhMzAwNGM0NDAy
11
- YjBjOWE0ZjU4NjAwNmRiMjE2OWRiNTFhNDZiZjU1OTM0NmI5ODU=
12
- data.tar.gz: !binary |-
13
- ODZiYjlkNTNhM2MyODBhYTdlN2RiM2I4ZDM4YTAxNGM3ZDk3Y2E3NzBhMjE4
14
- ZGZkZGFjNTcyYmRlZjRhM2ZjZjZkYjM0MGNhODdiZDc3YWEwMzIyNWI2NDli
15
- OTdmYTliODZkNTQ1MmU3YWFmNzQ5ZjRlZmQyZGI1ODk3Y2ZmYjU=
6
+ metadata.gz: 41cb26133a685d546300513985f57e41fa58b4b8eb678689311d2b23bfddb6d9394d66f6f849ad4faff27369f3f95945c1525dcd7fa0105dfd801812236f2c8f
7
+ data.tar.gz: 8a1a29e8a90468f7392b1c9f54281fa3038956ad8776be4e668d5286057fbc164af9d25ca6b59efefdf2b0eb0daedff3481506264d33e9831fc64a1105d70d41
data/README.md CHANGED
@@ -882,12 +882,17 @@ require "~/github/local/MotionModel/lib/motion_model.rb"
882
882
  The `~/github/local` is where I cloned it, but you can put it anyplace. Next, make
883
883
  sure you are following the project on GitHub so you know when there are changes.
884
884
 
885
- Submissions/Patches
885
+ Submissions/Patches/Bug Reports
886
886
  ------------------
887
887
 
888
- Obviously, the ideal patch request is really a pull request from your own fork, complete with passing
889
- specs.
888
+ For a submission, do this:
890
889
 
891
- Really, for a bug report, even a failing spec or some proposed code is fine. I really want to make
892
- this a decent tool for RubyMotion developers who need a straightforward data
893
- modeling and persistence framework.
890
+ 1. Fork it
891
+ 2. Create your feature branch (git checkout -b my-new-feature)
892
+ 3. Commit your changes (git commit -am 'Add some feature')
893
+ 4. Push to the branch (git push origin my-new-feature)
894
+ 5. Create new Pull Request
895
+
896
+ For a bug report, the best bet is follow the above steps, but for #2 and 4,
897
+ use the issue number in the branch. Once you have created the pull request,
898
+ reference it in the issue.
@@ -44,17 +44,24 @@ module MotionModel
44
44
  # will remember the file name, so they may omit that argument.
45
45
  #
46
46
  # Raises a +MotionModel::PersistFileFailureError+ on failure.
47
- def deserialize_from_file(file_name = nil)
47
+ def deserialize_from_file(file_name = nil, directory = nil)
48
48
  if schema_version != '1.0.0'
49
49
  migrate
50
50
  end
51
51
 
52
52
  @file_name = file_name if file_name
53
+ @file_path =
54
+ if directory.nil?
55
+ documents_file(@file_name)
56
+ else
57
+ File.join(directory, @file_name)
58
+ end
59
+
53
60
 
54
- if File.exist? documents_file(@file_name)
61
+ if File.exist? @file_path
55
62
  error_ptr = Pointer.new(:object)
56
63
 
57
- data = NSData.dataWithContentsOfFile(documents_file(@file_name), options:NSDataReadingMappedIfSafe, error:error_ptr)
64
+ data = NSData.dataWithContentsOfFile(@file_path, options:NSDataReadingMappedIfSafe, error:error_ptr)
58
65
 
59
66
  if data.nil?
60
67
  error = error_ptr[0]
@@ -78,12 +85,19 @@ module MotionModel
78
85
  # remembered file name.
79
86
  #
80
87
  # Raises a +MotionModel::PersistFileError+ on failure.
81
- def serialize_to_file(file_name = nil)
88
+ def serialize_to_file(file_name = nil, directory = nil)
82
89
  @file_name = file_name if file_name
90
+ @file_path =
91
+ if directory.nil?
92
+ documents_file(@file_name)
93
+ else
94
+ File.join(directory, @file_name)
95
+ end
96
+
83
97
  error_ptr = Pointer.new(:object)
84
98
 
85
99
  data = NSKeyedArchiver.archivedDataWithRootObject collection
86
- unless data.writeToFile(documents_file(@file_name), options: NSDataWritingAtomic, error: error_ptr)
100
+ unless data.writeToFile(@file_path, options: NSDataWritingAtomic, error: error_ptr)
87
101
  # De-reference the pointer.
88
102
  error = error_ptr[0]
89
103
 
@@ -92,7 +106,6 @@ module MotionModel
92
106
  end
93
107
  end
94
108
 
95
-
96
109
  def documents_file(file_name)
97
110
  file_path = File.join NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true), file_name
98
111
  file_path
data/motion/ext.rb CHANGED
@@ -300,45 +300,47 @@ class Debug
300
300
  @@silent = false
301
301
  @@colorize = true
302
302
 
303
- # Use silence if you want to keep messages from being echoed
304
- # to the console.
305
- def self.silence
306
- @@silent = true
307
- end
303
+ class << self
304
+ # Use silence if you want to keep messages from being echoed
305
+ # to the console.
306
+ def silence
307
+ @@silent = true
308
+ end
308
309
 
309
- def self.colorize
310
- @@colorize
311
- end
310
+ def colorize
311
+ @@colorize
312
+ end
312
313
 
313
- def self.colorize=(value)
314
- @@colorize = value == true
315
- end
314
+ def colorize=(value)
315
+ @@colorize = value == true
316
+ end
316
317
 
317
- # Use resume when you want messages that were silenced to
318
- # resume displaying.
319
- def self.resume
320
- @@silent = false
321
- end
318
+ # Use resume when you want messages that were silenced to
319
+ # resume displaying.
320
+ def resume
321
+ @@silent = false
322
+ end
322
323
 
323
- def self.put_message(type, message, color = Ansi.reset_color)
324
- open_color = @@colorize ? color : ''
325
- close_color = @@colorize ? Ansi.reset_color : ''
324
+ def put_message(type, message, color = Ansi.reset_color)
325
+ open_color = @@colorize ? color : ''
326
+ close_color = @@colorize ? Ansi.reset_color : ''
326
327
 
327
- NSLog("#{open_color}#{type} #{caller[1]}: #{message}#{close_color}") unless @@silent
328
- end
328
+ NSLog("#{open_color}#{type} #{caller[1]}: #{message}#{close_color}") unless @@silent
329
+ end
329
330
 
330
- def self.info(msg)
331
- put_message 'INFO', msg, Ansi.green_color
332
- end
331
+ def info(msg)
332
+ put_message 'INFO', msg, Ansi.green_color
333
+ end
334
+ alias :log :info
333
335
 
334
- def self.warning(msg)
335
- put_message 'WARNING', msg, Ansi.yellow_color
336
- end
336
+ def warning(msg)
337
+ put_message 'WARNING', msg, Ansi.yellow_color
338
+ end
337
339
 
338
- def self.error(msg)
339
- put_message 'ERROR', msg, Ansi.red_color
340
+ def error(msg)
341
+ put_message 'ERROR', msg, Ansi.red_color
342
+ end
340
343
  end
341
-
342
344
  end
343
345
 
344
346
  # These are C macros in iOS SDK. Not workable for Ruby.
@@ -106,6 +106,28 @@ module MotionModel
106
106
  end
107
107
  end
108
108
 
109
+ # Use at class level, as follows:
110
+ #
111
+ # class Task
112
+ # include MotionModel::Model
113
+ # include MotionModel::ArrayModelAdapter
114
+ #
115
+ # columns :name, :details, :assignees, :created_at, :updated_at
116
+ # has_many :assignees
117
+ # protects_remote_timestamps
118
+ #
119
+ # In this case, creating or updating will not alter the values of the
120
+ # timestamps, preferring to allow the server to be the only authority
121
+ # for assigning timestamp information.
122
+
123
+ def protect_remote_timestamps
124
+ @_protect_remote_timestamps = true
125
+ end
126
+
127
+ def protect_remote_timestamps?
128
+ @_protect_remote_timestamps == true
129
+ end
130
+
109
131
  # Use at class level, as follows:
110
132
  #
111
133
  # class Task
@@ -518,8 +540,10 @@ module MotionModel
518
540
 
519
541
  # Set created_at and updated_at fields
520
542
  def set_auto_date_field(field_name)
521
- method = "#{field_name}="
522
- self.send(method, Time.now) if self.respond_to?(method)
543
+ unless self.class.protect_remote_timestamps?
544
+ method = "#{field_name}="
545
+ self.send(method, Time.now) if self.respond_to?(method)
546
+ end
523
547
  end
524
548
 
525
549
  # Stub methods for hook protocols
@@ -792,7 +816,12 @@ module MotionModel
792
816
  when NilClass
793
817
  {column => value}
794
818
  when Proc
795
- {column => default.call}
819
+ begin
820
+ {column => default.call}
821
+ rescue Exception => ex
822
+ Debug.error "\n\nProblem initializing #{self.class} : #{column} with default and proc.\nException: #{ex.message}\nSorry, your app is pretty much crashing.\n"
823
+ exit
824
+ end
796
825
  when Symbol
797
826
  {column => self.send(column)}
798
827
  else
data/motion/version.rb CHANGED
@@ -4,5 +4,5 @@
4
4
  # or forward port their code to take advantage
5
5
  # of adapters.
6
6
  module MotionModel
7
- VERSION = "0.5.3"
7
+ VERSION = "0.5.4"
8
8
  end
@@ -238,5 +238,21 @@ describe "serialization of relations" do
238
238
  Parent.first.children.first.name.should == 'Fergie'
239
239
  Parent.first.dog.first.name.should == 'Fluffy'
240
240
  end
241
- end
242
241
 
242
+ it "allows to serialize and eserialize from directories" do
243
+ directory_path = '/Library/Caches'
244
+ Parent.serialize_to_file('parents.dat', directory_path)
245
+ Child.serialize_to_file('children.dat', directory_path)
246
+ Dog.serialize_to_file('dogs.dat', directory_path)
247
+ Parent.delete_all
248
+ Child.delete_all
249
+ Dog.delete_all
250
+ Parent.deserialize_from_file('parents.dat', directory_path)
251
+ Child.deserialize_from_file('children.dat', directory_path)
252
+ Dog.deserialize_from_file('dogs.dat', directory_path)
253
+ Parent.first.name.should == 'BoB'
254
+ Parent.first.children.count.should == 2
255
+ Parent.first.children.first.name.should == 'Fergie'
256
+ Parent.first.dog.first.name.should == 'Fluffy'
257
+ end
258
+ end
data/spec/date_spec.rb CHANGED
@@ -27,6 +27,14 @@ describe "time conversions" do
27
27
  :updated_at => :date
28
28
  end
29
29
 
30
+ class ProtectedUpdateable
31
+ include MotionModel::Model
32
+ include MotionModel::ArrayModelAdapter
33
+ columns :name => :string,
34
+ :updated_at => :date
35
+ protect_remote_timestamps
36
+ end
37
+
30
38
  it "Sets created_at when an item is created" do
31
39
  c = Creatable.new(:name => 'test')
32
40
  lambda{c.save}.should.change{c.created_at}
@@ -50,6 +58,12 @@ describe "time conversions" do
50
58
  lambda{ c.save }.should.change{c.updated_at}
51
59
  end
52
60
 
61
+ it "Honors (protects) server side timestamps" do
62
+ c = ProtectedUpdateable.create(:name => 'test')
63
+ sleep 1
64
+ c.name = 'test 1'
65
+ lambda{ c.save }.should.not.change{c.updated_at}
66
+ end
53
67
  end
54
68
 
55
69
  describe "parsing ISO8601 date formats" do
data/spec/model_spec.rb CHANGED
@@ -39,7 +39,7 @@ describe "Creating a model" do
39
39
  a_task = Task.new(:name => 'name', :details => 'details')
40
40
  a_task.name.should.equal('name')
41
41
  end
42
-
42
+
43
43
  it 'creates a model with all attributes even if some omitted' do
44
44
  atask = Task.create(:name => 'bob')
45
45
  atask.should.respond_to(:details)
@@ -177,14 +177,14 @@ describe "Creating a model" do
177
177
  1.upto(10) {|i| Task.create(:name => "task #{i}")}
178
178
  end
179
179
  end
180
-
180
+
181
181
  it 'deletes a row' do
182
182
  target = Task.find(:name).eq('task 3').first
183
183
  target.should.not == nil
184
184
  target.delete
185
185
  Task.find(:name).eq('task 3').count.should.equal 0
186
186
  end
187
-
187
+
188
188
  it 'deleting a row changes length' do
189
189
  target = Task.find(:name).eq('task 2').first
190
190
  lambda{target.delete}.should.change{Task.length}
@@ -198,7 +198,7 @@ describe "Creating a model" do
198
198
  Task.find(:name).eq('task 3').count.should.equal 1
199
199
  end
200
200
  end
201
-
201
+
202
202
  describe 'Handling Attribute Implementation' do
203
203
  it 'raises a NoMethodError exception when an unknown attribute it referenced' do
204
204
  task = Task.new
@@ -243,7 +243,7 @@ describe "Creating a model" do
243
243
  end
244
244
  end
245
245
  end
246
-
246
+
247
247
  describe 'defining custom attributes' do
248
248
  before do
249
249
  Task.delete_all
@@ -254,4 +254,49 @@ describe "Creating a model" do
254
254
  @task.custom_attribute_by_method.should == 'Feed the Cat - Get food, pour out'
255
255
  end
256
256
  end
257
+
258
+ describe 'protecting timestamps' do
259
+ class NoTimestamps
260
+ include MotionModel::Model
261
+ include MotionModel::ArrayModelAdapter
262
+ columns name: :string
263
+ protect_remote_timestamps
264
+ end
265
+
266
+ class AutoTimeable
267
+ include MotionModel::Model
268
+ include MotionModel::ArrayModelAdapter
269
+ columns name: :string,
270
+ created_at: :date,
271
+ updated_at: :date
272
+ end
273
+
274
+ class ProtectedTimestamps
275
+ include MotionModel::Model
276
+ include MotionModel::ArrayModelAdapter
277
+ columns name: :string,
278
+ created_at: :date,
279
+ updated_at: :date
280
+ protect_remote_timestamps
281
+ end
282
+
283
+ it 'does nothing to break classes with no timestamps' do
284
+ lambda{NoTimestamps.create!(name: 'no timestamps')}.should.not.raise
285
+ end
286
+
287
+ it "changes the timestamps if they are not protected" do
288
+ auto_timeable = AutoTimeable.new(name: 'auto timeable')
289
+ lambda{auto_timeable.name = 'changed auto timeable'; auto_timeable.save!}.should.change{auto_timeable.updated_at}
290
+ end
291
+
292
+ it "does not change created_at if timestamps are protected" do
293
+ protected_times = ProtectedTimestamps.new(name: 'auto timeable', created_at: Time.now, updated_at: Time.now)
294
+ lambda{protected_times.name = 'changed created at'; protected_times.save!}.should.not.change{protected_times.created_at}
295
+ end
296
+
297
+ it "does not change updated_at if timestamps are protected" do
298
+ protected_times = ProtectedTimestamps.new(name: 'auto timeable', created_at: Time.now, updated_at: Time.now)
299
+ lambda{protected_times.name = 'changed updated at'; protected_times.save!}.should.not.change{protected_times.updated_at}
300
+ end
301
+ end
257
302
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Ross
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-23 00:00:00.000000000 Z
11
+ date: 2014-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bubble-wrap
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.3.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.3.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: motion-support
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.1.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.1.0
41
41
  description: Simple model and validation mixins for RubyMotion
@@ -95,17 +95,17 @@ require_paths:
95
95
  - lib
96
96
  required_ruby_version: !ruby/object:Gem::Requirement
97
97
  requirements:
98
- - - ! '>='
98
+ - - '>='
99
99
  - !ruby/object:Gem::Version
100
100
  version: '0'
101
101
  required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  requirements:
103
- - - ! '>='
103
+ - - '>='
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  requirements: []
107
107
  rubyforge_project:
108
- rubygems_version: 2.2.2
108
+ rubygems_version: 2.3.0
109
109
  signing_key:
110
110
  specification_version: 4
111
111
  summary: Simple model and validation mixins for RubyMotion