Thursday, 26 October 2017

MS SQL Server on Ubuntu with Rails 5 + TinyTDS & activerecord-sqlserver-adapter

Run SQL Server on your favorite platform Im choosing Linux - ubuntu

Start by going to the below page
By clicking Try now will take it to below url
choose Install on Ubuntu Linux 16.04 ->
follow the steps given below the “ Install SQL Server and create a database on Ubuntu “

Prerequisites

You must have a Ubuntu 16.04 machine with at least 3.25 GB of memory.
Same step listing here as well.
  1. Import the public repository GPG keys:
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -


2. Register the Microsoft SQL Server Ubuntu repository:
sudo add-apt-repository “$(curl https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2017.list)"


the4.After the package installation finishes, run mssql-conf setup and follow the prompts to set the SA password and choose your edition.
sudo apt-get update
sudo apt-get install -y mssql-server
a. Choose respective edition
b. Choose respective language
c. Set password


5. Once the configuration is done, verify that the service is running:
sudo /opt/mssql/bin/mssql-conf setup


At this point, SQL Server is running on your Ubuntu machine and is ready to use!
systemctl status mssql-server
At this point, SQL Server is running on your Ubuntu machine and is ready to use!
In rails application add list of gems into Gemfile and bundle it.
gem 'tiny_tds', '~>2.0.0'gem 'activerecord-sqlserver-adapter'
if fails and ask for
“ An error occurred while installing tiny_tds (2.0.0), and Bundler cannot continue. Make sure that `gem install tiny_tds -v ‘2.0.0’` succeeds before bundling.
then do the listed below to solve the issue
sudo apt-get install wget
sudo apt-get install build-essential
sudo apt-get install libc6-dev
sudo wget http://www.freetds.org/files/stable/freetds-1.00.21.tar.gz
sudo tar -xzf freetds-1.00.21.tar.gz
cd freetds-1.00.21
sudo ./configure — prefix=/usr/local — with-tdsver=7.3
make
sudo make install
Few Reference link:
when you get error like below run the below command
/var/lib/gems/2.3.0/gems/tiny_tds-2.0.0/lib/tiny_tds.rb:41:in `require': libsybdb.so.5: cannot open shared object file: No such file or directory - /var/lib/gems/2.3.0/gems/tiny_tds-2.0.0/lib/tiny_tds/tiny_tds.so (LoadError)
 from /var/lib/gems/2.3.0/gems/tiny_tds-2.0.0/lib/tiny_tds.rb:41:in `<top (required)>'
/sbin/ldconfig /usr/local/lib
Now setup the database.yml
default: &default
  adapter: sqlserver
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000
  host: localhost
development:
  <<: *defaultYes !!! you are done!!
  database: rails_sample_development
  username: sa 
  password: password given while setting up the mssql server
run rake db:create
start the rails server
Yes!! you are done

Sunday, 8 October 2017

Handling email scheduling by day, time and timezone

I’m going to share my experience of scheduling task using


a. cron job
b.sidekiq
c.sidekiq-scheduler
d.redis
Triggers every hour and look for the day, time and start schedule by timezone.
In detail i’m sharing my problem statement to understand better.
There is a TV channel and its subscribers. The subscriber will be receiving email at starting of the program and ending of the program. My Job is to trigger two emails which are at start time and end time of a particular day, time and location by considering the timezone.
Example
User : John,
Timezone : Asia/Singapore,
start time : 21:02:55 SGT +08:00
end time : 22:02:55 SGT +08:00
days : Monday, TuesDay, Friday

User : Alice
Timezone : Asia/Calcutta
start time : 18:31:13 IST +05:30
end time : 19:31:13 IST +05:30
days : Friday, Sunday



John is at Singapore timezone and he should be receiving the start time email at 21:02 and end time email at 22:02 on Monday, Tuesday, Friday. Similar for Alice.
a. cron to schedule jobs that run every hour
b. Group the list of data by timezone. Result looks like key and values. Key is timezone and values are subscriber list.
c. Loop through the list(timezone), again loop the values and get current dayat time zone, check it for days include current day.
For example days to send email for John is [Monday, Tuesday, Friday]. So current day is Friday look for Friday inside John’s day list.
d. If it does n’t include the day, skip it.
e. If it includes then look for (current_time start_time) leave it if false. If true then look for the status. Here we have status to tract the job has scheduled or started or completed.
f. If status is scheduled or started then leave it. Meaning is that job has already scheduled. Remember cron runs for every hour.
g. If status is completed which means it’s ready for scheduling.
h. Now we are ready to schedule a new job and executing at background using gem ‘sidekiq and gem ‘sidekiq-scheduler’.
Worker.perform_in(start_time, 'send_start_email')
Scheduling the stop email at same time.
Worker.perform_in(end_time, 'send_stop_email')
Updating the status and job id for future reference. It’ll be helpfull if scheduling is changed once Job is scheduled.

