PackingPeanut 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +34 -3
- data/lib/PackingPeanut-android/PackingPeanut.rb +92 -87
- data/lib/PackingPeanut-ios/PackingPeanut.rb +54 -51
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12ff5130d11697ea17d75fb51296fc420846c8b7
|
4
|
+
data.tar.gz: 87951bc7c2fb7f9182531bba0594ecaff8173ad1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94326ee0e5896786cfeb0b73b9ab7426b47ee73a36391d1c435e543db1fb289b13e1787c4a17a743dec1f5368d55e5b3a83b2a5b8a451c1cea0f831a240b5cd2
|
7
|
+
data.tar.gz: 7e8fdc3f22364045d489abedcbfea00a5d0a13c38000a10260d3db441da6382bed2097e071607bfc300e2e881b3de86c8a6e2e8ac88f9965980737d2f0d1181c
|
data/README.md
CHANGED
@@ -32,9 +32,9 @@ App::Persistence[:foo] = true
|
|
32
32
|
```
|
33
33
|
|
34
34
|
Whirlwind Tour via the REPL
|
35
|
-
```
|
35
|
+
```ruby
|
36
36
|
# ONLY ANDROID REQUIRES CONTEXT!
|
37
|
-
#
|
37
|
+
# See the section on Android context for more info
|
38
38
|
$ App::Persistence.context = self
|
39
39
|
=> #<MainActivity:0x1d20058e>
|
40
40
|
$ App::Persistence['dinner'] = "nachos"
|
@@ -48,11 +48,19 @@ $ App::Persistence.all
|
|
48
48
|
$ App::Persistence.storage_file = "some_new_file"
|
49
49
|
=> "some_new_file"
|
50
50
|
$ App::Persistence['dinner']
|
51
|
-
=>
|
51
|
+
=> nil # empty because we're now outside the default storage file.
|
52
|
+
```
|
52
53
|
|
54
|
+
Friendly aliases:
|
55
|
+
```ruby
|
53
56
|
# You can use PP instead of App::Persistence if you like
|
54
57
|
$ PP['some_boolean'] = true
|
58
|
+
# You can use PackingPeanut (true name) if you like
|
59
|
+
$ PackingPeanut['so_easy'] = true
|
60
|
+
```
|
55
61
|
|
62
|
+
Access deeper features:
|
63
|
+
```ruby
|
56
64
|
# On Android you can set prefrence_modes for cross/app communication
|
57
65
|
$ App::Persistence.preference_mode = :world_readable
|
58
66
|
=> :world_readable
|
@@ -85,6 +93,29 @@ Adding [Darin's moran gem](https://github.com/darinwilson/moran) allowed seriali
|
|
85
93
|
* **iOS:** Yup!
|
86
94
|
* **Android:** Boy that would be nice wouldn't it?
|
87
95
|
|
96
|
+
## PackingPeanut Alongside Bubblewrap on iOS?
|
97
|
+
It's meant to look just like BubbleWrap, not fight with it. If you include the BubbleWrap library, PackingPeanut will gracefully bow out of the App::Persistence namespace. You can still access PackingPeanut with `PP` or `PackingPeanut`.
|
98
|
+
|
99
|
+
## Explain this Android `context` _thing_ Again
|
100
|
+
Just like a conversation taken out of context can be confusing, Android has a lot of moving parts and requires just about EVERYTHING that would be a lib component to understand the context. When accessing persistent data, context is required. You can easily handle this by giving PackingPeanut your application context in your Application startup file.
|
101
|
+
|
102
|
+
PackingPeanut Context Examples:
|
103
|
+
```ruby
|
104
|
+
# Providing Context - Regular
|
105
|
+
class MyApplication < Android::App::Application
|
106
|
+
def onCreate
|
107
|
+
PP.context = self
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Providing Context with BluePotion
|
112
|
+
class MyApplication < PMApplication
|
113
|
+
def on_create
|
114
|
+
PP.context = self
|
115
|
+
end
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
88
119
|
## Contributing
|
89
120
|
|
90
121
|
1. Fork it
|
@@ -1,105 +1,110 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def [](key)
|
36
|
-
# Let's play nice with strings and non-strings
|
37
|
-
string_key = key.to_s
|
38
|
-
json_string = get_value(string_key)
|
39
|
-
return json_string if json_string == ""
|
40
|
-
deserialize(string_key, json_string)
|
41
|
-
end
|
1
|
+
module PackingPeanut
|
2
|
+
|
3
|
+
MODE_PRIVATE = 0
|
4
|
+
MODE_WORLD_READABLE = 1
|
5
|
+
MODE_WORLD_WRITEABLE = 2
|
6
|
+
MODE_MULTI_PROCESS = 4
|
7
|
+
|
8
|
+
JSONObject = Org::Json::JSONObject
|
9
|
+
|
10
|
+
PREFERENCE_MODES = {
|
11
|
+
private: MODE_PRIVATE,
|
12
|
+
readable: MODE_WORLD_READABLE,
|
13
|
+
world_readable: MODE_WORLD_READABLE,
|
14
|
+
writable: MODE_WORLD_WRITEABLE,
|
15
|
+
world_writable: MODE_WORLD_WRITEABLE,
|
16
|
+
multi: MODE_MULTI_PROCESS,
|
17
|
+
multi_process: MODE_MULTI_PROCESS
|
18
|
+
}
|
19
|
+
|
20
|
+
module_function
|
21
|
+
|
22
|
+
# Serialize key/value as json then
|
23
|
+
# store that string with the settings key == json key
|
24
|
+
def []=(key, value)
|
25
|
+
# Let's play nice with strings and non-strings
|
26
|
+
string_key = key.to_s
|
27
|
+
settings = get_settings
|
28
|
+
editor = settings.edit
|
29
|
+
json = serialize(string_key,value)
|
30
|
+
editor.putString(string_key, json.toString)
|
31
|
+
editor.commit
|
32
|
+
end
|
42
33
|
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
def [](key)
|
35
|
+
# Let's play nice with strings and non-strings
|
36
|
+
string_key = key.to_s
|
37
|
+
json_string = get_value(string_key)
|
38
|
+
return nil if json_string == ""
|
39
|
+
deserialize(string_key, json_string)
|
40
|
+
end
|
46
41
|
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
def serialize(key, value)
|
43
|
+
Moran.generate({:"#{key}" => value})
|
44
|
+
end
|
50
45
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
46
|
+
def deserialize(key, json_string)
|
47
|
+
Moran.parse(json_string)[key]
|
48
|
+
end
|
55
49
|
|
56
|
-
|
57
|
-
|
58
|
-
|
50
|
+
def get_value key
|
51
|
+
settings = get_settings
|
52
|
+
settings.getString(key,nil)
|
53
|
+
end
|
59
54
|
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
def storage_file=(value)
|
56
|
+
@persistence_storage_file = value
|
57
|
+
end
|
63
58
|
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
def storage_file
|
60
|
+
@persistence_storage_file ||= "default_persistence_file"
|
61
|
+
end
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
def preference_mode=(value)
|
64
|
+
@current_preference_mode = PREFERENCE_MODES[value] || value
|
65
|
+
end
|
71
66
|
|
72
|
-
|
73
|
-
|
74
|
-
|
67
|
+
def preference_mode
|
68
|
+
@current_preference_mode ||= MODE_PRIVATE
|
69
|
+
end
|
75
70
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
merged_hashes = merged_hashes.merge(h)
|
80
|
-
end
|
71
|
+
def all
|
72
|
+
settings = get_settings
|
73
|
+
all_hashes = settings.getAll.map { |key, value| Moran.parse(value) }
|
81
74
|
|
82
|
-
|
75
|
+
# Currently an array of hashes, needs to be one big hash
|
76
|
+
merged_hashes = {}
|
77
|
+
all_hashes.each do |h|
|
78
|
+
merged_hashes = merged_hashes.merge(h)
|
83
79
|
end
|
84
80
|
|
85
|
-
|
86
|
-
|
87
|
-
end
|
81
|
+
merged_hashes
|
82
|
+
end
|
88
83
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
@context || getApplicationContext
|
94
|
-
end
|
84
|
+
def get_settings
|
85
|
+
raise "[PackingPeanut] Fatal Error - You must set the context before accessing persistent data." unless @context
|
86
|
+
current_context.getSharedPreferences(storage_file, preference_mode)
|
87
|
+
end
|
95
88
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
89
|
+
# Allows us to use this from anywhere by setting the context
|
90
|
+
# Useful when you want to access this module from the REPL
|
91
|
+
def current_context
|
92
|
+
# THIS SHOULD HAVE SAFE FAILOVERS
|
93
|
+
# BUT defined? is causing erros in RMA native methods as of this commit
|
94
|
+
@context
|
95
|
+
end
|
100
96
|
|
97
|
+
# attr_accessor is not supported for modules in RMAndroid... yet.
|
98
|
+
def context= supplied_context
|
99
|
+
@context = supplied_context
|
101
100
|
end
|
101
|
+
|
102
102
|
end
|
103
103
|
|
104
|
-
# delicious shortcut
|
105
|
-
PP =
|
104
|
+
# delicious PP shortcut
|
105
|
+
PP = PackingPeanut unless defined? PP
|
106
|
+
|
107
|
+
# Bubblewrap syntax
|
108
|
+
module App
|
109
|
+
Persistence = PackingPeanut unless defined? App::Persistence
|
110
|
+
end
|
@@ -1,68 +1,71 @@
|
|
1
1
|
# Persistence module built on top of NSUserDefaults
|
2
|
-
module
|
3
|
-
|
4
|
-
module_function
|
2
|
+
module PackingPeanut
|
3
|
+
module_function
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def app_key
|
6
|
+
@app_key ||= NSBundle.mainBundle.bundleIdentifier
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def storage_file
|
10
|
+
@persistence_storage_file ||= "default_persistence_file"
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def storage_file=(value)
|
14
|
+
@persistence_storage_file = value
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def []=(key, value)
|
18
|
+
storage.setObject(value, forKey: storage_key(key))
|
19
|
+
storage.synchronize
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
22
|
+
def [](key)
|
23
|
+
value = storage.objectForKey storage_key(key)
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
# RubyMotion currently has a bug where the strings returned from
|
26
|
+
# standardUserDefaults are missing some methods (e.g. to_data).
|
27
|
+
# And because the returned object is slightly different than a normal
|
28
|
+
# String, we can't just use `value.is_a?(String)`
|
29
|
+
value.class.to_s == 'String' ? value.dup : value
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
storage.synchronize
|
32
|
+
def merge(values)
|
33
|
+
values.each do |key, value|
|
34
|
+
storage.setObject(value, forKey: storage_key(key))
|
38
35
|
end
|
36
|
+
storage.synchronize
|
37
|
+
end
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
def delete(key)
|
40
|
+
value = storage.objectForKey storage_key(key)
|
41
|
+
storage.removeObjectForKey(storage_key(key))
|
42
|
+
storage.synchronize
|
43
|
+
value
|
44
|
+
end
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
def storage
|
47
|
+
NSUserDefaults.standardUserDefaults
|
48
|
+
end
|
50
49
|
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
def storage_key(key)
|
51
|
+
"#{app_key}_#{storage_file}_#{key}"
|
52
|
+
end
|
54
53
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
new_hash
|
54
|
+
def all
|
55
|
+
hash = storage.dictionaryRepresentation.select{|k,v| k.start_with?("#{app_key}_#{storage_file}") }
|
56
|
+
new_hash = {}
|
57
|
+
hash.each do |k,v|
|
58
|
+
new_hash[k.sub("#{app_key}_#{storage_file}_", '')] = v
|
62
59
|
end
|
60
|
+
new_hash
|
63
61
|
end
|
64
|
-
|
65
62
|
end
|
66
63
|
|
67
|
-
|
68
|
-
|
64
|
+
|
65
|
+
# delicious PP shortcut
|
66
|
+
PP = PackingPeanut unless defined? PP
|
67
|
+
|
68
|
+
# Bubblewrap syntax
|
69
|
+
module App
|
70
|
+
Persistence = PackingPeanut unless defined? App::Persistence
|
71
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: PackingPeanut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gant
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|