Pages

Wednesday, December 10, 2014

Model Concerns in Rails 4

Concerns in Model can be used to skin-nize fat models as well as DRY up your model codes. Here is an explanation with examples:


Consider a Article model, a Event model and a Comment Model. A article or A event has many comments. A comment belongs to either article or event.
Traditionally, the models may look like this:
Comment Model:
class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end
Article Model:
class Article < ActiveRecord::Base
  has_many :comments, as: :commentable 

  def find_first_comment
    comments.first(created_at DESC)
  end

  def self.least_commented
   #return the article with least number of comments
  end
end
Event Model
class Event < ActiveRecord::Base
  has_many :comments, as: :commentable 

  def find_first_comment
    comments.first(created_at DESC)
  end

  def self.least_commented
   #returns the event with least number of comments
  end
end
As we can notice, there is a significant piece of code common to both Event and Article Model. Using concerns we can extract this common code in a separate module Commentable.

Wednesday, December 3, 2014

Adding Password Complexity Validations To Devise

Here we have a typical Devise user model. What’s new is the password complexity validation.
class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
  attr_accessible :email, :password, :password_confirmation, :remember_me,

  validate :password_complexity

  def password_complexity
    if password.present? and not password.match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d). /)
      errors.add :password, "must include at least one lowercase letter, one uppercase letter, and one digit"
    end
  end
end

Friday, November 21, 2014

Simple, user-friendly cancel links for your Rails forms



The default Rails view generator includes back links on form-related view templates, so if users change their mind they can easily get out of the form and on to something else. However, these links are static. What do you do if you allow users to access the form from multiple views (say, an index and a show).
Here’s a simple but effective solution I came up with: Instead of passing a static URL, I pass the HTTP referrer environment variable as the location. That way users are taken back to the page from which they opened the form to begin with.
Here’s how it works. Most of the code resides in the application_helper.rb file:
  module ApplicationHelper
    include Rails.application.routes.url_helpers

    def cancel_link
      return link_to 'Cancel', request.env["HTTP_REFERER"], 
        :class => 'cancel', 
        :confirm => 'Are you sure? Any changes will be lost.'
    end
  end
You’ll need to include Rails.application.routes.url_helpers in order to access link_to from a helper method. Then you add the helper method itself, which does nothing more than return a cancel link. Mine uses an old-style :confirm message; you can spruce it up with some less obtrusive if you’d like.
If I need a cancel link in a view, I just add
  <%= cancel_link %>
The result: a flexible, reusable cancel option that’s much more user-friendly.

Wednesday, May 28, 2014

Counters for Partials

Sometimes I like to number rows using a counter when rendering lists of things:
<% @products.each_with_index do |product, i| %>
  <li class="product_<%= i %>"><%= product.name %></li>
<% end %>
They are handy for testing, among other things.
Of course, if the content of the block gets too big I’ll factor it out into a partial. The idiomatic Rails way of doing this is to factor the block contents out into a partial and then render it with the :collectionoption:
< %= render :partial => "product", :collection => @products %>
Which is very clean, except now where do we get our row counter? As it turns out, Rails provides one for us:
  <li class="product_<%= product_counter %>"><%= product.name %></li>
Note the use of product_counter. Rails takes the name of the partial and adds _counter to it when providing the built-in counter.

Thursday, May 15, 2014

Copy a file from your system to EC2 Server with port and pem file



Here is command for Copying a file from your system to EC2 Server with port and pem file:

scp -P <PORT> -i xyz.pem  /home/user/file.txt  ec2-user@host:/home/ec2-user/

Below are the all available options that you can use based on your requirements:

scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-S program] [[user@]host1:]file1 ... [[user@]host2:]file2

Monday, May 12, 2014

Irreversible Migrations in Ruby on Rails

In Rails 2 in migrations there were only 2 methods: up and down. They are called on running migrations up and down respectively with rake tasks rake db:migrate and rake db:rollback.

In Rails 2

def up
add_column :users, :active, :boolean User.update_all(active: true) end

def down remove_column :users, :active end

Rails 3 produced us great method change which allowed us to write there code which creates a table and drops the table automatically on rolling migration back. But unfortunately there was a problem – you didn’t have opportunity to say “don’t run this peace of code on down but run this only on up”. So the solution was just to use old syntax. 

Thursday, May 1, 2014

Ruby remove duplicate entries in array of hashes but based on more than one value

Suppose you have the following array of hashes:

new_tracks = [{:name=>"Yes, Yes, Yes", :artist=>"Some Dude", :composer=> 'First Dude', :duration=>"3:21"},
 {:name=>"Chick on the Side", :artist=>"Another Dude", :duration=>"3:20"},
 {:name=>"Luv Is", :duration=>"3:13"},
 {:name=>"Yes, Yes, Yes", :artist=>"Some Dude", :composer=> 'First Dude', :duration=>"2"},
 {:name=>"Chick on the Side", :artist=>"Another Dude"}]

uniq accepts a block. If a block is given, it will use the return value of the block for comparison.
You can join the attributes you want into a string and return that string.

new_tracks.uniq { |track| [track[:name], track[:artist]].join(":") }

The resultant of above code will be an array of hashes unique on the basis of name and artist attributes.

Wednesday, April 30, 2014

Configure Authlogic to log in with “username” OR “email”



Its very simple to implement Authlogic to use multiple attributes for login.

For example if you want to enable user to login with either email or username, you just need to add the following things to your code:

