Skip to content

Instantly share code, notes, and snippets.

@redtachyons
Forked from alameenkhader/rails-rpush.md
Last active September 22, 2018 06:27
Show Gist options
  • Save redtachyons/ba3363623f4a941317d59c8bdb9ba240 to your computer and use it in GitHub Desktop.
Save redtachyons/ba3363623f4a941317d59c8bdb9ba240 to your computer and use it in GitHub Desktop.
Rpush/Rails Integration

Follow the steps in rpush to add the gem to your rails project

PushNotificationDevice

rails g model PushNotificationDevice device_type:integer:index device_token:string
class CreatePushNotificationDevices < ActiveRecord::Migration
  def change
    create_table :push_notification_devices do |t|
      t.integer :device_type
      t.string :device_token

      t.timestamps
    end

    add_index :push_notification_devices, :device_type
  end
end
class PushNotificationDevice < ActiveRecord::Base
  has_many :user_push_notification_devices
  has_many :users, through: :user_push_notification_devices

  enum device_type: { android: 0, ios: 1 }

  validates :device_type, :device_token, presence: true

  class << self
    # [push_notification description]
    # @param devices [Array] Array of devices
    # @param data [Hash] Data to be passes with the notification
    def push_notification(devices, data)
      ios_device_tokens = get_device_tokens(devices, :ios)
      android_device_tokens = get_device_tokens(devices, :android)

      if android_device_tokens.present?
        options = { registration_ids: android_device_tokens, data: data }
        PushNotify.push(PushNotify::SERVICE[:android],
                        PushNotify::APP_NAME[:android], options)
      end

      ios_device_tokens.each do |token|
        options = { device_token: token, data: data, alert: data[:message] }
        PushNotify.push(PushNotify::SERVICE[:ios],
                        PushNotify::APP_NAME[:ios], options)
      end
    end

    # Fetch device tokens from device records of the matching device_type
    # @param devices [Array] Array of devices
    # @param device_type [Symbol] type of device
    #
    # @return [Array] Array of device tokens
    def get_device_tokens(devices, device_type)
      devices.select { |d| d.device_type.to_sym.eql?(device_type) }
        .map(&:device_token).uniq
    end
  end
end

UserPushNotificationDevice

rails g model UserPushNotificationDevice user_id:integer push_notification_device_id:integer
class CreateUserPushNotificationDevices < ActiveRecord::Migration
  def change
    create_table :user_push_notification_devices do |t|
      t.integer :user_id
      t.integer :push_notification_device_id

      t.timestamps
    end

    add_index :user_push_notification_devices, :user_id
  end
end
class UserPushNotificationDevice < ActiveRecord::Base
  belongs_to :user
  belongs_to :push_notification_device
end

User

class User < ActiveRecord::Base
  has_many :user_push_notification_devices, dependent: :destroy
  has_many :push_notification_devices, through: :user_push_notification_devices
  
  # To add device info(type and token)
  #
  # @param attributes [Hash] device informations
  def add_device_info(attributes)
    return unless attributes.present? && attributes[:device_type].present? && attributes[:device_token].present?

    device_attr = attributes.slice(:device_type, :device_token)
    device_params = {
      device_type: PushNotificationDevice.device_types[device_attr[:device_type]],
      device_token: device_attr[:device_token]
    }

    device = PushNotificationDevice.where(device_params).first_or_initialize

    devices = push_notification_devices
    return if devices.include?(device)
    self.push_notification_devices << device
  end
end

PushNotify

lib/assets/push_notify.rb

# Push Notification related methods
#   To make push notification more easier
#   Please see https://github.com/rpush/rpush for more details
#
# @author alameen
#
class PushNotify
  MSGS = {
    invalid_app_type: 'Please provide a valid App type'
  }

  APP_NAME = {
    android: :android,
    ios: :ios
  }

  class << self
    # Pushes the message
    # @param type [Symbol] type of app
    # @param app_name [String] Name of the app
    # @param options [Hash] Notification options
    #
    # @return [Array/Boolean]
    def push(type, options)
      app = Rpush::Apns::App.find_by_name(type)
      case type
      when :android
        push_android(app, options)
      when :ios
        push_ios(app, options)
      else
        [false, MSGS[:invalid_app_type]]
      end
    end

    def push_android(app, options)
      options = options.slice(:registration_ids, :data).merge(app: app)
      Rpush::Gcm::Notification.new(options).save!
    end

    def push_ios(app, options)
      options = options.slice(:device_token, :alert, :data).merge(app: app)
      Rpush::Apns::Notification.new(options).save!
    end
  end
end

config/application.rb
config.autoload_paths += %W(#{config.root}/lib/assets)

Usage

Android - Create an app using the Google Authentication key
Rpush::Gcm::App.create(
  name: PushNotify::APP_NAME[:android],
  auth_key: ENV['V_GCM_AUTH_KEY']
  )
iOS - Create an app using the apns certificate
apns_cetificate = File.read("#{Rails.root}/public/certificates/apns_production.pem")
Rpush::Apns::App.create(
  name: PushNotify::APP_NAME[:ios],
  environment: 'production',
  password: 'password',
  certificate: apns_cetificate
  )
Adding device tokens

In controllers

# Use the method add_device_info to assign a device_token to a user
user.add_device_info(device_info_params)

private

# To set the device info params
#
# @return [Hash]
def device_info_params
  { device_type: find_device_type, device_token: params[:device_token] }
end

In one of the helper modules

# Determines the device type from the request headers
#
# @return [Symbol] the device key name/symbol
def find_device_type
  case request.user_agent
  when /mac|iOS/i
    :ios
  when /android/i
    :android
  else
    nil
  end
end
How to push a notification
devices = user.push_notification_devices

return if devices.blank?

data = {
  message: 'This is a test push notification',
  user_id: 2
}
PushNotificationDevice.push_notification(devices, data)

How to get the GCM Auth Key

https://developer.android.com/google/gcm/gs.html#create-proj

  1. Go to https://console.developers.google.com
  2. Create a new project
  3. Enable Google Cloud Messaging for Android in the APIs section
  4. Create a new public key from the Credentials section

Rpush Daemon

Remember to start the daemon rpush start More details here

References

  1. https://github.com/rpush/rpush
  2. https://developer.android.com/google/gcm/gs.html#create-proj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment