motion_model 0.5.1 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTY0YmQxMmY0NmY3OWZmNjQ0M2ZkMGY0YTViOWEwZTE2N2JiZjM1YQ==
4
+ YmQ4MDAzNDMxNzQ2MDVhOWZkMDVhNjA0M2JhMWEwMGJmZWM4NTU1MQ==
5
5
  data.tar.gz: !binary |-
6
- YTU5OTViYjhmYzg5ODE0ZDUyNDM2M2QyMjNjYTNmMjZkYjM1MjJkNA==
6
+ M2UzM2UyYjcyY2JjOWUyMjNhZDRlZmQ1OGE0YTUzZDY5MzY2NDNmOA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZTg2NzFmZjdiODVhNjJiODk2YzRiOWQ5OTI4ZmZlYjU2MmQ2MjY2M2I5OWY1
10
- OWQzN2MyZWRiYmFjNTdmMzhlMTYwMzdkMDNkZWZjZDNmNjBhMTNhYzk5NGNh
11
- M2E5MTAyYTU0MzVmYmViMjIzN2ZiZmY2ZTE5MjU3YTM5ZjRkMDE=
9
+ ZWUxMmM3OGU3ZWM5YzU5YTEwMzVmMWE3OWYwYmNkYzRkYzk2ZTRiM2UzZGYz
10
+ ZGFiYTkyYzZiNGNlMjZjNmZlYThiMjM5YzRjNjQ1MTVmYWZhMzAwNGM0NDAy
11
+ YjBjOWE0ZjU4NjAwNmRiMjE2OWRiNTFhNDZiZjU1OTM0NmI5ODU=
12
12
  data.tar.gz: !binary |-
13
- MDI5Njc4YTVkYmZkMGY1YzkwMGJiNjI0NDM0MzdiMzQ3YjcwMDZiODBjZmQ4
14
- Y2Y0MDI1Y2Q1MTZjYTI3MjJmMmYwODI5YjExMGQ3NGE1MTA0YTQ5YzBmMTEz
15
- MmIyNjNhZjY1MDg0MmNlZTcwM2ZmNGYwZTljZmQyNGMxZTkzMjM=
13
+ ODZiYjlkNTNhM2MyODBhYTdlN2RiM2I4ZDM4YTAxNGM3ZDk3Y2E3NzBhMjE4
14
+ ZGZkZGFjNTcyYmRlZjRhM2ZjZjZkYjM0MGNhODdiZDc3YWEwMzIyNWI2NDli
15
+ OTdmYTliODZkNTQ1MmU3YWFmNzQ5ZjRlZmQyZGI1ODk3Y2ZmYjU=
@@ -1,5 +1,7 @@
1
1
  language: objective-c
2
- before_install: ruby --version
2
+ before_install:
3
+ - ruby --version
4
+ - sudo chown -R travis ~/Library/RubyMotion
3
5
  rvm:
4
6
  - "1.9.3"
5
7
  script: bundle exec rake spec
data/README.md CHANGED
@@ -167,6 +167,62 @@ class Task
167
167
  end
168
168
  ```
169
169
 
170
+ A note on defaults, you can specify a proc, block or symbol for your default if you want to get fancy. The most obvious use case for this is that Ruby will optimize the assignment of an array so that a default of `[]` always points to the same object. Not exactly what is intended. Wrapping this in a proc causes a new array to be created. Here's an example:
171
+
172
+ ```
173
+ class Foo
174
+ include MotionModel::Model
175
+ include MotionModel::ArrayModelAdapter
176
+ columns subject: { type: :array, default: ->{ [] } }
177
+ end
178
+ ```
179
+
180
+ This is not constrained to initializing arrays. You can
181
+ initialize pretty much anything using a proc or block.
182
+ If you are specifying a block, make sure to use begin/end
183
+ instead of do/end because it makes Ruby happy.
184
+
185
+ Here's a different example:
186
+
187
+ ```
188
+ class Timely
189
+ include MotionModel::Model
190
+ include MotionModel::ArrayModelAdapter
191
+ columns ended_run_at: { type: :time, default: ->{ Time.now } }
192
+ end
193
+ ```
194
+ Note that this uses the "stubby proc" syntax. That is pretty much equivalent
195
+ to:
196
+
197
+ ```
198
+ columns ended_run_at: { type: :time, default: lambda { Time.now } }
199
+ ```
200
+
201
+ for the previous example.
202
+
203
+ If you want to use a block, use the begin/end syntax:
204
+
205
+ ```
206
+ columns ended_run_at: { type: :time, default:
207
+ begin
208
+ Time.now
209
+ end
210
+ }
211
+ ```
212
+ Finally, you can have the default call some class method as follows:
213
+
214
+ ```
215
+ class Timely
216
+ include MotionModel::Model
217
+ include MotionModel::ArrayModelAdapter
218
+ columns unique_thingie: { type: :integer, default: :randomize }
219
+
220
+ def self.randomize
221
+ rand 1_000_000
222
+ end
223
+ end
224
+ ```
225
+
170
226
  You can also include the `Validatable` module to get field validation. For example:
171
227
 
172
228
  ```ruby
