Trong bài này, mình sẽ xây dựng chức năng push notification đơn giản sử dụng actioncable của Rails.
Như đã biết actionCable được dùng để làm realtime cho ứng dụng của mình.
Bước thực hiện
Tạo một channel cho actioncable
1 2 3 4 5 6 | ✗ rails generate channel notifications Running via Spring preloader in process 4124 create app/channels/notifications_channel.rb identical app/assets/javascripts/cable.js create app/assets/javascripts/channels/notifications.coffee |
Nó đã tạo 2 file như trên. Bây giờ mình sẽ subscribe vào channel tên là: notifications_channel
1 2 3 4 5 6 7 8 9 10 | <span class="token comment"># app/channels/notifications_channel.rb</span> <span class="token keyword">class</span> <span class="token class-name">NotificationsChannel</span> <span class="token operator"><</span> <span class="token constant">ApplicationCable</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">Channel</span> <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">subscribed</span></span> stream_from <span class="token string">"notifications_channel"</span> <span class="token keyword">end</span> <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">unsubscribed</span></span> <span class="token keyword">end</span> <span class="token keyword">end</span> |
Tạo Form
Đơn giản chỉ có một text_field và nút submit để có thể gửi nội dùng push message.
View
1 2 3 4 5 | <span class="token operator"><</span><span class="token string">%= form_tag push_notification_path do %> <%=</span> text_field_tag <span class="token symbol">:message</span> <span class="token string">%> <%= submit_tag :submit %></span> <span class="token operator"><</span><span class="token operator">%</span> <span class="token keyword">end</span> <span class="token operator">%</span><span class="token operator">></span> |
Controller
1 2 3 4 5 6 7 8 9 | <span class="token keyword">class</span> <span class="token class-name">NotificationsController</span> <span class="token operator"><</span> <span class="token constant">ApplicationController</span> <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">push_notification</span></span> <span class="token constant">ActionCable</span><span class="token punctuation">.</span>server<span class="token punctuation">.</span>broadcast<span class="token punctuation">(</span><span class="token string">"notifications_channel"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>message<span class="token punctuation">:</span> params<span class="token punctuation">[</span><span class="token symbol">:message</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">)</span> redirect_to root_path <span class="token keyword">end</span> <span class="token keyword">end</span> |
routes
1 2 3 4 | <span class="token constant">Rails</span><span class="token punctuation">.</span>application<span class="token punctuation">.</span>routes<span class="token punctuation">.</span>draw <span class="token keyword">do</span> post <span class="token symbol">:push_notification</span><span class="token punctuation">,</span> to<span class="token punctuation">:</span> <span class="token string">"notifications#push_notification"</span> <span class="token keyword">end</span> |
Đến đây, khi submit form, nó sẽ broadcast tới notifications_channel
với data object {message: params[:message]})
Làm thế nào để push notification
Ở đây mình sẽ sử dụng Push API để push notification.
https://developer.mozilla.org/en-US/docs/Web/API/Push_API
1 2 3 4 | <span class="token comment">// app/assets/javascript/application.js</span> <span class="token comment">// request permission</span> Notification<span class="token punctuation">.</span><span class="token function">requestPermission</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">result</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> |
Để push notification, mình có thể dùng như sau:
1 2 | <span class="token keyword">new</span> <span class="token class-name">Notification</span><span class="token punctuation">(</span>title<span class="token punctuation">,</span> <span class="token punctuation">{</span>body<span class="token operator">:</span> body<span class="token punctuation">}</span><span class="token punctuation">)</span> |
Từ đó, mình sẽ áp dụng cái này vào trong notifications_channel
trong hàm received như sau:
1 2 3 4 5 6 7 8 9 10 11 12 | App<span class="token punctuation">.</span>notifications <span class="token operator">=</span> App<span class="token punctuation">.</span>cable<span class="token punctuation">.</span>subscriptions<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token string">"NotificationsChannel"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token function-variable function">connected</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"connected"</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token function-variable function">disconnected</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token function-variable function">received</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>Notification<span class="token punctuation">.</span>permission <span class="token operator">===</span> <span class="token string">"granted"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> title <span class="token operator">=</span> <span class="token string">"Push Notification"</span> <span class="token keyword">var</span> options <span class="token operator">=</span> <span class="token punctuation">{</span>body<span class="token operator">:</span> data<span class="token punctuation">[</span><span class="token string">"message"</span><span class="token punctuation">]</span><span class="token punctuation">}</span> <span class="token keyword">new</span> <span class="token class-name">Notification</span><span class="token punctuation">(</span>title<span class="token punctuation">,</span> options<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Như trên, sau khi submit form, controller sẽ broadcast đến notifications_channel
. Sau đó hàm received
sẽ được thực hiện và call push notification lên.
Đến đây là đã xong. Vào localhost:3000 và chạy thử nhé!