Ruby Native sends push notifications from your Rails app to iOS and Android devices. The gem provides the native_push_tag helper to register devices and a built-in endpoint to receive their tokens.
Add native_push_tag to your layout. The app prompts the user for notification permission the first time it sees this signal.
<%= native_push_tag if user_signed_in? %>
import { NativePush } from "@ruby-native/react"
{user && <NativePush />}
<script setup>
import { NativePush } from "@ruby-native/vue"
defineProps(["user"])
</script>
<template>
<NativePush v-if="user" />
</template>
Only show it for signed-in users. You need an authenticated user to associate the device token with.
Install the Action Push Native gem to handle device tokens and sending notifications. Run its install generator to create the migration:
bundle add action_push_native
bin/rails g action_push_native:install
bin/rails action_push_native:install:migrations
bin/rails db:migrate
When the user grants permission, the app sends the device token to your server via the gem's built-in endpoint.
The gem's endpoint calls your controller's current_user and saves the token to its push_devices association, which the Action Push Native install adds to your user model. If your app resolves the signed-in user differently, point the gem at it in an initializer with a method name or a callable:
# config/initializers/ruby_native.rb
RubyNative.configure do |config|
config.current_user_resolver = :current_person # a controller method
# or
config.current_user_resolver = -> { Current.person } # any callable
end
Whatever it returns needs that push_devices association.
Each platform needs its own credentials so the gem can deliver through APNs (iOS) or FCM (Android):
Once credentials are configured, the action_push_native gem provides a notification class. The same call delivers to both iOS and Android devices:
notification = ApplicationPushNotification
.with_data(path: "/links/#{link.id}")
.new(title: "New bookmark", body: "Someone shared a link with you.")
notification.deliver_later_to(user.push_devices)
with_data accepts two keys that control where the user lands when they tap the notification:
path: an internal route (e.g. /links/42). The app appends it to your base URL and loads it in-app. Use this for screens that live inside your Rails app.url: a full external URL (e.g. https://dashboard.stripe.com/payments/pi_abc).
http / https: opens inside the app's embedded browser on iOS, or the device browser on Android.mailto:, tel:, maps:, third-party app schemes): opens the relevant app if it's installed.When both are present, url wins. Malformed URLs are dropped; the tap does not fall back to path.
Pass badge: to set the app icon badge when the notification arrives:
notification = ApplicationPushNotification
.with_data(path: "/links/#{link.id}")
.new(
title: "New bookmark",
body: "Someone shared a link with you.",
badge: user.unread_count
)
On iOS the system sets the Home Screen badge to this number. Android has no numeric app icon badge; the count feeds the launcher dot and long-press preview instead.
The push badge does not update the tab bar badge. That comes from the badge signal, so include native_badge_tag on your pages and the two stay in sync the next time the user opens the app. See Badges for details.