motion-prime 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/.travis.yml +6 -0
- data/Gemfile +5 -10
- data/Gemfile.lock +10 -7
- data/README.md +15 -7
- data/Rakefile +3 -2
- data/files/Gemfile +8 -1
- data/files/Rakefile +2 -0
- data/files/app/app_delegate.rb +10 -0
- data/files/app/config/base.rb +6 -0
- data/files/app/models/.gitkeep +0 -0
- data/files/app/screens/application_screen.rb +4 -0
- data/files/app/screens/help_screen.rb +5 -0
- data/files/app/screens/home_screen.rb +5 -0
- data/files/app/screens/sidebar_screen.rb +14 -0
- data/files/app/sections/sidebar/action.rb +5 -0
- data/files/app/sections/sidebar/table.rb +20 -0
- data/files/app/styles/sidebar.rb +38 -0
- data/files/resources/images/navigation/bg.png +0 -0
- data/files/resources/images/navigation/bg@2x.png +0 -0
- data/files/resources/images/navigation/button.png +0 -0
- data/files/resources/images/navigation/button@2x.png +0 -0
- data/lib/motion-prime.rb +1 -1
- data/motion-prime.gemspec +3 -0
- data/motion-prime/config/base.rb +8 -0
- data/motion-prime/config/config.rb +49 -0
- data/motion-prime/elements/draw/label.rb +1 -1
- data/motion-prime/models/association.rb +115 -0
- data/motion-prime/models/bag.rb +129 -0
- data/motion-prime/models/base.rb +15 -65
- data/motion-prime/models/errors.rb +3 -0
- data/motion-prime/models/finder.rb +189 -0
- data/motion-prime/models/json.rb +45 -0
- data/motion-prime/models/model.rb +118 -0
- data/motion-prime/models/store.rb +53 -0
- data/motion-prime/models/store_extension.rb +159 -0
- data/motion-prime/styles/{forms.rb → base.rb} +4 -0
- data/motion-prime/support/dm_view_controller.rb +1 -1
- data/motion-prime/version.rb +1 -1
- data/spec/config/store_spec.rb +73 -0
- data/spec/delegate/base_delegate_spec.rb +12 -0
- data/spec/helpers/base_delegate.rb +5 -0
- data/spec/helpers/base_screen.rb +9 -0
- data/spec/helpers/models.rb +53 -0
- data/spec/models/association_spec.rb +49 -0
- data/spec/models/bag_spec.rb +92 -0
- data/spec/models/base_model_spec.rb +158 -0
- data/spec/models/finder_spec.rb +183 -0
- data/spec/models/store_extension_spec.rb +120 -0
- data/spec/models/store_spec.rb +51 -0
- data/spec/screens/base_screen_spec.rb +77 -0
- metadata +84 -8
- data/lib/view_styler.rb +0 -141
- data/spec/main_spec.rb +0 -9
@@ -0,0 +1,118 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module ModelMethods
|
3
|
+
def save
|
4
|
+
raise StoreError, 'No store provided' unless self.store
|
5
|
+
|
6
|
+
error_ptr = Pointer.new(:id)
|
7
|
+
self.store.addObject(self, error: error_ptr)
|
8
|
+
raise StoreError, error_ptr[0].description if error_ptr[0]
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete
|
13
|
+
raise StoreError, 'No store provided' unless self.store
|
14
|
+
|
15
|
+
error_ptr = Pointer.new(:id)
|
16
|
+
self.store.removeObject(self, error: error_ptr)
|
17
|
+
raise StoreError, error_ptr[0].description if error_ptr[0]
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def store
|
22
|
+
super || self.class.store
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module ModelClassMethods
|
27
|
+
# Initialize a new object
|
28
|
+
#
|
29
|
+
# Examples:
|
30
|
+
# User.new(name: "Bob", age: 10)
|
31
|
+
#
|
32
|
+
# @return MotionPrime::BaseModel unsaved model
|
33
|
+
def new(data = {})
|
34
|
+
data.keys.each { |k|
|
35
|
+
unless self.attributes.member? k.to_sym
|
36
|
+
raise StoreError, "'#{k}' is not a defined attribute for this model"
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
object = self.nanoObjectWithDictionary(data)
|
41
|
+
object
|
42
|
+
end
|
43
|
+
|
44
|
+
# Initialize a new object and save it
|
45
|
+
#
|
46
|
+
# Examples:
|
47
|
+
# User.create(name: "Bob", age: 10)
|
48
|
+
#
|
49
|
+
# @return MotionPrime::BaseModel saved model
|
50
|
+
def create(data = {})
|
51
|
+
object = self.new(data)
|
52
|
+
object.save
|
53
|
+
end
|
54
|
+
|
55
|
+
# Define model attribute
|
56
|
+
#
|
57
|
+
# Examples:
|
58
|
+
# class User < MotionPrime::BaseModel
|
59
|
+
# attribute :name
|
60
|
+
# attribute :age
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# @return Nil
|
64
|
+
def attribute(name)
|
65
|
+
attributes << name
|
66
|
+
|
67
|
+
define_method(name) do |*args, &block|
|
68
|
+
self.info[name]
|
69
|
+
end
|
70
|
+
|
71
|
+
define_method((name + "=").to_sym) do |*args, &block|
|
72
|
+
self.info[name] = args[0]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return all model attribute names
|
77
|
+
#
|
78
|
+
# @return Array array of attribute names
|
79
|
+
def attributes(*attrs)
|
80
|
+
if attrs.size > 0
|
81
|
+
attrs.each{|attr| attribute attr}
|
82
|
+
else
|
83
|
+
@attributes ||= []
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return store associated with model class, or shared store by default
|
88
|
+
#
|
89
|
+
# @return MotionPrime::Store store
|
90
|
+
def store
|
91
|
+
@store ||= MotionPrime::Store.shared_store
|
92
|
+
end
|
93
|
+
|
94
|
+
# Define store associated with model class
|
95
|
+
#
|
96
|
+
# @param MotionPrime::Store store
|
97
|
+
# @return MotionPrime::Store store
|
98
|
+
def store=(store)
|
99
|
+
@store = store
|
100
|
+
end
|
101
|
+
|
102
|
+
# Count of models
|
103
|
+
#
|
104
|
+
# @return Fixnum count
|
105
|
+
def count
|
106
|
+
self.store.count(self)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Delete objects from store
|
110
|
+
#
|
111
|
+
# @param [Array, MotionPrime::BaseModel] objects to delete
|
112
|
+
# @return [Array] result
|
113
|
+
def delete(*args)
|
114
|
+
keys = find_keys(*args)
|
115
|
+
self.store.delete_keys(keys)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
motion_require '../config/base.rb'
|
2
|
+
module MotionPrime
|
3
|
+
class Store
|
4
|
+
def self.create(type = nil, path = nil)
|
5
|
+
error_ptr = Pointer.new(:id)
|
6
|
+
case type || MotionPrime::Config.model.store_type.to_sym
|
7
|
+
when :memory
|
8
|
+
store = NSFNanoStore.createAndOpenStoreWithType(NSFMemoryStoreType, path: nil, error: error_ptr)
|
9
|
+
when :temporary, :temp
|
10
|
+
store = NSFNanoStore.createAndOpenStoreWithType(NSFTemporaryStoreType, path: nil, error: error_ptr)
|
11
|
+
when :persistent, :file
|
12
|
+
path ||= begin
|
13
|
+
documents_path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0]
|
14
|
+
documents_path + "/nano.db"
|
15
|
+
end
|
16
|
+
store = NSFNanoStore.createAndOpenStoreWithType(NSFPersistentStoreType, path: path, error: error_ptr)
|
17
|
+
else
|
18
|
+
raise StoreError.new("unexpected store type (#{type}), must be one of: :memory, :temporary or :persistent")
|
19
|
+
end
|
20
|
+
|
21
|
+
raise StoreError, error_ptr[0].description if error_ptr[0]
|
22
|
+
store
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.connect!(type = nil)
|
26
|
+
self.shared_store = create(type)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.connect(type = nil)
|
30
|
+
connect!(type) unless connected?
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.connected?
|
34
|
+
!!shared_store
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.disconnect
|
38
|
+
self.shared_store = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.shared_store
|
42
|
+
@shared_store
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.shared_store=(store)
|
46
|
+
@shared_store = store
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.debug=(debug)
|
50
|
+
NSFSetIsDebugOn(debug)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
class NSFNanoStore
|
2
|
+
def engine
|
3
|
+
self.nanoStoreEngine
|
4
|
+
end
|
5
|
+
|
6
|
+
def changed?
|
7
|
+
self.hasUnsavedChanges
|
8
|
+
end
|
9
|
+
|
10
|
+
def save_interval=(interval)
|
11
|
+
self.setSaveInterval(interval)
|
12
|
+
end
|
13
|
+
|
14
|
+
## Open and Close store
|
15
|
+
|
16
|
+
def close
|
17
|
+
error_ptr = Pointer.new(:id)
|
18
|
+
closed = self.closeWithError(error_ptr)
|
19
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
20
|
+
closed
|
21
|
+
end
|
22
|
+
|
23
|
+
def open
|
24
|
+
error_ptr = Pointer.new(:id)
|
25
|
+
opened = self.openWithError(error_ptr)
|
26
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
27
|
+
opened
|
28
|
+
end
|
29
|
+
|
30
|
+
def closed?
|
31
|
+
self.isClosed
|
32
|
+
end
|
33
|
+
|
34
|
+
## Adding and Removing Objects
|
35
|
+
|
36
|
+
def <<(objects)
|
37
|
+
error_ptr = Pointer.new(:id)
|
38
|
+
if objects.is_a?(Array)
|
39
|
+
self.addObjectsFromArray(objects, error:error_ptr)
|
40
|
+
else
|
41
|
+
self.addObject(objects, error:error_ptr)
|
42
|
+
end
|
43
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def +(object)
|
48
|
+
error_ptr = Pointer.new(:id)
|
49
|
+
self.addObject(object, error:error_ptr)
|
50
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
# delete a object or array of objects from the array
|
55
|
+
def delete(objects)
|
56
|
+
error_ptr = Pointer.new(:id)
|
57
|
+
if objects.is_a?(Array)
|
58
|
+
result = self.removeObjectsInArray(objects, error:error_ptr)
|
59
|
+
else
|
60
|
+
result = self.removeObject(objects, error:error_ptr)
|
61
|
+
end
|
62
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
# Delete objects by keys
|
67
|
+
def delete_keys(keys)
|
68
|
+
error_ptr = Pointer.new(:id)
|
69
|
+
success = self.store.removeObjectsWithKeysInArray(keys, error: error_ptr)
|
70
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# delete all objects from store
|
76
|
+
def clear
|
77
|
+
error_ptr = Pointer.new(:id)
|
78
|
+
result = self.removeAllObjectsFromStoreAndReturnError(error_ptr)
|
79
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
80
|
+
result
|
81
|
+
end
|
82
|
+
|
83
|
+
# delete object with keys
|
84
|
+
# param: keys - array of key
|
85
|
+
def delete_keys(keys)
|
86
|
+
error_ptr = Pointer.new(:id)
|
87
|
+
result = self.removeObjectsWithKeysInArray(keys, error:error_ptr)
|
88
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
89
|
+
result
|
90
|
+
end
|
91
|
+
|
92
|
+
## Save and Maintenance
|
93
|
+
|
94
|
+
# Saves the uncommitted changes to the document store.
|
95
|
+
def save
|
96
|
+
error_ptr = Pointer.new(:id)
|
97
|
+
result = saveStoreAndReturnError(error_ptr)
|
98
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
99
|
+
result
|
100
|
+
end
|
101
|
+
|
102
|
+
# Discards the uncommitted changes that were added to the document store.
|
103
|
+
alias_method :discard, :discardUnsavedChanges
|
104
|
+
|
105
|
+
# Compact the database file size.
|
106
|
+
def compact
|
107
|
+
error_ptr = Pointer.new(:id)
|
108
|
+
result = self.compactStoreAndReturnError(error_ptr)
|
109
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
110
|
+
result
|
111
|
+
end
|
112
|
+
|
113
|
+
# Remove all indexes from the document store.
|
114
|
+
def clear_index
|
115
|
+
error_ptr = Pointer.new(:id)
|
116
|
+
result = self.clearIndexesAndReturnError(error_ptr)
|
117
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
118
|
+
result
|
119
|
+
end
|
120
|
+
|
121
|
+
# Recreate all indexes from the document store.
|
122
|
+
def rebuild_index
|
123
|
+
error_ptr = Pointer.new(:id)
|
124
|
+
result = self.rebuildIndexesAndReturnError(error_ptr)
|
125
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
# Makes a copy of the document store to a different location and optionally compacts it to its minimum size.
|
130
|
+
def save_store(path, compact=true)
|
131
|
+
error_ptr = Pointer.new(:id)
|
132
|
+
result = self.saveStoreToDirectoryAtPath(path, compactDatabase:compact, error:error_ptr)
|
133
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
134
|
+
result
|
135
|
+
end
|
136
|
+
|
137
|
+
# Count number of this class objects in store
|
138
|
+
def count(clazz)
|
139
|
+
self.countOfObjectsOfClassNamed(clazz.bare_class_name)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Create a transaction
|
143
|
+
def transaction
|
144
|
+
error_ptr = Pointer.new(:id)
|
145
|
+
beginTransactionAndReturnError(error_ptr)
|
146
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
147
|
+
|
148
|
+
begin
|
149
|
+
yield self
|
150
|
+
rescue StandardError => e
|
151
|
+
rollbackTransactionAndReturnError(error_ptr)
|
152
|
+
raise e
|
153
|
+
end
|
154
|
+
success = commitTransactionAndReturnError(error_ptr)
|
155
|
+
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
156
|
+
success
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
data/motion-prime/version.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
describe MotionPrime::Config do
|
2
|
+
before { @config = MotionPrime::Config.new }
|
3
|
+
|
4
|
+
describe "[]" do
|
5
|
+
before { @config = MotionPrime::Config.new(foo: "bar") }
|
6
|
+
|
7
|
+
it "returns the value if there is one" do
|
8
|
+
@config[:foo].should == "bar"
|
9
|
+
@config["foo"].should == "bar"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns a new Configatron::Store object if there is no value" do
|
13
|
+
@config[:unknown].is_a?(MotionPrime::Config).should == true
|
14
|
+
@config["unknown"].is_a?(MotionPrime::Config).should == true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "[]=" do
|
19
|
+
it "sets the value" do
|
20
|
+
@config[:foo] = "bar"
|
21
|
+
@config[:foo].should == "bar"
|
22
|
+
@config["foo"].should == "bar"
|
23
|
+
|
24
|
+
@config[:baz] = "bazzy"
|
25
|
+
@config[:baz].should == "bazzy"
|
26
|
+
@config["baz"].should == "bazzy"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "nil?" do
|
31
|
+
it "returns true if there is no value set" do
|
32
|
+
@config.foo.nil?.should == true
|
33
|
+
@config.foo = "bar"
|
34
|
+
@config.foo.nil?.should == false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "class methods" do
|
39
|
+
it "should allow to set value for class" do
|
40
|
+
MotionPrime::Config.foo.nil?.should == true
|
41
|
+
MotionPrime::Config.foo = "bar"
|
42
|
+
MotionPrime::Config.foo.should == "bar"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "has_key?" do
|
47
|
+
it "returns true if there is a key" do
|
48
|
+
@config.has_key?(:foo).should == false
|
49
|
+
@config.foo = "bar"
|
50
|
+
@config.has_key?(:foo).should == true
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns false if the key is a MotionPrime::Config" do
|
54
|
+
@config.has_key?(:foo).should == false
|
55
|
+
@config.foo = MotionPrime::Config.new
|
56
|
+
@config.has_key?(:foo).should == false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "configuring with a block" do
|
61
|
+
before do
|
62
|
+
@config.a.b = 'B'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "yields the store to configure" do
|
66
|
+
@config.a do |a|
|
67
|
+
a.c = 'C'
|
68
|
+
end
|
69
|
+
@config.a.b.should == 'B'
|
70
|
+
@config.a.c.should == 'C'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
describe "base delegate" do
|
2
|
+
|
3
|
+
before { @subject = BaseDelegate.new }
|
4
|
+
|
5
|
+
it 'should call on_load on launch' do
|
6
|
+
@subject.mock!(:on_load) do |app, options|
|
7
|
+
app.should.be.kind_of(UIApplication)
|
8
|
+
end
|
9
|
+
|
10
|
+
@subject.application(UIApplication.sharedApplication, didFinishLaunchingWithOptions: {})
|
11
|
+
end
|
12
|
+
end
|