j7w1 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1aa16f84153486f2d40ab5806b51656e35e914e9
4
+ data.tar.gz: 3c26a01d9f6eaa343592709edfeb35b3c5a0c469
5
+ SHA512:
6
+ metadata.gz: de214ef7b05d91fc18494403906ce3b0653bbb33c0ce88b6292795199a41df99a33a8cb2535e1171fa7bdcf9a0b7cf3ca5908d10ef5721fff6c292ea70f315c2
7
+ data.tar.gz: ddea72235386072cf3642b577865146f101c60133df8467e95d6da633ae9cab94e819e0646596b22355b6118c246df472b8190109fe424644a576f83ae93193b
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in j7w1.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 condor
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # J7W1
2
+
3
+ A gem to send the push notification to mobile app via Amazon Simple Notification Service (SNS). Currently supports only iOS platform, but the support for Android is also scheduled.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'j7w1'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install j7w1
18
+
19
+ ## Usage
20
+
21
+ First, configure your app.
22
+
23
+ J7W1.configure 'config.yml'
24
+
25
+ Or, you may configure programatically as below:
26
+
27
+ configuration = {
28
+ app_endpoint: {
29
+ ios: {arn: ...},
30
+ },
31
+ account: {
32
+ ...
33
+ }
34
+ }
35
+ J7W1.configure
36
+
37
+ Configuration is expected to have the structure as below:
38
+
39
+ app_endpoint:
40
+ ios:
41
+ arn: "<The ARN of your app.>"
42
+ account:
43
+ access_key_id: "<Your Access Key>"
44
+ secret_access_key: "<Your Secret Key>"
45
+ region: '<Your Region>'
46
+
47
+
48
+ If you use this with RoR, top-level environmental definition can be available.
49
+
50
+ ### Registering device to SNS
51
+
52
+ J7W1::PushClient.create_device_endpoint.
53
+
54
+ J7W1::PushClient.create_device_identifier device_identifier, platform
55
+
56
+ This method returns the arn registered.
57
+
58
+ ### Sending push
59
+
60
+ J7W1::PushClient.push.
61
+
62
+ J7W1::PushClient.push endpoint_arn, platform, message: some_message, badge: badge_count, sound: xxx
63
+
64
+ endpoint_arn should be the return value of the :create_device_endpoint above.
65
+
66
+ ## RoR Integration
67
+
68
+ The generator j7w1:model must be useful for you. It provides the items below:
69
+
70
+ 1. The model J7W1ApplicationDevice. This model enables you to store the device information and to push easily.
71
+ 2. The migration for the model above.
72
+ 3. Asyncronous SNS Syncing support. Currently delayed_job and sidekiq are supported. If you use this feature, invoke j7w1:model generation with --async-engine=(delayed_job|sidekiq).
73
+
74
+ ## Contributing
75
+
76
+ 1. Fork it
77
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
78
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
79
+ 4. Push to the branch (`git push origin my-new-feature`)
80
+ 5. Create new Pull Request
81
+
82
+ ## Author
83
+
84
+ TOYODA Naoto https://github.com/condor
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/j7w1.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'j7_w1/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "j7w1"
8
+ spec.version = J7W1::VERSION
9
+ spec.authors = ["condor"]
10
+ spec.email = ["condor1226@gmail.com"]
11
+ spec.description = %q{Mobile apps push client}
12
+ spec.summary = %q{Mobile apps push client}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "aws-sdk", "~> 1.17"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ end
@@ -0,0 +1,38 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module J7W1
5
+ class MigrationGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ def self.orm
9
+ Rails::Generators.options[:rails][:orm]
10
+ end
11
+
12
+ def self.source_root
13
+ File.join(File.dirname(__FILE__), 'templates', (orm.to_s unless orm.class.eql?(String)) )
14
+ end
15
+
16
+ def self.orm_has_migration?
17
+ [:active_record].include? orm
18
+ end
19
+
20
+ def self.next_migration_number(dirname)
21
+ if ActiveRecord::Base.timestamped_migrations
22
+ migration_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
23
+ migration_number += 1
24
+ migration_number.to_s
25
+ else
26
+ "%.3d" % (current_migration_number(dirname) + 1)
27
+ end
28
+ end
29
+
30
+ desc "This generator provides the tables which the J7W1 uses."
31
+ def create_migration_file
32
+ if self.class.orm_has_migration?
33
+ migration_template 'migration.rb', 'db/migrate/j7w1_application_devices'
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ class J7W1ApplicationDevices < ActiveRecord::Migration
2
+ def change
3
+ create_table :j7w1_application_devices do |t|
4
+ t.string :owner_type, null: false
5
+ t.integer :owner_id, null: false
6
+ t.string :device_identifier, null: false
7
+ t.string :platform, null: false
8
+ t.string :device_endpoint_arn, null: true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require 'rails/generators'
2
+
3
+ module J7W1
4
+ class ModelGenerator < Rails::Generators::Base
5
+ source_root File.join(File.dirname(__FILE__), 'templates')
6
+ class_option :async_engine, type: :string, default: nil,
7
+ desc: 'AWS register/deregister processing method'
8
+
9
+ def create_model_file
10
+ template "j7_w1_application_device.rb.erb",
11
+ "app/models/j7_w1_application_device.rb"
12
+
13
+ if options['async_engine'] == 'sidekiq'
14
+ copy_file "j7_w1_create_endpoint_worker.rb",
15
+ "app/workers/j7_w1_create_endpoint_worker.rb"
16
+ copy_file "j7_w1_destroy_endpoint_worker.rb",
17
+ "app/workers/j7_w1_destroy_endpoint_worker.rb"
18
+ end
19
+
20
+ invoke "j7_w1:migration"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ class J7W1ApplicationDevice < ActiveRecord::Base
2
+ set_table_name 'j7w1_application_devices'
3
+
4
+ belongs_to :owner, polymorphic: true
5
+
6
+ <%- if options['async_engine'] -%>
7
+ after_create :create_device_endpoint_async
8
+ after_destroy :destroy_device_endpoint_async
9
+ <%- else -%>
10
+ after_create :create_device_endpoint
11
+ after_destroy :destroy_device_endpoint
12
+ <%- end -%>
13
+
14
+ def push!(options = {})
15
+ J7W1::PushClient.push device_endpoint_arn, platform, *options
16
+ end
17
+
18
+ def create_device_endpoint
19
+ device_endpoint_arn = J7W1::PushClient.create_device_endpoint device_identifier, platform_id,
20
+ custom_user_data: "#{owner.class} ##{owner.id}"
21
+ update_attributes! device_endpoint_arn: device_endpoint_arn
22
+ end
23
+
24
+ def destroy_device_endpoint
25
+ J7W1::PushClient.destroy_endpoint device_arn
26
+ end
27
+ <%- if options['async_engine'] == 'delayed_job' -%>
28
+
29
+ private
30
+ def create_device_endpoint_async
31
+ delay.create_device_endpoint
32
+ end
33
+
34
+ def destroy_device_endpoint_async
35
+ delay.destroy_device_endpoint
36
+ end
37
+ <%- elsif options['async_engine'] == 'sidekiq' -%>
38
+
39
+ private
40
+ def create_device_endpoint_async
41
+ J7W1Worker.perform_async id
42
+ end
43
+
44
+ def destroy_device_endpoint_async
45
+ J7W1Worker.perform_async id
46
+ end
47
+ <%- end -%>
48
+ end
@@ -0,0 +1,7 @@
1
+ class J7W1CreateEndpointWorker
2
+ include Sidekiq::Worker
3
+
4
+ def perform(id)
5
+ J7W1ApplicationDevice.find(id).create_device_endpoint
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class J7W1DestroyEndpointWorker
2
+ include Sidekiq::Worker
3
+
4
+ def perform(id)
5
+ J7W1ApplicationDevice.find(id).destroy_device_endpoint
6
+ end
7
+ end
@@ -0,0 +1,38 @@
1
+ module J7W1
2
+ module ActiveRecordExt
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ private
9
+ def application_device_owner
10
+ include InstanceMethods
11
+
12
+ has_many :application_devices, class_name: 'J7W1::ApplicationDevice'
13
+ end
14
+ end
15
+
16
+ module InstanceMethods
17
+ def add_device(device_identifier, platform)
18
+ device =
19
+ devices.where(device_identifier: device_identifier, platform: platform).
20
+ find_or_initialize
21
+ device.endpoint_arn = nil
22
+ device.save!
23
+ end
24
+
25
+ def remove_device(device_identifier, platform)
26
+ devices.where(device_identifier: device_identifier, platform: platform).
27
+ destroy_all
28
+ end
29
+
30
+ def push!(options = {})
31
+ sns_client = self.create_sns_client
32
+ aplication_devices.each do |device|
33
+ device.push! options.tap{|o|o.merge! sns_client: sns_client}
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,2 @@
1
+ require 'j7_w1/push_client'
2
+ require 'j7_w1/active_record_ext' if Object.const_defined? :ActiveRecord
@@ -0,0 +1,52 @@
1
+ module J7W1
2
+ class Configuration
3
+ module IOSEndpoint
4
+ def sandbox?
5
+ @sandbox
6
+ end
7
+
8
+ def arn
9
+ self[:arn]
10
+ end
11
+
12
+ def confirm_sandbox
13
+ arn =~ /:app\/APNS_SANDBOX\//
14
+ end
15
+ end
16
+
17
+ module AndroidEndpoint
18
+ def arn
19
+ self[:arn]
20
+ end
21
+ end
22
+
23
+ module Account
24
+ [:access_key_id, :secret_access_key, :region].each do |attr|
25
+ define_method(attr){self[attr]}
26
+ end
27
+ end
28
+
29
+ def initialize(configuration_values)
30
+ @values = configuration_values
31
+ if ios_endpoint
32
+ ios_endpoint.extend(IOSEndpoint)
33
+ ios_endpoint.confirm_sandbox
34
+ end
35
+ android_endpoint.extend(AndroidEndpoint) if android_endpoint
36
+ account.extend(Account)
37
+ end
38
+
39
+ def account
40
+ @values[:account]
41
+ end
42
+
43
+ def ios_endpoint
44
+ @values[:app_endpoint][:ios]
45
+ end
46
+
47
+ def android_endpoint
48
+ #TODO configの対応
49
+ @values[:app_endpoint][:android]
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,83 @@
1
+ module J7W1
2
+ module PushClient
3
+ def create_sns_client(configuration = J7W1.configuration)
4
+ AWS::SNS.new J7W1.configuration.account
5
+ end
6
+
7
+ def create_device_endpoint(device_identifier, platform, options = {})
8
+ custom_user_data = options[:custom_user_data]
9
+ sns_configuration = options[:sns_configuration]
10
+ sns_client = options[:sns_client]
11
+
12
+ sns_client ||= create_sns_client(sns_configuration || J7W1.configuration)
13
+
14
+ sns_config = J7W1.configuration
15
+ app_arn = platform == :ios ? sns_config.ios_endpoint.arn :
16
+ sns_config.android_endpoint.arn
17
+
18
+ endpoint =
19
+ sns_client.client.create_platform_endpoint(
20
+ platform_application_arn: app_arn,
21
+ token: device_identifier,
22
+ custom_user_data: custom_user_data
23
+ )
24
+ endpoint[:endpoint_arn]
25
+ end
26
+
27
+ def destroy_endpoint(device_endpoint_arn, options = {})
28
+ sns_client = options[:sns_client]
29
+ sns_client ||= create_sns_client(sns_configuration || J7W1.configuration)
30
+
31
+ sns_client.client.delete_endpoint(endpoint_arn: device_endpoint_arn)
32
+ rescue
33
+ nil
34
+ end
35
+
36
+ def push(endpoint_arn, platform, options = {})
37
+ return unless endpoint_arn && platform
38
+
39
+ message = options[:message]
40
+ badge = options[:badge]
41
+ sound = options[:sound]
42
+ sns_configuration = options[:sns_configuration]
43
+ sns_client = options[:sns_client]
44
+
45
+ message_value = {}
46
+ message_value.merge!(alert: message) unless message.blank?
47
+ message_value.merge!(badge: badge) unless badge.blank?
48
+ message_value.merge!(sound: sound) unless sound.blank?
49
+
50
+ payload = payload_for(message_value, platform)
51
+
52
+ sns_client ||= create_sns_client(sns_configuration || J7W1.configuration)
53
+ sns_client.client.publish(
54
+ target_arn: endpoint_arn,
55
+ message: payload.to_json,
56
+ message_structure: 'json',
57
+ )
58
+ end
59
+
60
+ private
61
+ def payload_for(message_value, platform)
62
+ case platform
63
+ when 'ios'
64
+ ios_payload_for(message_value)
65
+ when 'android'
66
+ android_payload_for(message_value)
67
+ end
68
+ end
69
+
70
+ def ios_payload_for(message_value)
71
+ prefix = J7W1::Sns.configuration.ios_endpoint.sandbox? ?
72
+ :APNS_SANDBOX : :APNS
73
+ {prefix => {aps: message_value}.to_json}
74
+ end
75
+
76
+ def android_payload_for(message_value)
77
+ # TODO Android Push Implementation
78
+ end
79
+
80
+ module_function :create_sns_client, :create_device_endpoint, :push,
81
+ :payload_for, :ios_payload_for, :android_payload_for
82
+ end
83
+ end
data/lib/j7_w1/stub.rb ADDED
@@ -0,0 +1,47 @@
1
+ module J7W1
2
+ module PushClient
3
+
4
+ class << self
5
+ def push_histories
6
+ @push_histories ||= []
7
+ end
8
+
9
+ def push(device, options)
10
+ @push_histories.push(options.merge(device: device))
11
+ end
12
+ end
13
+ end
14
+
15
+ module ActiveRecordExt
16
+ def self.included(base)
17
+ base.extend ClassMethods
18
+ end
19
+
20
+ module ClassMethods
21
+ def device_owner_classes
22
+ require 'set'
23
+ @device_owner_classes ||= Set.new
24
+ end
25
+
26
+ private
27
+ def device_owner
28
+ device_owner_classes << self
29
+ end
30
+ end
31
+
32
+ module InstanceMethods
33
+ def push!(options = {})
34
+ sns_client = self.create_sns_client
35
+ aplication_devices.each do |device|
36
+ device.push! sns_client, *options
37
+ end
38
+ end
39
+
40
+ def add_device(device_identifier, platform)
41
+ end
42
+
43
+ def remove_device(device_identifier, platform)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module J7W1
2
+ VERSION = "0.0.1"
3
+ end
data/lib/j7w1.rb ADDED
@@ -0,0 +1,88 @@
1
+ require 'yaml'
2
+
3
+ module J7W1
4
+ autoload :Configuration, 'j7_w1/configuration'
5
+
6
+ class << self
7
+ attr_reader :current_strategy
8
+ private :current_strategy
9
+
10
+ def configure(configuration)
11
+ raise ArgumentError,
12
+ "J7W1 configuration values should be an instance of Hash or String, but actually it is a kind of #{configuration.class.name}" unless
13
+ configuration.is_a?(Hash) || configuration.is_a?(String)
14
+
15
+ configuration = configuration_values_of(configuration)
16
+ if configuration[:mock]
17
+ require 'j7_w1/mock'
18
+ return
19
+ end
20
+
21
+ require 'j7_w1/concrete'
22
+ @configuration = Configuration.new configuration
23
+ end
24
+
25
+ def configuration
26
+ @configuration
27
+ end
28
+
29
+ private
30
+ def configuration_values_of(configuration)
31
+ configuration =
32
+ case configuration
33
+ when String
34
+ configuration_values_of(YAML.load(File.read(configuration)))
35
+ when Hash
36
+ configuration
37
+ else
38
+ raise ArgumentError, "J7W1.configure can acceptable only Hash(configuration values) or String(pointing the yaml config file)"
39
+ end
40
+ configuration = symbolize_keys_recursive(configuration)
41
+
42
+ if self.class.const_defined? :Rails
43
+ return configuration[Rails.env.to_sym] if configuration[Rails.env.to_sym]
44
+ end
45
+
46
+ configuration
47
+ end
48
+
49
+ def symbolize_keys_recursive(hash)
50
+ hash.inject({}) do |h, kv|
51
+ (key, value) = kv
52
+ h[key.to_sym] = regularize_for_symbolization(value)
53
+ h
54
+ end
55
+ end
56
+
57
+ if const_defined?(:ActiveSupport) && Hash.instance_methods.include?(:symbolize_keys) &&
58
+ const_get(:ActiveSupport).const_defined?(:HashWithIndifferentAccess)
59
+ def regularize_for_symbolization(value)
60
+ case value
61
+ when ActiveSupport::HashWithIndifferentAccess
62
+ value
63
+ when Hash
64
+ value.symbolize_keys
65
+ when Array
66
+ value.map{|v|regularize_for_symbolization(v)}
67
+ else
68
+ value
69
+ end
70
+ end
71
+ else
72
+ def regularize_for_symbolization(value)
73
+ case value
74
+ when Hash
75
+ value.inject({}) do |h, kv|
76
+ (key, value) = kv
77
+ h[key.to_sym] = regularize_for_symbolization(value)
78
+ h
79
+ end
80
+ when Array
81
+ value.map{|v|regularize_for_symbolization(v)}
82
+ else
83
+ value
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
data/spec/.gitignore ADDED
@@ -0,0 +1 @@
1
+ config.yml
@@ -0,0 +1,7 @@
1
+ app_endpoint:
2
+ ios:
3
+ arn: "arn:aws:sns:<Your Region>:<Your Account ID>:app/<YourApp.sandbox? ? APNS_SANDBOX : APNS>/<Your App's name>"
4
+ account:
5
+ access_key_id: "<Your Access Key>"
6
+ secret_access_key: "<Your Secret Key>"
7
+ region: '<Your Region>'
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: j7w1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - condor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
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
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Mobile apps push client
70
+ email:
71
+ - condor1226@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - j7w1.gemspec
82
+ - lib/generators/j7_w1/migration/migration_generator.rb
83
+ - lib/generators/j7_w1/migration/templates/active_record/migration.rb
84
+ - lib/generators/j7_w1/model/model_generator.rb
85
+ - lib/generators/j7_w1/model/templates/j7_w1_application_device.rb.erb
86
+ - lib/generators/j7_w1/model/templates/j7_w1_create_endpoint_worker.rb
87
+ - lib/generators/j7_w1/model/templates/j7_w1_destroy_endpoint_worker.rb
88
+ - lib/j7_w1/active_record_ext.rb
89
+ - lib/j7_w1/concrete.rb
90
+ - lib/j7_w1/configuration.rb
91
+ - lib/j7_w1/push_client.rb
92
+ - lib/j7_w1/stub.rb
93
+ - lib/j7_w1/version.rb
94
+ - lib/j7w1.rb
95
+ - spec/.gitignore
96
+ - spec/config.example.yml
97
+ homepage: ''
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.0.3
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: Mobile apps push client
121
+ test_files:
122
+ - spec/.gitignore
123
+ - spec/config.example.yml