Handling the job once job is Scheduled.



Scenario one : Job is scheduled and didn’t start
I mentioned that each job id is stored for future reference.
By using the job ids (start and end job ids) we ‘ll able to find the scheduled job and delete it. Again look for updated days, time and same process mentioned above.
Scenario two : Job is scheduled and started (start email has been sent)
By using the job id (end job id) we’ll able to find the end scheduled job,delete it and send the email at same time saying ended now. Again look for updated days, time and same process mentioned above.
Scenario three : Job is scheduled, started and ended.
No need to look for job ids. It’ll be updated and scheduled.
Scenario four : Job is not scheduled.
No need to look for job ids. It’ll be updated and scheduled.

Must Have Ruby Gems and setups

Production Environment
For database/codebase backup
gem backup - Easy full stack backup operations on UNIX-like systems
For Log file backup
Log Rotate - Keep your log files in check as time goes on and make sure they don’t fill up your server’s disk space (log rotate)
For Exception tracking and logging
gem rollbar - Exception tracking and logging from Ruby to Rollbar
Rack middleware for blocking & throttling abusive requests
gem rack-attack - Rack::Attack is a rack middleware to protect your web app from bad clients. It allows safelistingblocklistingthrottling, and trackingbased on arbitrary properties of the request.
Development Environment
For debugger
gem pry - An IRB alternative and runtime developer console
For N+1 queries
gem bullet - help to kill N+1 queries and unused eager loading
For soft delete
gem Paranoia - When your app is using Paranoia, calling destroy on an ActiveRecord object doesn't actually destroy the database record, but just hides it.
For security vulnerability
gem brakeman - Brakeman is an open source static analysis tool which checks Ruby on Rails applications for security vulnerabilities.
List of things to be cared before going live
  • Tests passing?
  • SSL Certificates
  • Check it through webpagetest.org for problematic load times
  • Set up any workers and autoscalers
Listed few and I’m planning to add more when I come across with useful gems.
Readers please comment with the gem list, which you feel like must have.

Why rails5 update_attributes doesn’t but Update method does?

Rails version:
Rails 5.1.1
Ruby Version:ruby-2.4.0 [ x86_64 ]
Local Server:Puma starting in single mode…
* Version 3.9.1 (ruby 2.4.0-p0), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
I have a existing model called User and later I added the attribute last_name.
Then trying to update the newly created field(last_name) with other fields by rails method called

 User.update_attributes(first_name: ‘praaveen’, last_name:’vr’)
For update_attributes
This updates only first_name field and leave the last_name attribute.
rails log:
UPDATE “users” SET “updated_at” = $1, “first_name” = $2 WHERE “users”.”id” = $3 [[“updated_at”, “2017–09–20 14:19:26.174311”], [“first_name”, “praaveen”], [“id”, 156]]
Then tried with
User.update(first_name: ‘praaveen’, last_name:’vr’)
 User.update_columns(first_name: ‘praaveen’, last_name:’vr’)
These methods updates first_name and last_name as expected.
rails log:
 UPDATE “users” SET “updated_at” = $1, “first_name” = $2, “last_name” = $3 WHERE “users”.”id” = $4 [[“updated_at”, “2017–09–20 14:15:23.623292”], [“first_name”, “praaveen”], [“last_name”, “vr”], [“id”, 156]]
Any idea what’s going?

Pushmeup gem for IOS push notification rails5