@@ -1,4 +1,6 @@
1
1
  module DateParser
2
+ @@isoDateFormatter = nil
3
+
2
4
  # Parse a date string: E.g.:
3
5
  #
4
6
  # DateParser.parse_date "There is a date in here tomorrow at 9:00 AM"
@@ -6,8 +8,7 @@ module DateParser
6
8
  # => 2013-02-20 09:00:00 -0800
7
9
  def self.parse_date(date_string)
8
10
  if date_string.match(/\d{2}T\d{2}/)
9
- # Discards fractional seconds.
10
- date_string = date_string.split('.').first if date_string =~ /\.\d{3}Z$/
11
+ return fractional_date(date_string) if date_string =~ /\.\d{3}Z$/
11
12
  return Time.iso8601(date_string)
12
13
  end
13
14
 
@@ -46,6 +47,17 @@ module DateParser
46
47
  detector = NSDataDetector.dataDetectorWithTypes(NSTextCheckingTypeDate, error:error)
47
48
  matches = detector.matchesInString(date_string, options:0, range:NSMakeRange(0, date_string.length))
48
49
  end
50
+
51
+ def self.allocate_date_formatter
52
+ @@isoDateFormatter = NSDateFormatter.alloc.init
53
+ @@isoDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ'"
54
+ end
55
+
56
+ def self.fractional_date(date_string)
57
+ allocate_date_formatter if @@isoDateFormatter.nil?
58
+ date = @@isoDateFormatter.dateFromString date_string
59
+ return date
60
+ end
49
61
  end
50
62
 
51
63
 
@@ -785,8 +785,40 @@ module MotionModel
785
785
  def unload_relation(col)
786
786
  end
787
787
 
788
+ def evaluate_default_value(column, value)
789
+ default = self.class.default(column)
790
+
791
+ case default
792
+ when NilClass
793
+ {column => value}
794
+ when Proc
795
+ {column => default.call}
796
+ when Symbol
797
+ {column => self.send(column)}
798
+ else
799
+ {column => default}
800
+ end
801
+ end
802
+
803
+ # issue #113. added ability to specify a proc or block
804
+ # for the default value. This allows for arrays to be
805
+ # created as unique. E.g.:
806
+ #
807
+ # class Foo
808
+ # include MotionModel::Model
809
+ # include MotionModel::ArrayModelAdapter
810
+ # columns subject: { type: :array, default: ->{ [] } }
811
+ # end
812
+ #
813
+ # ...
814
+ #
815
+ # This is not constrained to initializing arrays. You can
816
+ # initialize pretty much anything using a proc or block.
817
+ # If you are specifying a block, make sure to use begin/end
818
+ # instead of do/end because it makes Ruby happy.
819
+
788
820
  def initialize_data_columns(column, value) #nodoc
789
- self.attributes = {column => value || self.class.default(column)}
821
+ self.attributes = evaluate_default_value(column, value)
790
822
  end
791
823
 
792
824
  def column_as(col) #nodoc
@@ -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.1"
7
+ VERSION = "0.5.3"
8
8
  end
@@ -39,7 +39,6 @@ describe 'persistence' do
39
39
 
40
40
  PersistTask.serialize_to_file('test.dat')
41
41
  tasks = PersistTask.deserialize_from_file('test.dat')
42
- puts tasks.inspect
43
42
  PersistTask.first.created_at.should == created_at
44
43
  PersistTask.first.updated_at.should == updated_at
45
44
  end
@@ -74,5 +74,12 @@ describe "time conversions" do
74
74
  m.test_date.should.not.be.nil
75
75
  m.test_date.utc.to_s.should.eql '2012-04-23 18:25:43 UTC'
76
76
  end
77
+
78
+ it "does not discard fractional portion of ISO8601 dates" do
79
+ m = Model.new(test_date: '2012-04-23T18:25:43.511Z')
80
+ m.test_date.should.not.be.nil
81
+ m.test_date.utc.to_s.should.eql '2012-04-23 18:25:43 UTC'
82
+ m.test_date.utc.to_s.should.not.eql '2012-04-23 18:25:51 UTC'
83
+ end
77
84
  end
78
85
  end
