Sunday 25 September 2016

Pinterest aunthentication and Posting on pinterest through RoR


In this blog, we will implement authentication with pinterest and posting on pinterset board.


We can divide it i  two parts. In first part we will do pinterest authentication and in second part we will do posting on pinterest -

1.) We can do pinterest authentication with gem 'omniauth-pinterest'

So, in Gemfile -


gem 'omniauth-pinterest'

After that in config/intializer/omniauth.b -


Rails.application.config.middleware.use OmniAuth::Builder do
# get appid and app_seceret from creating a developer account in pinterest
  provider :pinterest, ['app_id'], ['app_secret'], {:display => "popup"}
end

In routes.rb -


get '/auth/pinterest', as: 'pinterest-authentication'
# Here we are using oauths controller. Set callback url in pinterest developer account as https://localhost:3000/auth/pinterest/callback
get '/auth/pinterest/callback' => 'oauths#pinterest_callback', as: 'pinterest-callback'

Now in controller -


  def pinterest_callback
    token = request.env['omniauth.auth']['credentials']['token']
    pinterest_id = request.env['omniauth.auth'].uid
  end

Above method return token and pinterest id of pinterset user.

Now, we have all done with pinterest authentication.

In second part of the blog we will do pinterest posting.

To be continued ......

Sunday 18 September 2016

Checkbox tag with kaminari pagination



If you are using kaminari pagination with ajax and using check-box tag for selecting product there may be a problem in selection of product from different page because of pagination ajax it will select only products of last page.

In this situation, we can use jquery for updating the selected products.

In view page -
Here we have created a view of product listing with check-box tag and ajax pagination -


    <div class="product_list">
      <% if products.size > 0 %>
          <% products.each do |product| %>
              <div class="form-group">
                <%= check_box_tag "products[]", product.id, false, class: 'selected_product' -%>
                <%= image_tag(product.image_url, class: "list_pro_img") %>
                <%= link_to product.item_title, product.item_url, target: '_blank' %>
              </div>
          <% end %>
      <% else %>
          <p>Product is not found</p>
      <% end %>
    </div>
    <div id="paginator">
      <%= paginate @products, :remote => true %>
    </div>
    <%= submit_tag "Next", :class => "btn btn_next selected_post_product" %> 

Now we will update all the selected product from different page in products global variable of jquery -

So in custom.js -

function post_selected_products(){


    if (!Array.prototype.remove) {
        Array.prototype.remove = function(val, all) {
            var i, removedItems = [];
            if (all) {
                for(i = this.length; i--;){
                    if (this[i] === val) removedItems.push(this.splice(i, 1));
                }
            }
            else {
                i = this.indexOf(val);
                if(i>-1) removedItems = this.splice(i, 1);
            }
            return removedItems;
        };
    }

# In the above jquery we are removing items from array if product was unchecked after checked.
    products = [];
    $('div.product_list').on('change','input.selected_product',function(){
        if($(this).is(':checked')){
            var product_id = $(this).val();
            products.push(product_id)
        }else{
            var product_id = $(this).val();
            products.remove(product_id)
        }
# Now, we will post all the selected product on products controller -
        $.post('/products/selected_products', { product_ids: products});
    });



In view include above js -


<script type="text/javascript" charset="utf-8">
    post_selected_products()
</script>


In products controller -


def selected_products
    if request.xhr?
      # Here we will get all the selected products
      @products = params[:product_ids]
    end
end


Thats it !!!

Saturday 10 September 2016

Belongs_to Association in Devise Model Rails 5

Here, we are going to create a relationship between Account has_many user and user belongs_to account. User can create through Devise gem sign up.

So, in Gemfile -

gem 'devise'

Run the bundle command to install it.

$ bundle install

Next, you need to run the devise generator -


$ rails generate devise:install

Now, create a User model and configure it with the default Devise modules -


$ rails generate devise User

Then run

$ rake db:migrate

We have done set up of devise for user model -

Now, we will do association between Account and User Model.

In account.rb


class Account < ApplicationRecord
  has_many :users, inverse_of: :account, dependent: :destroy
end

In user.rb


class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  ######### Association####################
  belongs_to :account, inverse_of: :users
 
end


For this association we have to add refrence field of account_id in users table -

$ rails g migration add_account_id_to_users account_id:integer

Then run

$ rake db:migrate

Now, we have to override devise registeration controller for permit account_id params -

$ rails generate devise:controllers users registrations

In routes.rb

devise_for :users, controllers: {registrations: 'users/registrations'}

Now, we can permit the account_id params in registrations controllers -

In uncomment registrations controllers the follwing lines -

before_action :configure_sign_up_params, only: [:create]


 def create
    super
  end

 # account_id params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:account_id])
  end

Till now, we have ovveride the registrations controller and permit the extra params but when we will try to sign up a user it will through a exception of account id can't be blank.

For the handle above situation we have to assign the value of account_id in user table before creating user but before_create callback doesn't work in this condition due to validation of devise model. So we have to use before_validation.

In user.rb

 before_validation :create_account
 # Here we creating account and assing account_id to user
  def create_account
    account = Account.new(name: 'name')
    if account.save
      self.account_id = account.id
    end
  end




Friday 2 September 2016

Display a loading gif during Ajax request processing within rails

In this bog we will implement display a loading gif during Ajax request processing within rails.

HTML - In the view we will do product listing of the perticular user. While product will fetched from ajax request loading gif will be display.


<div class=""><h1>Product Listing</h1></div>
   <%= hidden_field_tag("user", current_user.id) %>
   <div class="loader">
     <i class="fa fa-refresh fa-spin fa-3x fa-fw"></i>
        <span>Loading...</span>
        <h2>Loading...</h2>
    </div>
  <div id="product_listing_div"></div>

Js - Now, we will send a ajax request to a controller's method for getting products for perticular user here we will send user params for that.

$(document).ready(function() {
    # Here ajax request is started on page load. You can create a condition for ajax request(ex- on click method).
        var user = $('#user').val();
        $.get(('/product_listing'), {user: user}, function(response) {
            if (response !== null) {
                $('.loader').hide();
            }
        });
    });


Controller -

def product_listing
    if request.xhr?
      user = params[:user]
      @products = Product.where(user: user).take
    end
  end

In view- Create product_listing.js.erb

$('#product_listing_div').html("<%= escape_javascript(render :partial => "product_listing", :locals => {:products => @products}) %>")

Create a partial view - _product_listing.html.erb


   
      <% if products.size > 0 %>
          <% products.each do |product| %>
              <div class="form-group">
                <%= image_tag(product.image) %>
                <%= product.title%>
              </div>
          <% end %>
      <% else %>
          <p>Product is not found</p>
      <% end %>

Css - for loading gif

.loader{
    text-align:center;
}
.loader .fa{
    font-size:100px;
    color:#25aae1 ;
}


That's it !!!!