PackingPeanut 1.0.0 → 1.1.0
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 +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
|