PackingPeanut 0.0.3 → 1.0.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 +28 -15
- data/lib/{project → PackingPeanut-android}/PackingPeanut.rb +24 -12
- data/lib/PackingPeanut-ios/PackingPeanut.rb +68 -0
- data/lib/PackingPeanut-ios/ns_user_defaults.rb +15 -0
- data/lib/PackingPeanut.rb +26 -6
- metadata +36 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2f04de5df63f75fb232e267e56ce3f33bc0eefb
|
4
|
+
data.tar.gz: 9ad3ba2c1db95ad649252daa5a85c7c786d12419
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fc18eab2b1d752c17d3c8f78df711e4f53fe66ecdf8bb94940b457c8d8be0adbfe857eda9822b69b526857cc3d90c9b21f831e57bb46ea312b4a14b8812c001
|
7
|
+
data.tar.gz: b752f132729c59c907d92b1f075bcff4aee493cfe8a35b519303c3a59c190612f2cfc3650204602209d777faec73722f181c04cb29c567e8e9129468d23c76a3
|
data/README.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# ![PackingPeanut Logo](./_art/logo_100.png) PackingPeanut [![Gem Version](https://badge.fury.io/rb/PackingPeanut.svg)](http://badge.fury.io/rb/PackingPeanut)
|
2
2
|
|
3
|
-
|
3
|
+
### Cross Platform App Persistence
|
4
|
+
![cross platform rubymotion gem](./_art/both_icon.png)
|
4
5
|
|
5
|
-
|
6
|
+
Inspired by BubbleWrap's easy syntax for App Persistence - Now a CROSS PLATFORM App Persistence Gem for RubyMotion.
|
7
|
+
|
8
|
+
There is a sedulous effort to make this syntax fit BubbleWrap's as much as possible for easy replacement :smiling_imp:
|
6
9
|
|
7
10
|
[**GITHUB HOMEPAGE**](http://gantman.github.io/PackingPeanut/)
|
8
11
|
|
@@ -16,6 +19,10 @@ There is a sedulous effort to make this syntax fit BubbleWrap's as much as possi
|
|
16
19
|
|
17
20
|
$ bundle
|
18
21
|
|
22
|
+
**Step 3:** IF on Android:
|
23
|
+
|
24
|
+
$ [bundle exec] rake gradle:install
|
25
|
+
|
19
26
|
## Usage
|
20
27
|
|
21
28
|
**It's as simple as:**
|
@@ -26,32 +33,34 @@ App::Persistence[:foo] = true
|
|
26
33
|
|
27
34
|
Whirlwind Tour via the REPL
|
28
35
|
```
|
29
|
-
#
|
30
|
-
#
|
36
|
+
# ONLY ANDROID REQUIRES CONTEXT!
|
37
|
+
# Set the context (required in the REPL or when not including the module).
|
31
38
|
$ App::Persistence.context = self
|
32
39
|
=> #<MainActivity:0x1d20058e>
|
33
40
|
$ App::Persistence['dinner'] = "nachos"
|
34
|
-
=>
|
35
|
-
$ App::Persistence['dinner']
|
41
|
+
=> "nachos"
|
42
|
+
$ App::Persistence['dinner']
|
36
43
|
=> "nachos"
|
37
44
|
$ App::Persistence[:lunch] = "tacos"
|
38
45
|
=> "tacos" # Use symbols or strings as you please
|
39
46
|
$ App::Persistence.all
|
40
|
-
=>
|
47
|
+
=> {"dinner"=>"nachos", "lunch"=>"tacos"}
|
41
48
|
$ App::Persistence.storage_file = "some_new_file"
|
42
49
|
=> "some_new_file"
|
43
50
|
$ App::Persistence['dinner']
|
44
51
|
=> "" # empty because we're now outside the default storage file.
|
45
|
-
$ App::Persistence.preference_mode = :world_readable
|
46
|
-
=> :world_redable
|
47
|
-
$ PP::Persistence['some_boolean'] = true #You can use PP instead of App if you like
|
48
|
-
```
|
49
52
|
|
53
|
+
# You can use PP instead of App::Persistence if you like
|
54
|
+
$ PP['some_boolean'] = true
|
50
55
|
|
56
|
+
# On Android you can set prefrence_modes for cross/app communication
|
57
|
+
$ App::Persistence.preference_mode = :world_readable
|
58
|
+
=> :world_readable
|
59
|
+
```
|
51
60
|
|
52
61
|
## What are preference modes?
|
53
62
|
|
54
|
-
Preference Modes are
|
63
|
+
Preference Modes are Android Operating modes, used to control permission levels on the persistence file.
|
55
64
|
|
56
65
|
Memorizable symbols and their corresponding constants:
|
57
66
|
```ruby
|
@@ -66,11 +75,15 @@ Memorizable symbols and their corresponding constants:
|
|
66
75
|
}
|
67
76
|
```
|
68
77
|
|
69
|
-
|
70
|
-
|
78
|
+
Use 0 or MODE_PRIVATE for the default operation, MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE for more permissive modes. The bit MODE_MULTI_PROCESS can also be used if multiple processes are mutating the same SharedPreferences file. MODE_MULTI_PROCESS is always on in apps targeting Gingerbread (Android 2.3) and below, and off by default in later versions.
|
79
|
+
|
80
|
+
## Dependencies
|
81
|
+
Adding [Darin's moran gem](https://github.com/darinwilson/moran) allowed serialization of hashes for Android. This means `motion-gradle` is also necessary for complete Packing Peanut excellence on Android.
|
71
82
|
|
72
83
|
## Tests?
|
73
|
-
|
84
|
+
|
85
|
+
* **iOS:** Yup!
|
86
|
+
* **Android:** Boy that would be nice wouldn't it?
|
74
87
|
|
75
88
|
## Contributing
|
76
89
|
|
@@ -23,27 +23,29 @@ module App
|
|
23
23
|
# Serialize key/value as json then
|
24
24
|
# store that string with the settings key == json key
|
25
25
|
def []=(key, value)
|
26
|
+
# Let's play nice with strings and non-strings
|
27
|
+
string_key = key.to_s
|
26
28
|
settings = get_settings
|
27
29
|
editor = settings.edit
|
28
|
-
json = serialize(
|
29
|
-
editor.putString(
|
30
|
-
editor.commit
|
30
|
+
json = serialize(string_key,value)
|
31
|
+
editor.putString(string_key, json.toString)
|
32
|
+
editor.commit
|
31
33
|
end
|
32
34
|
|
33
35
|
def [](key)
|
34
|
-
|
36
|
+
# Let's play nice with strings and non-strings
|
37
|
+
string_key = key.to_s
|
38
|
+
json_string = get_value(string_key)
|
35
39
|
return json_string if json_string == ""
|
36
|
-
deserialize(
|
40
|
+
deserialize(string_key, json_string)
|
37
41
|
end
|
38
42
|
|
39
43
|
def serialize(key, value)
|
40
|
-
|
41
|
-
json.put(key, value)
|
44
|
+
Moran.generate({:"#{key}" => value})
|
42
45
|
end
|
43
46
|
|
44
47
|
def deserialize(key, json_string)
|
45
|
-
|
46
|
-
json.get(key)
|
48
|
+
Moran.parse(json_string)[key]
|
47
49
|
end
|
48
50
|
|
49
51
|
def get_value key
|
@@ -69,7 +71,15 @@ module App
|
|
69
71
|
|
70
72
|
def all
|
71
73
|
settings = get_settings
|
72
|
-
settings.getAll.map { |key, value|
|
74
|
+
all_hashes = settings.getAll.map { |key, value| Moran.parse(value) }
|
75
|
+
|
76
|
+
# Currently an array of hashes, needs to be one big hash
|
77
|
+
merged_hashes = {}
|
78
|
+
all_hashes.each do |h|
|
79
|
+
merged_hashes = merged_hashes.merge(h)
|
80
|
+
end
|
81
|
+
|
82
|
+
merged_hashes
|
73
83
|
end
|
74
84
|
|
75
85
|
def get_settings
|
@@ -79,15 +89,17 @@ module App
|
|
79
89
|
# Allows us to use this from anywhere by setting the context
|
80
90
|
# Useful when you want to access this module from the REPL
|
81
91
|
def current_context
|
92
|
+
#p defined? getApplicationContext
|
82
93
|
@context || getApplicationContext
|
83
94
|
end
|
84
95
|
|
85
96
|
# attr_accessor is not supported for modules in RMAndroid... yet.
|
86
|
-
def context= supplied_context
|
97
|
+
def context= supplied_context
|
87
98
|
@context = supplied_context
|
88
99
|
end
|
89
100
|
|
90
101
|
end
|
91
102
|
end
|
92
103
|
|
93
|
-
|
104
|
+
# delicious shortcut
|
105
|
+
PP = App::Persistence unless defined? PP
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Persistence module built on top of NSUserDefaults
|
2
|
+
module App
|
3
|
+
module Persistence
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def app_key
|
7
|
+
@app_key ||= NSBundle.mainBundle.bundleIdentifier
|
8
|
+
end
|
9
|
+
|
10
|
+
def storage_file
|
11
|
+
@persistence_storage_file ||= "default_persistence_file"
|
12
|
+
end
|
13
|
+
|
14
|
+
def storage_file=(value)
|
15
|
+
@persistence_storage_file = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
storage.setObject(value, forKey: storage_key(key))
|
20
|
+
storage.synchronize
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](key)
|
24
|
+
value = storage.objectForKey storage_key(key)
|
25
|
+
|
26
|
+
# RubyMotion currently has a bug where the strings returned from
|
27
|
+
# standardUserDefaults are missing some methods (e.g. to_data).
|
28
|
+
# And because the returned object is slightly different than a normal
|
29
|
+
# String, we can't just use `value.is_a?(String)`
|
30
|
+
value.class.to_s == 'String' ? value.dup : value
|
31
|
+
end
|
32
|
+
|
33
|
+
def merge(values)
|
34
|
+
values.each do |key, value|
|
35
|
+
storage.setObject(value, forKey: storage_key(key))
|
36
|
+
end
|
37
|
+
storage.synchronize
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete(key)
|
41
|
+
value = storage.objectForKey storage_key(key)
|
42
|
+
storage.removeObjectForKey(storage_key(key))
|
43
|
+
storage.synchronize
|
44
|
+
value
|
45
|
+
end
|
46
|
+
|
47
|
+
def storage
|
48
|
+
NSUserDefaults.standardUserDefaults
|
49
|
+
end
|
50
|
+
|
51
|
+
def storage_key(key)
|
52
|
+
"#{app_key}_#{storage_file}_#{key}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def all
|
56
|
+
hash = storage.dictionaryRepresentation.select{|k,v| k.start_with?("#{app_key}_#{storage_file}") }
|
57
|
+
new_hash = {}
|
58
|
+
hash.each do |k,v|
|
59
|
+
new_hash[k.sub("#{app_key}_#{storage_file}_", '')] = v
|
60
|
+
end
|
61
|
+
new_hash
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# delicious shortcut
|
68
|
+
PP = App::Persistence unless defined? PP
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Reopens the NSUserDefaults class to add Array like accessors
|
2
|
+
# @see https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/nsuserdefaults_Class/Reference/Reference.html
|
3
|
+
class NSUserDefaults
|
4
|
+
|
5
|
+
# Retrieves the object for the passed key
|
6
|
+
def [](key)
|
7
|
+
self.objectForKey(key.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Sets the value for a given key and save it right away.
|
11
|
+
def []=(key, val)
|
12
|
+
self.setObject(val, forKey: key.to_s)
|
13
|
+
self.synchronize
|
14
|
+
end
|
15
|
+
end
|
data/lib/PackingPeanut.rb
CHANGED
@@ -1,12 +1,32 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
2
|
unless defined?(Motion::Project::Config)
|
4
|
-
raise "
|
3
|
+
raise "The PackingPeanut gem must be required within a RubyMotion project Rakefile."
|
4
|
+
end
|
5
|
+
|
6
|
+
# WHAT ARE WE?
|
7
|
+
platform = Motion::Project::App.respond_to?(:template) ? Motion::Project::App.template : :ios
|
8
|
+
if platform.to_s.start_with?('ios')
|
9
|
+
platform_name = 'ios'
|
10
|
+
elsif platform.to_s.start_with?('android')
|
11
|
+
platform_name = 'android'
|
5
12
|
end
|
6
13
|
|
7
|
-
|
14
|
+
# necessary for Android gem dependency as of 5/9/2015
|
15
|
+
require "moran" if platform_name == "android"
|
16
|
+
|
8
17
|
Motion::Project::App.setup do |app|
|
9
|
-
|
10
|
-
|
11
|
-
|
18
|
+
platform_lib = File.join(File.dirname(__FILE__), "PackingPeanut-#{platform_name}")
|
19
|
+
unless File.exists? platform_lib
|
20
|
+
raise "Sorry, the platform #{platform.inspect} (aka #{platform_name}) is not supported by PackingPeanut"
|
21
|
+
end
|
22
|
+
|
23
|
+
# scans app.files until it finds app/ (the default)
|
24
|
+
# if found, it inserts just before those files, otherwise it will insert to
|
25
|
+
# the end of the list
|
26
|
+
insert_point = app.files.find_index { |file| file =~ /^(?:\.\/)?app\// } || 0
|
27
|
+
|
28
|
+
Dir.glob(File.join(platform_lib, '**/*.rb')).reverse.each do |file|
|
29
|
+
app.files.insert(insert_point, file)
|
30
|
+
end
|
31
|
+
|
12
32
|
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: 0.0
|
4
|
+
version: 1.0.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-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -24,7 +24,35 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: moran
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: motion-gradle
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: App persistent data for RubyMotion Android and iOS
|
28
56
|
email:
|
29
57
|
- GantMan@gmail.com
|
30
58
|
executables: []
|
@@ -32,8 +60,10 @@ extensions: []
|
|
32
60
|
extra_rdoc_files: []
|
33
61
|
files:
|
34
62
|
- README.md
|
63
|
+
- lib/PackingPeanut-android/PackingPeanut.rb
|
64
|
+
- lib/PackingPeanut-ios/PackingPeanut.rb
|
65
|
+
- lib/PackingPeanut-ios/ns_user_defaults.rb
|
35
66
|
- lib/PackingPeanut.rb
|
36
|
-
- lib/project/PackingPeanut.rb
|
37
67
|
homepage: http://gantman.github.io/PackingPeanut/
|
38
68
|
licenses:
|
39
69
|
- MIT
|
@@ -57,6 +87,6 @@ rubyforge_project:
|
|
57
87
|
rubygems_version: 2.4.5
|
58
88
|
signing_key:
|
59
89
|
specification_version: 4
|
60
|
-
summary: App persistent data for RubyMotion Android, designed to fit the API
|
61
|
-
of the popular iOS Gem BubbleWrap which also supplies persistence.
|
90
|
+
summary: App persistent data for RubyMotion Android and iOS, designed to fit the API
|
91
|
+
stylings of the popular iOS Gem BubbleWrap which also supplies persistence.
|
62
92
|
test_files: []
|