acts_as_pushable 0.1.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: ed12f0e669f857b1557bfd63ceaf0b707666202e
4
+ data.tar.gz: 82c4bbdfc796f1c940a6a0f1d4fa3eb89ee7b5c5
5
+ SHA512:
6
+ metadata.gz: cc1fda57e9415e2492820c26a233311c0d6eea4886dde6112d98b8f2a56482ddfe2e2220ffb6c7699808ecf4633e84ef788ad23dd2bb49c739b0be8e5abf200d
7
+ data.tar.gz: a8f27a82cd72ef09e38750ae37f5d1b722fb16f988be7b0b9abae1fd8ef23f186a302cbb217de5487f2b6a0d3f6723ab4a44b5084951e6ba65a02d7a49e8457c
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Adam Butler
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # ActsAsPushable
2
+
3
+ [![Build Status](https://semaphoreci.com/api/v1/projects/28a53ae7-389f-4d93-9f8a-51c4b0756cf7/840599/badge.svg)](https://semaphoreci.com/simpleweb/acts_as_pushable)
4
+ [![Gem Version](https://badge.fury.io/rb/acts_as_pushable.svg)](https://badge.fury.io/rb/acts_as_pushable)
5
+
6
+ A gem for Ruby on Rails that makes managing devices and push notifications for both iOS and Android easy and reliable.
7
+
8
+ ## Setup
9
+
10
+ Add ActsAsPushable to your Gemfile
11
+
12
+ ```shell
13
+ gem 'acts_as_pushable'
14
+ bundle install
15
+ ```
16
+
17
+ or just install it -
18
+
19
+ ```shell
20
+ gem install acts_as_pushable
21
+ ```
22
+
23
+ ## Quick start
24
+
25
+ Run the generator to create the migrations and initializer template -
26
+
27
+ ```shell
28
+ rails generate act_as_pushable
29
+ ```
30
+
31
+ This a file at `config/initializers/acts_as_pushable.rb` that you can modify to match your settings. Follow the quick start guides for the platforms that you want to support.
32
+
33
+ Next add `acts_as_pushable` the following to the model that you want to have devices, this is usually the `User` model. It should look something like this -
34
+
35
+ ```ruby
36
+ class User < ActiveRecord::Base
37
+ acts_as_pushable
38
+ end
39
+ ```
40
+
41
+ ## Quick start - iOS
42
+
43
+ Before we start you'll need a push certificate for both APN Development and APN Production. You can find instructions on how to do this [here](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW11).
44
+
45
+ > **Important:** You should do both production and development and include them in all deployment environments. These relate to the two environments that Apple provide rather than your environments.
46
+
47
+ Once you have the certificate from Apple, you will need to export your key and the installed certificate as p12 files. Here how you do this -
48
+
49
+ 1. In Keychain Access find your installed certificate
50
+ 2. Right click the certificate, it should have an arrow next to it if install correctly, then export it.
51
+ ![export](https://cloud.githubusercontent.com/assets/1238468/15851982/5a9bb9e0-2c97-11e6-8407-2e4797673dff.jpg)
52
+ 3. Next convert the p12 file to a pem file by running the following command.
53
+ ```
54
+ $ openssl pkcs12 -in cert.p12 -out apple_push_notification.pem -nodes -clcerts
55
+ ```
56
+ 4. The output pem file should be put in one of the following locations depending on it's type -
57
+ - `config/acts_as_pushable/apn/production.pem`
58
+ - `config/acts_as_pushable/apn/development.pem`
59
+
60
+ > Note: You can change the location that the pem file is loaded stored in the `acts_as_pushable.rb` initializer.
61
+
62
+ ## Quick start - Android
63
+
64
+ 1. Register for GCM (Google Cloud Messaging) at [developers.google.com](https://developers.google.com/cloud-messaging/).
65
+ 2. Enter your key into the `acts_as_pushable.rb` initializer. You can get this from the [Google API Developer Console](https://console.developers.google.com). It should be entered as such -
66
+
67
+ ```ruby
68
+ ActsAsPushable.configure do |config|
69
+ config.gcm_key = 'replace_me_with_your_api_key'
70
+ end
71
+ ```
72
+
73
+ ## Add a device
74
+
75
+ You can add a device to any model with `acts_as_pushable`. In these examples we'll use a model named `User` as an example.
76
+
77
+ ```ruby
78
+ user = User.create
79
+ user.add_device({
80
+ token: 'the_token_generated_by_the_device',
81
+ platform: "ios",
82
+ platform_version: "9.3",
83
+ push_environment: "development",
84
+ })
85
+ ```
86
+
87
+ ## Send a push notification to a user
88
+
89
+ Sending a push notification to a user will send the message to all of their valid device tokens both on iOS & Android
90
+
91
+ ```ruby
92
+ user = User.find(id)
93
+ user.send_push_notification(title: 'My App', message: 'this is a test', options)
94
+ ```
95
+
96
+ > You might want to consider doing this inside a worker.
97
+
98
+ ## Send a push notification to a specific device
99
+
100
+ ```ruby
101
+ user = User.find(id)
102
+ device = user.devices.first
103
+
104
+ case device.platform
105
+ when "ios"
106
+ # iOS does not support titles
107
+ user.send_push_notification(message: 'this is a test', options)
108
+ when "android"
109
+ user.send_push_notification(message: 'this is a test', options)
110
+ end
111
+ ```
112
+
113
+ > You might want to consider doing this inside a worker.
114
+
115
+ ## Apple Feedback Service
116
+
117
+ Occasionally you'll want to cleanup old tokens that have been invalidated for various reasons. You can do this by running -
118
+
119
+ ```
120
+ ActsAsPushable::APN::FeedbackService.run
121
+ ```
122
+
123
+ We'd recommnd running this on a daily/weekly cron job.
124
+
125
+ > Note: With Android this happens at the time of sending a notification, no action is required.
126
+
127
+ ---
128
+
129
+ ## Setup for development
130
+
131
+ Clone the repository -
132
+
133
+ ```shell
134
+ git clone git@github.com:simpleweb/acts_as_pushable.git
135
+ cd acts_as_pushable
136
+ bundle install
137
+ ```
138
+
139
+ #### Run the specs with RSpec
140
+
141
+ ```
142
+ rspec
143
+ ```
144
+
145
+ ## Other useful resources
146
+
147
+ - [Bullet Proof Push](https://www.youtube.com/watch?v=k5J6t-y1bws) _15 minute talk by [Adam Butler](http://twitter.com/labfoo)_ - The ideas that this gem is based on.
148
+ - [simpleweb/ios-development-for-teams](https://github.com/simpleweb/ios-development-for-teams) - A guide by the author of this gem on setting up Certificates, ID's and Provisioning profiles that work well for teams.
149
+ - [nomad/houston](https://github.com/nomad/houston) - Powers the APN part of this gem
150
+ - [spacialdb/gcm](https://github.com/spacialdb/gcm) - Powers the GCM part of this gem.
151
+
152
+ ## Contributing
153
+
154
+ This project follows the [GitHub Flow workflow](https://guides.github.com/introduction/flow/). All contributions should be provided as descriptive atomic pull requests.
155
+
156
+ The gem should be versioned in accordance to [Semantic Versioning 2.0.0](http://semver.org/).
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'ActsAsPushable'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,46 @@
1
+ module ActsAsPushable
2
+ class Device < ActiveRecord::Base
3
+ belongs_to :parent, polymorphic: true
4
+
5
+ validates :token, :platform, :valid_at, :parent, :platform_version, :push_environment, presence: true
6
+ validates :token, uniqueness: true
7
+ validates :active, inclusion: { in: [true, false] }
8
+
9
+ before_validation :set_valid_at, on: :create
10
+
11
+ scope :active, -> { where(invalidated_at: nil, active: true) }
12
+
13
+ default_scope { active }
14
+
15
+ def ios?
16
+ platform == 'ios'
17
+ end
18
+
19
+ def android?
20
+ platform == 'android'
21
+ end
22
+
23
+ def deactivate
24
+ self.update_attributes({
25
+ active: false,
26
+ deactivated_at: Time.now,
27
+ })
28
+ end
29
+
30
+ def send_push_notification(message:, **options)
31
+ case platform
32
+ when 'ios'
33
+ ActsAsPushable::APN::Notification.send(device: self, message: message, **options)
34
+ when 'android'
35
+ raise ArgumentError, 'missing keyword: title' unless options.key? :title
36
+ ActsAsPushable::GCM::Notification.send(device: self, title: options[:title], message: message, **options)
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def set_valid_at
43
+ self.valid_at = Time.now
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,22 @@
1
+ require 'houston'
2
+
3
+ module ActsAsPushable
4
+ module APN
5
+ class FeedbackService
6
+ def self.run
7
+ development_apn = Houston::Client.development
8
+ production_apn = Houston::Client.production
9
+
10
+ development_apn.certificate = ActsAsPushable.configuration.apn_development_certificate_file
11
+ production_apn.certificate = ActsAsPushable.configuration.apn_production_certificate_file
12
+
13
+ devices = development_apn.devices + production_apn.devices
14
+
15
+ devices.each do |device|
16
+ device = ActsAsPushable::Device.find_by_token(device)
17
+ device.update_attribute('invalidated_at', Time.now) if device
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ require 'houston'
2
+
3
+ module ActsAsPushable
4
+ module APN
5
+ class Notification
6
+ def self.send(device:, message:, **options)
7
+ development_apn = Houston::Client.development
8
+ production_apn = Houston::Client.production
9
+
10
+ development_apn.certificate = ActsAsPushable.configuration.apn_development_certificate_file
11
+ production_apn.certificate = ActsAsPushable.configuration.apn_production_certificate_file
12
+
13
+ payload = {
14
+ popup: options.fetch('popup', true),
15
+ popup_title: options.fetch('popup_title', nil),
16
+ popup_body: options.fetch('popup_body', nil),
17
+ popup_type: options.fetch('popup_type', 'alert'),
18
+ popup_ok_button_text: options.fetch('popup_ok_button_text', 'Ok'),
19
+ popup_cancel_button_text: options.fetch('popup_cancel_button_text', 'Cancel'),
20
+ navigate_to_view: options.fetch('navigate_to_view', nil),
21
+ navigate_to_view_as_modal: options.fetch('navigate_to_view_as_modal', true),
22
+ navigate_to_view_parameters: options.fetch('navigate_to_view_parameters', {}),
23
+ }
24
+
25
+ notification = Houston::Notification.new(device: device.token)
26
+ notification.alert = message
27
+ notification.badge = options.fetch('count', nil)
28
+ notification.custom_data = payload
29
+
30
+ if device.push_environment == 'development'
31
+ development_apn.push(notification)
32
+ else
33
+ production_apn.push(notification)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ module ActsAsPushable
2
+ class Configuration
3
+ attr_accessor :apn_development_certificate_path, :apn_production_certificate_path, :gcm_key
4
+
5
+ def initialize
6
+ self.apn_development_certificate_path = Rails.root.join('config', 'acts_as_pushable', 'apn', 'development.pem')
7
+ self.apn_production_certificate_path = Rails.root.join('config', 'acts_as_pushable', 'apn', 'production.pem')
8
+ end
9
+
10
+ def apn_development_certificate_file
11
+ File.read(apn_development_certificate_path)
12
+ end
13
+
14
+ def apn_production_certificate_file
15
+ File.read(apn_production_certificate_path)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ require 'gcm'
2
+
3
+ module ActsAsPushable
4
+ module GCM
5
+ class Notification
6
+ def self.send(device:, title:, message:, **options)
7
+ payload = {
8
+ popup: options.fetch("popup", true),
9
+ popup_title: options.fetch("popup_title", nil),
10
+ popup_body: options.fetch("popup_body", nil),
11
+ popup_type: options.fetch("popup_type", 'alert'),
12
+ popup_ok_button_text: options.fetch("popup_ok_button_text", 'Ok'),
13
+ popup_cancel_button_text: options.fetch("popup_cancel_button_text", 'Cancel'),
14
+ navigate_to_view: options.fetch("navigate_to_view", nil),
15
+ navigate_to_view_as_modal: options.fetch("navigate_to_view_as_modal", true),
16
+ navigate_to_view_parameters: options.fetch("navigate_to_view_parameters", {}),
17
+ }
18
+
19
+ gcm = ::GCM.new(ActsAsPushable.configuration.gcm_key)
20
+
21
+ gcm_options = {
22
+ data: {
23
+ title: title,
24
+ message: message,
25
+ }.merge(payload)
26
+ }
27
+
28
+ response = gcm.send([device.token], gcm_options)
29
+ if response[:not_registered_ids].include? device.token
30
+ device.update_attribute 'invalidated_at', Time.now
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,47 @@
1
+ module ActsAsPushable
2
+ module Pushable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ end
7
+
8
+ module ClassMethods
9
+ def acts_as_pushable(options = {})
10
+ has_many :devices, as: :parent, class_name: 'ActsAsPushable::Device'
11
+ end
12
+ end
13
+
14
+ def ios_devices
15
+ devices.where(platform: 'ios')
16
+ end
17
+
18
+ def android_devices
19
+ devices.where(platform: 'android')
20
+ end
21
+
22
+ def add_device(device_params)
23
+ device = build_device(device_params)
24
+ device.save
25
+ end
26
+
27
+ def add_device!(device_params)
28
+ device = build_device(device_params)
29
+ device.save!
30
+ end
31
+
32
+ def send_push_notification(title:, message:, **options)
33
+ devices.each do |device|
34
+ device.send_push_notification(title: title, message: message, **options)
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def build_device(device_params)
41
+ self.devices.build(device_params)
42
+ end
43
+
44
+ end
45
+ end
46
+
47
+ ActiveRecord::Base.send :include, ActsAsPushable::Pushable
@@ -0,0 +1,3 @@
1
+ module ActsAsPushable
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,30 @@
1
+ require 'acts_as_pushable/version'
2
+ require 'acts_as_pushable/configuration'
3
+
4
+ require 'acts_as_pushable/active_record/device.rb'
5
+ require 'acts_as_pushable/pushable'
6
+
7
+ require 'acts_as_pushable/apn/notification'
8
+ require 'acts_as_pushable/apn/feedback_service'
9
+ require 'acts_as_pushable/gcm/notification'
10
+
11
+ module ActsAsPushable
12
+ LOCK = Mutex.new
13
+
14
+ class << self
15
+ def configure(config_hash=nil)
16
+ if config_hash
17
+ config_hash.each do |k,v|
18
+ configuration.send("#{k}=", v) rescue nil if configuration.respond_to?("#{k}=")
19
+ end
20
+ end
21
+
22
+ yield(configuration) if block_given?
23
+ end
24
+
25
+ def configuration
26
+ @configuration = nil unless defined?(@configuration)
27
+ @configuration || LOCK.synchronize { @configuration ||= ActsAsPushable::Configuration.new }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ require 'rails/generators/migration'
2
+
3
+ module ActsAsPushable
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ def copy_initializer_file
11
+ template "initializer.rb", "config/initializers/acts_as_pushable.rb"
12
+ end
13
+
14
+ def copy_migration_files
15
+ migration_template "migration/devices.rb", "db/migrate/devices.rb"
16
+ end
17
+
18
+ def self.next_migration_number(dirname)
19
+ if ActiveRecord::Base.timestamped_migrations
20
+ sleep 1 # make sure each time we get a different timestamp
21
+ Time.new.utc.strftime("%Y%m%d%H%M%S")
22
+ else
23
+ "%.3d" % (current_migration_number(dirname) + 1)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ ActsAsPushable.configure do |config|
2
+ # Defaults
3
+ # config.apn_development_certificate_path = Rails.root.join('config', 'acts_as_pushable', 'apn', 'development.pem')
4
+ # config.apn_production_certificate_path = Rails.root.join('config', 'acts_as_pushable', 'apn', 'production.pem')
5
+
6
+ config.gcm_key = "replace_me_with_your_gcm_api_key"
7
+ end
@@ -0,0 +1,21 @@
1
+ class Devices < ActiveRecord::Migration
2
+ def change
3
+ create_table :devices do |t|
4
+ t.string :token
5
+ t.integer :parent_id
6
+ t.string :parent_type
7
+ t.string :platform
8
+ t.boolean :active, default: true
9
+ t.datetime :valid_at
10
+ t.datetime :invalidated_at
11
+ t.datetime :deleted_at
12
+ t.string :platform_version
13
+ t.string :platform_type
14
+ t.string :push_environment
15
+ t.datetime :deactivated_at
16
+ t.timestamps
17
+ end
18
+
19
+ add_index :devices, :token, unique: true
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :acts_as_pushable do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_pushable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Adam Butler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0.beta4
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 5.0.0.beta4
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.1'
33
+ - !ruby/object:Gem::Dependency
34
+ name: houston
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: gcm
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: sqlite3
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec-rails
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: fuubar
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: timecop
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: pry
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: simplecov
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ description: A gem for Ruby on Rails that makes managing devices and push notifications
146
+ for both iOS and Android easy and reliable.
147
+ email:
148
+ - adam@simpleweb.co.uk
149
+ executables: []
150
+ extensions: []
151
+ extra_rdoc_files: []
152
+ files:
153
+ - MIT-LICENSE
154
+ - README.md
155
+ - Rakefile
156
+ - lib/acts_as_pushable.rb
157
+ - lib/acts_as_pushable/active_record/device.rb
158
+ - lib/acts_as_pushable/apn/feedback_service.rb
159
+ - lib/acts_as_pushable/apn/notification.rb
160
+ - lib/acts_as_pushable/configuration.rb
161
+ - lib/acts_as_pushable/gcm/notification.rb
162
+ - lib/acts_as_pushable/pushable.rb
163
+ - lib/acts_as_pushable/version.rb
164
+ - lib/generators/acts_as_pushable/install_generator.rb
165
+ - lib/generators/acts_as_pushable/templates/initializer.rb
166
+ - lib/generators/acts_as_pushable/templates/migration/devices.rb
167
+ - lib/tasks/acts_as_pushable_tasks.rake
168
+ homepage: https://github.com/simpleweb/acts_as_pushable
169
+ licenses:
170
+ - MIT
171
+ metadata: {}
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 2.4.5.1
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: Add iOS & Android device and push notification support in your Rails application.
192
+ test_files: []