This gem is a wrapper to send push notifications to devices. Currently it only sends to Android or iOS devices, but more platforms will be added soon. With APNS (Apple Push Notifications Service) you can send push notifications to Apple devices. With GCM (Google Cloud Messaging) you can send push notifications to Android devices.
Im not going to cover the Android part.
add it to Gemfile
gem ‘pushmeup’
APNS (Apple iOS)
Configure (mobile side)
In Keychain access export your certificate and your private key as a p12.
![Keychain Access](
https://raw.github.com/NicosKaralis/pushmeup/master/KeychainAccess.jpg)
Run the following command to convert the p12 to a pem file
$ openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts
Configure (server(rails) side)
a. After you have created your pem file.
b.Set the host, port and certificate file location on the APNS class. You just need to set this once:
create a file called push_me_up.rb and env.yml(files names are not mandatory to be same name and check if you already have the file for environment variable)

push_me_up.rb

 APNS.host = ENV[“APNS_HOST”]
APNS.port = 2195
 # this is also the default. Shouldn’t ever have to set this, but just in case Apple goes crazy, you can.
APNS.pem = Rails.root/ENV[“APNS_PEM”]
 # this is also the default. Shouldn’t ever have to set this, but just in case Apple goes crazy, you can.
APNS.pass = ENV[“APNS_PASS”]

 env.yml
APNS_HOST: gateway.push.apple.com
 # gateway.sandbox.push.apple.com is default and only for development
 # gateway.push.apple.com is only for production
APNS_PEM: pem_file.pem

 APNS_PASS: password
 # Just in case your pem need a password
Now, configurations are over and we will start using it
Usage
Sending a single notification(inside controller or service or worker any where*):
device_token = ‘123abc456def’
 APNS.send_notification(device_token, ‘Hello iPhone!’ )
 APNS.send_notification(device_token, :alert => ‘Hello iPhone!’, :badge => 1, :sound => ‘default’)
Sending multiple notifications and other options please refer the link (pushmeup)

Wednesday, 2 August 2017

Rails 5.1 with webpack and api-ai SDK

Here we are going to see how to use webpacker with rails application and adding one javascript SDK with rails application.

Webpack

Here webpack takes modules with dependencies and generates static representing those modules.

reference link

https://webpack.github.io/docs/what-is-webpack.html



Let we start with step by step Processes


a.Create new rails repo with webpacker
rails new myapp --webpack

b. File called package.json is created inside the myapp(rails repo) with content


{
  "name": "chat_bot",
  "private": true,
  "dependencies": {}
}

c. Add required javascript lib inside the  package.json under 
dependencies. 
here we are adding the api.ai SDK into package.json

ex: 

{
  "name": "chat_bot",
  "private": true,
  "dependencies": {
    "api-ai-javascript" : "~> 2.0.0-beta.21"}

}

d. Once this added please run npm install at myapp(rails repo) 
directory level. 

e. Make sure to require "api-ai-javascript"  at application.js or 
where ever you required.

f. Now javascript web SDK for API.ai is available throughout the project


Note : If you are using less then the rails5.1 then the way of 
adding the SDK will be different. Please look into reference link. 

Reference link

https://github.com/rails/webpacker

https://github.com/api-ai/apiai-javascript-client


Sunday, 30 July 2017

Rails5 application with Push Notification using FCM for Android

Part One for Android

Gem used
a.fcm

Support

a. Android
b. IOS


Here we are going to see how push notification can be sent to android using fcm. Same fcm gem can be used for ios as well.

a. Add it to gem file and run bundle


#for push notification for ios and android 
 gem 'fcm'


b. Next add project to firebase 
(mobile developers will understand the process)

  1. visit https://console.firebase.google.com
  2. create a new project with required info(ex: project name)   
  3. Asks for  
      a.Add Firebase to your iOS app
      b.Add Firebase to your Android app
   here we go with android and fill the fields 
      a. Android package name
      b. Download config file
      c. Add Firebase SDK   
   Please do all required steps to get
      a. Server key   
      b. Legacy server key
      c. registration_ids/device token of every user who receives 
         the push notification  
 
c. Here i'm writing push notification as a separate service.Basically
 an api service. So my code goes here 

 /controller/api/PushNotifiactionService/push_notification.rb


  
require 'fcm'
fcm = FCM.new("Legacy server key") Ex: AIzaSydsfds324asfdsfdsf
# get it from project settings - cloud messaging 
registration_ids= ["fgf4yaJ64E:APA91bfsfds...", "EaIbj_2oGkR7JXi..."]  
#mobile end will provide you the ref_ids to whom shoulbe received
options = {data: {student_count: "50"}, collapse_key: "updated_count"}
#message content to sent in push notifiaction
response = fcm.send(registration_ids, options)
#sending push notifaiction

d. Add it to config/application.rb
config.autoload_paths += %W(#{config.root}/app/controllers
/PushNotificationService/PushNotification)
That's it



Reference Link :

a. https://github.com/spacialdb/fcm