class UserSession < Authlogic::Session::Base 
  find_by_login_method :find_by_username_or_email
end
and in user.rb
def self.find_by_username_or_email(login)
  User.find_by_username(login) || User.find_by_email(login)
end

Thursday, April 24, 2014

How to change root password of Mysql to an empty one or blank?


You should first restart the MySQL server or run the following command:
FLUSH PRIVILEGES;
 Now change the root password to an empty one:
mysqladmin -u root -p'<current password>' password ''
Now your password is updated to blank.

Fix String Encoding error with Mysql



The reason was apparently that the database (and especially the database tables) had the wrong character set. Switching the collation of the database alone did not help. Inspection of the database tables showed that each table still had the latin1 charset, which can not store all utf8 characters:
mysql> show table status;
+----------+--------+-------------------+ ..
| Name     | Engine | Collation         | ..
+----------+--------+-------------------+ ..
| my_table | InnoDB | latin1_swedish_ci | ..
Therefore I altered the character set of the table directly:
ALTER TABLE my_table CONVERT TO CHARACTER SET utf8;
Then it finally worked, and the character set is how utf8
   mysql> show table status;
    ... +-------------------+ ..
    ... | Collation         | .. 
    ... +-------------------+ ..
    ....| utf8_general_ci   | ..

Thursday, January 30, 2014

API Upload with CarrierWave

 I want to share a quick snippet with regards to a problem I had a few months ago: How to upload a picture/file to a Ruby on Rails project, which is utilizing CarrierWave to handle the upload mechanism, by utilizing the direct POST call.
With this comes at least two challenges:
  • You cannot insert a file directly into a JSON object;
  • CarrierWave does not support uploading a file which is not uploaded using a form object.
Solving the first problem is almost trivial, you simply encode the file into Base64 and pass it along, but the second problem requires a little more work. What I did to solve it was to decode the Base64 string into a temp file, and then create a new uploaded file from that temp file.

Saturday, January 11, 2014

Fixing readline for the Ruby on Rails console

have begun trying out the Ruby on Rails framework. While doing so I got stuck at a very early stage in thedocumentation.
$ rails console
/home/tobias/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/irb/completion.rb:9:in `require': no such file to load -- readline (LoadError)
from /home/tobias/.rvm/rubies/ruby-1.9.2-p18080/lib/ruby/1.9.1/irb/completion.rb:9:in `<top (required)>'
from /home/tobias/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.9/lib/rails/commands/console.rb:3:in `require'
from /home/tobias/.rvm/gems/ruby-1.9.2-p180/gemsems/railties-3.0.9/lib/rails/commands/console.rb:3:in `<top (required)>'
from /home/tobias/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.9/lib/rails/commands.commandsrb:20:in `require'
from /home/tobias/.rvm/gems/ruby-1.9.2-p180/gems/railsilties-3.0.9/lib/rails/commands.rb:20:in `<top (required)>'
from scriptt/rails:6:in `require'
from script/rails:6:in `<main>'
The problem is that Ruby is somehow not cofigured to load the readline library and thus cannot run its console. This is a downside of using a language specific package manager, seperate from your operating system's package manager.

Friday, January 10, 2014

Rails- :dependent => :destroy VS :dependent => :delete_all

In rails guides it's described like this:
Objects will be in addition destroyed if they’re associated with :dependent => :destroy, and deleted if they’re associated with :dependent => :delete_all
But what's the difference between being destroyed and being deleted?
The difference is with callback.
The :delete_all, made directly in your application the delete by SQL :
DELETE * FROM users where compagny_id = XXXX
With the :destroy, there are an instantiation of all of you children. 
So, if you can't destroy it or if each has their own :dependent, its can be called.

Use after_commit instead of active record callbacks to avoid unexpected errors

AR callbacks after_create/after_update/after_destroy to generate background job etc are useful, but these callbacks are still wrapped in database transaction, and you may probably get unexpected errors on production servers.
Before It’s common to generate a background job to send emails like
class Comment < ActiveRecord::Base
  after_create :asyns_send_notification
  def async_send_notification
    Notifier.send_new_comment_notification(self).deliver
  end
 handle_asynchronously :async_send_notification
end

# It looks fine that comment record passed to delayed job and then delayed job will fetch this
#comment and then post on which this comment has been made and a notification will
#send via email to the author of that post. Right?
You won’t see any issue in development, as local db can commit fast. But in production server, db traffic might be huge, worker probably finish faster than transaction commit. e.g
  1. main process
  2. worker process
  3. BEGIN
     INSERT comment in comments table
     # return id 10 for newly-created notification
     SELECT * FROM notifications WHERE id = 10
     COMMIT
    
In this case, the worker process query the newly-created notification before main process commits the transaction, it will raise NotFoundError, because transaction in worker process can’t read uncommitted notification from transaction in main process.
Refactor
So we should tell activerecord to generate notification worker after notification insertion transaction committed.
class Comment < ActiveRecord::Base
after_commit :asyns_send_notification,:on => :create  # This is the main point of the whole thing.

  def async_send_notification
    Notifier.send_new_comment_notification(self).deliver
  end
 handle_asynchronously :async_send_notification
end
Now the transactions order becomes
  1. main process
  2. worker process
  3. BEGIN
     INSERT comment into comments_table
     return id 10 for newly-created notification
     COMMIT
     SELECT * FROM notifications WHERE id = 10
    
Worker process won’t receive NotFoundErrors any more. :)
For More Details visit http://www.codebeerstartups.com