How to send Basic Authentication (BA) credentials in ruby on rails

HTTP Basic authentication is a simple authentication scheme in which user authentication is done by a username and password eliminating the needs of cookies, sessions and login pages. It is base64 encoded.

Rails provides a method for this type of authentication: authenticate_with_http_basic

This method can be used as follows:

authenticate_with_http_basic do |username, password|
  ——
end

Inside the block you can access the username and password.

But how to send a request with basic auth in rails ?

This is really tricky and I didn’t find any documentation for this. Here I am describing how to send a request with basic auth.

1. Use Faraday library (Faraday is an HTTP client lib)
https://github.com/lostisland/faraday

Create a connection:

connection = Faraday.new(:url => HOST) do |faraday|
      faraday.request  :url_encoded             # form-encode POST params
      faraday.response :logger                  # log requests to STDOUT
      faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
      faraday.basic_auth(USERNAME, PASSWORD)
end

parameters = params[‘user’].permit!.to_h

response = connection.get do |req|
      req.url(params[:url])
      req.headers['Content-Type'] = 'application/json'
      req.params.merge!(parameters)
end

response = connection.post do |req|
        req.url(params[:url])
        req.headers['Content-Type'] = 'application/json'
        req.body = parameters
end

render json: response.body

Here,

HOST = 'http://lvh.me:3002'
USERNAME = 'EdcddzrbmET55016'
PASSWORD = 'UXBJnS309S49st3rHqmH5934'
params['url'] = '/users/profile'

We can use Faraday’s (‘faraday.basic_auth’) basic auth method to reach out our solution.

If you are getting any error like follows in post request