@@ -0,0 +1,78 @@
1
+ describe "proc for defaults" do
2
+ describe "accepts a proc or block for default" do
3
+ describe "accepts proc" do
4
+ class AcceptsProc
5
+ include MotionModel::Model
6
+ include MotionModel::ArrayModelAdapter
7
+ columns subject: { type: :array, default: ->{ [] } }
8
+ end
9
+
10
+ before do
11
+ @test1 = AcceptsProc.create
12
+ @test2 = AcceptsProc.create
13
+ end
14
+
15
+ it "initializes array type using proc call" do
16
+ @test1.subject.should.be == @test2.subject
17
+ end
18
+ end
19
+
20
+ describe "accepts block" do
21
+ class AcceptsBlock
22
+ include MotionModel::Model
23
+ include MotionModel::ArrayModelAdapter
24
+ columns subject: {
25
+ type: :array, default: begin
26
+ []
27
+ end
28
+ }
29
+ end
30
+
31
+ before do
32
+ @test1 = AcceptsBlock.create
33
+ @test2 = AcceptsBlock.create
34
+ end
35
+
36
+ it "initializes array type using begin/end block call" do
37
+ @test1.subject.should.be == @test2.subject
38
+ end
39
+ end
40
+
41
+ describe "accepts symbol" do
42
+ class AcceptsSym
43
+ include MotionModel::Model
44
+ include MotionModel::ArrayModelAdapter
45
+ columns subject: { type: :integer, default: :randomize }
46
+
47
+ def self.randomize
48
+ rand 1_000_000
49
+ end
50
+ end
51
+
52
+ before do
53
+ @test1 = AcceptsSym.create
54
+ @test2 = AcceptsSym.create
55
+ end
56
+
57
+ it "initializes column by calling a method" do
58
+ @test1.subject.should.be == @test2.subject
59
+ end
60
+ end
61
+
62
+ describe "scalar defaults still work" do
63
+ class AcceptsScalars
64
+ include MotionModel::Model
65
+ include MotionModel::ArrayModelAdapter
66
+ columns subject: { type: :integer, default: 42 }
67
+ end
68
+
69
+ before do
70
+ @test1 = AcceptsScalars.create
71
+ end
72
+
73
+ it "initializes column as normal" do
74
+ @test1.subject.should == 42
75
+ end
76
+ end
77
+ end
78
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.3
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-03-20 00:00:00.000000000 Z
11
+ date: 2014-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bubble-wrap
@@ -55,7 +55,6 @@ files:
55
55
  - Rakefile
56
56
  - app/app_delegate.rb
57
57
  - lib/motion_model.rb
58
- - lib/motion_model/date_parser.rb
59
58
  - motion/adapters/array_finder_query.rb
60
59
  - motion/adapters/array_model_adapter.rb
61
60
  - motion/adapters/array_model_persistence.rb
@@ -83,6 +82,7 @@ files:
83
82
  - spec/model_hook_spec.rb
84
83
  - spec/model_spec.rb
85
84
  - spec/notification_spec.rb
85
+ - spec/proc_defaults_spec.rb
86
86
  - spec/relation_spec.rb
87
87
  - spec/transaction_spec.rb
88
88
  - spec/validation_spec.rb
@@ -105,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  version: '0'
106
106
  requirements: []
107
107
  rubyforge_project:
108
- rubygems_version: 2.1.10
108
+ rubygems_version: 2.2.2
109
109
  signing_key:
110
110
  specification_version: 4
111
111
  summary: Simple model and validation mixins for RubyMotion
@@ -123,6 +123,7 @@ test_files:
123
123
  - spec/model_hook_spec.rb
124
124
  - spec/model_spec.rb
125
125
  - spec/notification_spec.rb
126
+ - spec/proc_defaults_spec.rb
126
127
  - spec/relation_spec.rb
127
128
  - spec/transaction_spec.rb
128
129
  - spec/validation_spec.rb
@@ -1,66 +0,0 @@
1
- module DateParser
2
- # Parse a date string: E.g.:
3
- #
4
- # DateParser.parse_date "There is a date in here tomorrow at 9:00 AM"
5
- #
6
- # => 2013-02-20 09:00:00 -0800
7
- def self.parse_date(date_string)
8
- detect(date_string).first.date
9
- end
10
-
11
- # Parse time zone from date
12
- #
13
- # ateParser.parse_date "There is a date in here tomorrow at 9:00 AM EDT"
14
- #
15
- # Caveat: This is implemented per Apple documentation. I've never really
16
- # seen it work.
17
- def self.parse_time_zone(date_string)
18
- detect(date_string).first.timeZone
19
- end
20
-
21
- # Parse a date string: E.g.:
22
- #
23
- # SugarCube::DateParser.parse_date "You have a meeting from 9:00 AM to 3:00 PM"
24
- #
25
- # => 21600.0
26
- #
27
- # Divide by 3600.0 to get number of hours duration.
28
- def self.parse_duration(date_string)
29
- detect(date_string).first.send(:duration)
30
- end
31
-
32
- # Parse a date into a raw match array for further processing
33
- def self.match(date_string)
34
- detect(date_string)
35
- end
36
-
37
- private
38
- def self.detect(date_string)
39
- error = Pointer.new(:object)
40
- detector = NSDataDetector.dataDetectorWithTypes(NSTextCheckingTypeDate, error:error)
41
- matches = detector.matchesInString(date_string, options:0, range:NSMakeRange(0, date_string.length))
42
- end
43
- end
44
-
45
-
46
- class String
47
- # Use NSDataDetector to parse a string containing a date
48
- # or duration. These can be of the form:
49
- #
50
- # "tomorrow at 7:30 PM"
51
- # "11.23.2013"
52
- # "from 7:30 to 10:00 AM"
53
- #
54
- # etc.
55
- def to_date
56
- DateParser.parse_date(self)
57
- end
58
-
59
- def to_timezone
60
- DateParser.parse_time_zone(self)
61
- end
62
-
63
- def to_duration
64
- DateParser.parse_duration(self)
65
- end
66
- end