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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12a47cd8b03f2575cbec3c3768afd5827e3459f7
4
- data.tar.gz: 07bdafd4af83852cd593c96af077634284d3370f
3
+ metadata.gz: e2f04de5df63f75fb232e267e56ce3f33bc0eefb
4
+ data.tar.gz: 9ad3ba2c1db95ad649252daa5a85c7c786d12419
5
5
  SHA512:
6
- metadata.gz: 2298a6a63b15c41318495495b3c9b64b30fe3f80c6f96673e92ba7df7f0c10331441b1ad4e99b217b2272123efe9995e83c68decc9161473f134ff0e07ca03ae
7
- data.tar.gz: 44023b702723b79591bb23bad85b1c4d2f18c330515a382cdcada4bde59c8ae5ffc02aa17ca91faf8303f6369fbcdba451fad2bf476ad19a14b8603331acdcc9
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
- iOS has [BubbleWrap](https://github.com/rubymotion/BubbleWrap) for App Persistence : Android has PackingPeanut
3
+ ### Cross Platform App Persistence
4
+ ![cross platform rubymotion gem](./_art/both_icon.png)
4
5
 
5
- There is a sedulous effort to make this syntax fit BubbleWrap's as much as possible, but differences simply exist, either for good, technical, or sometimes diabolical reasons :smiling_imp:
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
- # PP automatically has context if the module is included
30
- # In this case we need to set the context
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
- => true # This differs from Bubblewrap.... boolean on success for save (more informative)
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
- => [{:dinner=>"nachos"}, {:lunch=>"tacos"}]
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 ANdroid Operating modes. Use 0 or MODE_PRIVATE for the default operation, MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE to control permissions. 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.
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
- ## Limitations?
70
- Achilles, the Death Star, and video game villians always have a significant catch. As of right now, you can only store **strings, ints, and booleans**. The data is serialized, and should support hashes, arrays, and floats but alas, I claim there be bugs in conversions via RM Android.
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
- Boy that would be nice wouldn't it?
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(key,value)
29
- editor.putString(key, json.toString)
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
- json_string = get_value(key)
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(key, json_string)
40
+ deserialize(string_key, json_string)
37
41
  end
38
42
 
39
43
  def serialize(key, value)
40
- json = JSONObject.new
41
- json.put(key, value)
44
+ Moran.generate({:"#{key}" => value})
42
45
  end
43
46
 
44
47
  def deserialize(key, json_string)
45
- json = JSONObject.new(json_string)
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| {key.to_sym => JSONObject.new(value).get(key)} }
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
- PP = App
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
@@ -1,12 +1,32 @@
1
1
  # encoding: utf-8
2
-
3
2
  unless defined?(Motion::Project::Config)
4
- raise "This file must be required within a RubyMotion project Rakefile."
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
- lib_dir_path = File.dirname(File.expand_path(__FILE__))
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
- app.files.unshift(Dir.glob(File.join(lib_dir_path, "project/**/*.rb")))
10
- # Required for android as off 4/11/2015
11
- app.files.flatten!
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.3
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-04-13 00:00:00.000000000 Z
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
- description: App persistent data for RubyMotion Android
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 stylings
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: []