NoMethodError (undefined method `bytesize' for {}:ActiveSupport::HashWithIndifferentAccess):

Don’t forget to convert the ruby hash ‘parameters’ to json by calling ‘to_json’ upon it.

        req.body = parameters.to_json 

In Other way you can use something like this to generate the basic auth header

request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(USERNAME, PASSWORD)

How to use Ruby Rest Client:

require 'rest_client'

headers = {
  :authorization => 'Basic FytxhZGKpbjpvcGVuIHNlc2FtHUHU'
}

response = RestClient.get 'https://yourdomain.com/api/users.json?activityId=02ddf868-6484-440f-8c39-c7d4fb4e7b33', headers
puts response
Advertisements

Rbenv: Start with new ruby and rails versions

Check for the new ruby and rails versions
https://www.ruby-lang.org/en/downloads/
https://rubygems.org/gems/rails/versions

Suppose we are going to install Ruby – 2.4.1 & Rails – 5.1.3

Get rbenv into action

1. $ rbenv install --list # Gets the list of ruby versions available

$ rbenv install 2.4.1

ruby-build: definition not found: 2.4.1

The following versions contain `2.4.1' in the name:
  rbx-2.4.1

See all available versions with `rbenv install --list'.

If the version you need is missing, try upgrading ruby-build:

  brew update && brew upgrade ruby-build

Oops..!

rbenv cannot find the version: 2.4.1

Upgrade ruby-build

Mac:

$ brew upgrade ruby-build --HEAD

Now install ruby 2.4.1

$ rbenv install 2.4.1

Create a new gemset:

$ rbenv gemset create 2.4.1 demo-app
That set up a directory for you in ~/.rbenv/versions/2.4.1/gemsets/demo-app

Set the ruby version to the newest

$ rbenv local 2.4.1

$ rbenv version
=> 2.4.1

    Activate New Gemset


For activating a gemset we need to create a .rbenv-gemsets file in the current directory.

$ touch .rbenv-gemsets
$ echo demo-app > .rbenv-gemsets

Check active gemset:

$ rbenv gemset active

Install Rails 5.1.3

$ gem install rails -v '5.1.3'
$ gem install --no-rdoc --no-ri rails -v '5.1.3' # skips the documentation

Later we can delete this .rbenv-gemsets file and add a new file named ‘.ruby-gemset’ in the rails project directory. I cannot see any other good way of doing this. If anybody know about some other good way of doing this please give a comment.

Create a New Rails app

$ rails new demo-app

$ rm .rbenv-gemsets

$ cd demo-app
$ touch .ruby-gemset
$ echo demo-app > .ruby-gemset
$ touch .ruby-version
$ echo 2.4.1 > .ruby-version
$ rails s
=> Booting Puma
=> Rails 5.1.3 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.9.1 (ruby 2.4.1-p111), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop

Goto http://localhost:3000/

rails-5-new.png

Done! Lets go…

#Rails 4.2 #Ruby2.2 How to find association class and other info from an object and its association name

When I was doing something, I encountered one situation like: I need the association class of an object. I have the object and its association name as input. How can I find the association class?

Suppose we have Student class that belongs to a school

class School
  has_many students
end

class Student
  belongs_to :school
end

and so many other relations like this in my project.

So I have

s = Student.last
:school symbol 

in my hand

I can use

s.school.class and s.school.class.name

But what if the school is blank? The result is ‘NilClass’ From the above code.

Basically for has_many associations we gets the class name as

"ActiveRecord::Associations::CollectionProxy"

because recently in new versions rails changed the Array of objects as associations to its own ‘CollectionProxy’.

So we can use ‘ActiveRecord::Reflection::ClassMethods’ for finding all the association info.

This Rails module is so useful to find all the association related information.

In the above situation we can use ‘reflect_on_association’ method for finding association reflection info. And it returns ‘ActiveRecord::Reflection’ Object.

http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html#method-i-reflect_on_association

> s.class.reflect_on_association(:school)
=> ##<ActiveRecord::StatementCache:0x000000037a5c08 
@query_builder=#, @bind_map=#<ActiveRecord::StatementCache::BindMap:0x000000037a7238 
@indexes=[0], @bind_values=[[#
, #
]]>>}, @scope_lock=#
, @class_name="Topic", @foreign_key="school_id">

Set up capistrano deployment for Ruby On Rails

STEP 1:
Install capistrano gem

group :test, :development do
  gem 'capistrano'
end

Install capistrano with rvm

gem 'rvm-capistrano'

STEP 2:
Prepare your Project for Capistrano
Capify your project. The following command initialise your project with Capistrano.

$ capify .

STEP 3:
Do proper modificatons in Capistrano Recipe (config/deploy.rb)
http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html

Lets do the deployment for staging environment.
Create a ruby file under config/deploy/ folder named staging.rb
Copy the following content

set :domain, "mydomain.in"
role :app, domain
role :web, domain
role :db, domain, :primary => true
role :resque_worker, domain   # if you are using workers in your project, set role for them if needed
role :resque_scheduler, domain # if you are using workers in your project

set :deploy_to, "/home/my_deploy_path/"  # the deployment directory
set :environment, "staging"
set :rails_env, "staging"
set :branch, "staging"
set :previous_environment, "develop"

STEP 4:
Setup capistrano in deployment server

$ cap staging deploy:setup

This will Create folder structure that capistrano uses in the process.

Make sure that everything is set up correctly on the server by the command

$ cap staging deploy:check

Now you can see a message like:
“You appear to have all necessary dependencies installed”

Create shared/config folder in your deploy_to path
and copy database.yml and other config files as you written in the symlink_shared task in cap recipie (if any)

STEP 5:
Deploy your project:

cap staging deploy

How to categorise a blog posts data by month in Ruby On Rails

Suppose we created a ‘BlogPost’ Model in Rails and we have the following fields in a blog post:

title – title of the blog post
posted_on – date posted
permalink – a permanent link of each blog post (act as a primary key)
publish – a boolean field which decides the post need to show or not

Lets write a method in ‘BlogPost’ Model to get a recent list of posts.
Pass a ‘months_old’ parameter to determine how much months old posts we wanted to list.
Just select the required columns to show the details of the post (by ‘:select => ‘). And Group each post by posted month.

  def self.get_recent_months_post(months_old)
    @blog_posts = where("publish = ? AND posted_on > ?", true, Date.today - months_old.months).all(:select => "title, posted_on, permalink", :order => "posted_on DESC")
    (@blog_posts.group_by { |t| t.posted_on.beginning_of_month }).sort.reverse
  end

We successfully written the method above. Now lets write a method to get the archives (old posts).

  def self.get_archives(old)
    @blog_posts = where("publish = ? AND posted_on  "title, posted_on, permalink", :order => "posted_on DESC")
    (@blog_posts.group_by { |t| t.posted_on.beginning_of_month }).sort.reverse
  end

How to create a migration file dynamically from a rake task or a lib file in rails 4.0

If you want to add a migration file from lib file or somewhere from your ruby file and execute it, use the dynamic method which can create a class or method dynamically. The following code snippet is not complete. But gives a better idea to create migration file dynamically. Use a bit of metaprogramming.

 def create_columns(tb_with_cols)
    .........
    .........
    columns.each { |column| add_columns << "\tadd_column(':#{tb_name}', :#{column})\n" }
    columns
 end

 def migration_file_content(tb_with_cols)
<<-RUBY
  class AddMissingColumnsToTable < ActiveRecord::Migration
     def change_table
    #{create_columns(tb_with_cols)}
   end
 end
  RUBY
 end


 def write_content_to_file(path, content)
    File.open(path, 'w+') do |f|
      f.write(content)
    end
 end

Just call the method ‘migration_file_content’ in your code. Pass the parameter tb_with_cols as a Hash whose key is the table_name and value is the columns that should be added to that table like:

tb_with_cols = {:users => {:name => :string, :age => :integer, :address => :text} }

After that just call the method ‘write_content_to_file’ with your new migration file path and the content from our ‘migration_file_content’ method. 🙂

Rails way of creating a new full url with new parameters after removing old parameters from a url

If we have some keys and values and we just need to create a url with this data just pass the url and hash as a parameter to the following method.

def generate_url_with_params(url, params = {})
    uri = URI(url)
    uri.query = params.to_query
    uri.to_s
end

If you want to get rid of the parameters from a url use the following method.

  def generate_url_without_params(url, params = {})
    uri = URI(url)
    full_params = Rack::Utils.parse_query uri.query
    params.each do |key, val|
      full_params.delete key
    end
    uri.query = full_params.to_param
    uri.to_s
  end