Tuesday, 25 September 2012

Solution: Make Use of Rails Serialization

Solution: Make Use of Rails Serialization


There are some important topic

  • Never build beyond the application requirements at the time you are writing the code.
  • If you do not have concrete requirements, don't write any code.
  • Don't jump to a model prematurely; there are often simple ways, such as using Booleans and denormalization, to avoid using adding additional models.
  • If there is no user interface for adding, removing, or managing data, there is no need for a model. A denormalized column populated by a hash or array of possible values is fine.










Figure : A form that enables a user to select multiple values for an item, including other.

Above figure, shows a registration form where the user is asked to select the one or more ways he/she heard about the organization. A user who selects Other should fill in the "other" text input field. This is a fairly common interface, and you can model it in a few different ways, using Active Record models.

"Has" and "Belongs to Many"
The first way to model the user interface shown in figure is to normalize the possible "heard about" values into a referral model that is related to the user  with a "has and belongs to many" relationship:

class Referral < ActiveRecord::Base
  has_and_belongs_to_many :users
end

In, addition, User has a string attribute, referral_other, that stores the value typed into the "other" input field.

"Has Many"
The second way to model the user interface shown in the figure would be to not join the User and Referral models together with a "has many" relationship and not normalize the content of the Referral model. The model code for this would look as follows:

class User < ActiveRecord::Base
  has_many :referral_types
end

class Referral < ActiveRecord::Base
  VALUES = ['Newsletter','School','Web','Partners/Events','Media','Other']
  validates :value, :inclusion => {:in => VALUES}

  belongs_to :user
end

In addition, the User model would once again have a string attribute, referral_other, used for storing the value typed into the "other" input field.


Monday, 24 September 2012

Solution : Denormalize into Text Fields

Solution : Denormalize into Text Fields

Take a look at the following Article model and the associated State and Category models:

class Article < ActiveRecord::Base

  belongs_to :state
  belongs_to :category

  validates :state_id,         :presence => true

  validates :category_id,  :presence => true
end

class State < ActiveRecord::Base

  has_many :articles
end

class Category < ActiveRecord::Base

  has_many :articles
end

Given these models, the specific set of available states and categories would be loaded into the production application's respective database tables, and code for working with these associations would be as follows:


@article.state = State.find_by_name("published")


Of course, repeating the finder and the string for the published state is bad practice, so it might be wise to abstract that out into a custom finder on the State model:


@article.state == State.published


The code for dynamically defining these custom finder methods might be as follows:


class State < ActiveRecord::Base

  validates :name => :presence => true
  class << self
    all.each do |state|
      define_method "#{state}" do
        first(:conditions => { :name => state })
      end 
    end
  end
end

There is quite a bit of functionality associated with these types of models (states, categories, and so on) and, therefore, it's not desirable to allow end users or even administrators - to add or remove available states in the database. 


For Example, if the article publication workflow changes and a new state needs to be added, it's unlikely that an administrator can simply add the state to the database and have everything as desired.


You would denormalize the data from the state and category tables into the article table itself, and you would remove the State and Category models. 


When you do all this, the Article model looks as follows:


class Article < ActiveRecord::Base

  STATES = %W(draft review published archived)
  CATEGORIES = %w(tips faqs misc)

  validates :state,         :inclusion => {:in => STATES}

  validates :category,  :inclusion => {:in => CATEGORIES}

  STATES.each do |state|

    define_method "#{state}?" do
      self.state == state
    end
  end

  CATEGORIES.each do |category|

    define_method "#{category}?" do
      self.category == category
    end
  end

  class << self

    STATES.each do |state|
      define_method "#{state}" do
        state
      end
    end
   
    CATEGORIES.each do |category|
       define_method "#{category}" do
          category
       end
    end

  end


end


As you can see, the total code shown here for the normalized version is very similar to the code for the denomalized version. The dynamic methods are still being defined but the difference here is that the Article model now has state and category columns that contain a string representing the state instead of foreign key columns to hold the ID of the State and Category.


Learn and Love the Scope Method

Learn and Love the Scope Method

If you want to optimize your code and minimize the complexity we can increasing the opportunity for code reuse is by leveraging the Active Record scoping methods.

For Example

class RemoteProcess < ActiveRecord::Base
  def self.find_top_running_processes(limit=5)
    find(:all, 
            :conditions => "state = 'running'",
            :order => "percent_cpu desc",
            :limit => limit)
  end


 def self.find_top_running_system_processes(limit=5)
  find(:all,
          :conditions => "state = 'running' and ( owner in ('root', 'mysql') )",
          :order => "percent_cpu desc",
          :limit => limit)
 end
end



We can clean up this method and make the components reusable by employing named scopes. The scope method defines class methods on your model that can be chained together and combined into one SQL query.

A scope can be defined by a hash of options that should be merge into the find call or by a lambda that can take arguments and return such a hash.

When you call a scope, you get back an ActiveRecord::Relation object, which walks and talks just like the array you would have gotten back from find.

You could use scopes as follows the rewrite the preceding finder:


class RemoteProcess < ActiveRecord::Base
  scope :running, where(:state => 'Running')
  scope :system,    where(:owner => ['root','mysql'])
  scope :sorted,     order("percent_cpu desc")
  scope :top,          lambda {|1| limit(1) }
end

RemoteProcess.running.sorted.top(10)
RemoteProcess.running.system.sorted.top(5)


We can shore this up nicely by wrapping the chain in a descriptive class method:

class RemoteProcess < ActiveRecord::Base
  scope :running, where(:state => 'Running')
  scope :system,    where(:owner => ['root', 'mysql'])
  scope :sorted,     order("percent_cpu desc")
  scope :top,          lambda { |1| limit(1) }

  def self.find_top_running_processes(limit=5)
   running.sorted.top(limit)
  end

  def self.find_top_running_system_processes(limit=5)
    running.system.sorted.top(limit)
  end
end

Example 2

Now we've taken a quick look at basic scope usage, let's return to the original problem of writing advanced search methods.

For Example

class Song < ActiveRecord::Base
  def self.search(title, artist, genre, published, order, limit, page)
    condition_values = { :title => "%#{title}%", 
                                       :artist => "%#{artist}%", 
                                       :genre => "%#{genre}%"
                                     }
    case order
    when "name"  :   order_clause = "name DESC"
    when "length" :   order_clause = "duration ASC"
    when "genre"  :   order_clause = "genre DESC"
    else
       order_clause = "album DESC"
    end
    joins = []
    conditions = []
    conditions << "(title LIKE ':title')" unless title.blank?
    conditions << "(artist LIKE ':artist')" unless artist.blank?
    conditions << "(genre LIKE ':genre')" unless genre.blank?

    unless published.blank?
      conditions << "(published_on == :true OR published_on IS NOT NULL)"
    end

    find_opts = { :conditions => [ conditions.join("AND"), condition_values ],
                           :joins => joins.join(''),
                           :limit => limit,
                           :order => order_clause }

   page = 1 if page.blank?
   paginate(:all, find_opts.merge(:page => page, :per_page => 25))
  end
end

we can clean up the preceding method by employing scopes as follows:

class Song <  ActiveRecord::Base
  def self.top(number)
    limit(number)
  end

  def self.matching(column,value)
     where(["#{column} like ?, "%#{value}"])
  end

  def self.published
    where("published on is not null")
  end

  def self.order(col)
    sql = case col
                when "name" : "name desc"
                when "length"  : "duration asc"
                when "genre" : "genre desc"
                else "album desc"
             end
       order(sql)
  end

  def self.search(title, artist,genre, published)
   finder = matching(:title, title)
   finder = finder.matching(:artist, artist)
   finder = finder.matching(:genre, genre)
   finder = finder.published unless published.blank?
   return finder
  end

  Song.search("fool", "billy", "rock", true).order("length).top(10).paginate(:page => 1)
end

While this re-implementation using scopes reduces the code size somewhat, the real benefits are elsewhere

Scope object instead of a results array:

class Song < ActiveRecord::Base
  has_many :uploads
  has_many :users, :through => :uploads

  # top and order are implemented the same as before,
  # using named_scope...

  def self.search(title, artist, genre, published)
    finder =            where(["title LIKE ? ", "%#{title}%"])
   finder =  finder.where(["artist LIKE ? ", "%#{artist}%"])
   finder =  finder.where(["genre LIKE ? ", "%#{genre}%"])
   unless published.blank?
     finder = finder.where("published_on is not null")
   end
  return finder
  end
end


Friday, 21 September 2012

Keep Finders on Their Own Model

Keep Finders on Their Own Model

Moving the find calls out of the controller layer in your Rails application and into custom finders on the model is a strong step in the right direction of producing maintainable software.

For Example

Optimize(1)

class UsersController < ApplicationController
  def index
    @user = User.find(params[:id])
    @members = @user.members.where(:active => true).limit(5).order("last_active_on DESC")
  end
end

We know that we diligently move that scope chain into a method on the User model.
Now If we write code in Model then

Optimize(2)

class UsersController < ApplicationController
  def index
    @user = User.find(params[:id])
    @recent_active_members = @user.find_recent_active_members
  end
end

In User Model

class User < ActiveRecord::Base
  has_many :members
  
  def find_recent_active_members
    memberships.where(:active=>true).limit(5).order("last_active_on DESC")
  end
end

This is definitely an improvement. UsersController is now much thinner, and the method name reveals intent nicely. But you can do more...

By making use of the power of Active Record associations, you can trim up this example even further. You can define a finder on member, and you can then acess that finder through the User#members association, as follows:

Optimize(3)

class User < ActiveRecord::Base
  has_many :members
  def find_recent_active_members
    member.find_recently_active
  end
end

class Member < ActiveRecord::Base
  belongs_to :user
  def self.find_recently_active
    where(:active=>true).limit(5).order("last_active_on DESC")
  end
end

Now, This is much better. The application now honors the MVC boundaries and delegates domain model responsibilities cleanly. But you can do more...

You can make use of scopes here to produce a variety of finders on Membership that you can then chain together to get the results you're looking for:

Optimize(4)

class User < ActiveRecord::Base
  has_many :members
  
  def find_recent_active_members
    members.only_active.order_by_activity.limit(5)
  end

end

class Member < ActiveRecord::Base
  belongs_to :user
  
  scope :only_active, where(:active => true)
  scope :order_by_activity, order('last_active_on DESC')

end

By making the re-factoring in this last step, you've generalized a lot of the code. Instead of only having a Member#find_recently_active method, you now have three class methods that you can mix and match to your heart's desire.


Push All find() Calls into Finders on the Model

Push All find() Calls into Finders on the Model

Programmers who are not familiar with the MVC design pattern to which Rails adheres, as well as those who are just unfamiliar with the general structures provided by Ruby on Rails may find themselves with code living where it simply doesn't belong.

The code problem discussed in this section can present itself in all three layers of the MVC design pattern, but it is most prevalent in its most blatant form in the view or the controller.

For example, if you wanted to create a web page that displays all the users in your web application, ordered by last name, you might be tempted to put this call to find directly in the view code as follows:

<html>
  <body>
    <% User.find(:order => "last_name").each do |user| %>
       <li><%= user.last_name %><%= user.first_name %></li>
    <% end %>
  </body>
</html>

At the very least, including the actual logic for what users will be displayed on this page is a violation of MVC. At worst, this logic can be duplicated many times throughout the application, causing very real maintainability issues.

In order to get rid of the MVC violation, you need to move the logic for which users are displayed on the page into the Users Controller. When you do this, you end up with something like the following:

class UsersController < ApplicationController
  def index
    @users = User.order("last_name")
  end
end

The following is the corresponding index view:

<html>
   <body>
      <ul> 
         <% @users.each do |user| -%>
            <li><%= user.last_name %><%= user.first_name %></li>
         <% end %>
      </ul>
   </body>
</html>

Now you don't have any logic in the presentation layer about the collection of users you're displaying; now it's just sitting in the controller.

We can also moving the direct find call down into the model itself. with this change, the view doesn't change at all. However, you end up with a controller that calls a new ordered method on the User model:

class UsersController < ApplicationController
  def index
    @users = User.ordered
  end
end

And the User model contains the call to find:

class User < ActiveRecord::Base
  def self.ordered
    order("last_name")
  end
end

The Ruby on Rails community has embraced this concept so strongly that is has been baked into the framework itself, with scope. We'll go into the use of scopes later, but for now suffice to say that they are shortcuts for defining methods on a model.

For example, the named scope for the ordered method would be written as follows:

class User < ActiveRecord::Base
  scope :ordered, order("last_name")
end



Follow the Law of Demeter

Solution : Follow the Law of Demeter

You have some models, and you have view code that looks like the following:

class Address < ActiveRecord::Base
  belongs_to :customer
end

class Customer < ActiveRecord::Base
  has_one :address
  has_many :invoices
end

class Invoice < ActiveRecord::Base
  belongs_to :customer
end

This code shows a simple invoice structure, with a customer who has a single address. The view code to display the address lines for the invoice would be as follows:

<%= @invoice.customer.name %>
<%= @invoice.customer.address.street %>
<%= @invoice.customer.address.city %>
<%= @invoice.customer.address.state %>
<%= @invoice.customer.address.zip_code %>

Ruby on Rails allows you to easily navigate between the relationships of objects and therefore makes it easy to dive deep within and across related objects. While this is really powerful, there are a few reasons it's not ideal. For proper encapsulation, the invoice should not reach across the customer object to the street attribute of the address object. Because if, for example, in the future your application were to change so that a customer has both a billing address and a shipping address, every place in your code that reached across these objects to retrieve the street would break and would need to change.

To avoid the problem just described, it's important to follow the Law of Demeter, also known as the Principle of Least Knowledge. 

In Rails, this could be summed up as "use only one dot." for example, @invoice.customer.name breaks  the Law of Demeter, but @invoice.customer_name does not. Of course, this is an over simplification of the principle, but it can be used as a guideline.

To follow the Law of Demeter, you could rewrite the code above as follows:

class Address < ActiveRecord::Base
  belongs_to :customer
end

class Customer < ActiveRecord::Base
  has_one :address
  has_many :invoices

  def street
    address.street
  end

  def city
    address.city
  end

  def state
    address.state
  end

  def zip_code
    address.zip_code
  end

end

class Invoice < ActiveRecord::Base
  belongs_to :customer

  def customer_name
    customer.name
  end
  
  def customer_street
    customer.street
  end

  def customer_city
    customer.city
  end

  def customer_state
    customer.state
  end

  def customer_zip_code
    customer.zip_code
  end 

end

And you could change the view code to the following:

<%= @invoice.customer_name %>
<%= @invoice.customer_street %>
<%= @invoice.customer_city %>
<%= @invoice.customer_state %>
<%= @invoice.customer_zip_code %>

In this new code, you have abstracted out the individual methods that were originally being reached by crossing two objects into individual wrapper methods on each of the models.

The downside to this approach is that the classes have been littered with many small wrapper methods. If things were to change, now all of these wrapper methods would need to be maintained. And while this will likely be considerably less work than changing hundreds of references to invoice.customer.address.street  throughout your code, it's still an annoyance that would be nice to avoid.

Fortunately, Ruby on Rails includes a function that addresses the first concern. this method is the class-level delegate method. This method provides a shortcut for indicating that one or more methods that will be created on your object are actually provided by the related object.

Using this delegate method, you can rewrite your example like this:

class Address < ActiveRecord::Base
  belongs_to :customer
end

class Customer < ActiveRecord::Base
  has_one :address
  has_many :invoices

  delegate :street, :city, :state, :zip_code, :to => :address
end

class Invoice < ActiveRecord::Base
  belongs_to :customer

  delegate :name, :street, :city, :state, :zip_code, :to => :customer, :prefix => true

end

In this situation, you don't have to change your view code; the methods are exposed just as they were before:

<%= @invoice.customer_name %>
<%= @invoice.customer_street %>
<%= @invoice.customer_city %>
<%= @invoice.customer_state %>
<%= @invoice.customer_zip_code %>



Monday, 17 September 2012

Facebook Share Button


Facebook Share Button

<script>
 function fbs_click() {
 u="<%= DOMAIN_CONFIG %>";
 t=document.title;
 window.open('http://www.facebook.com/sharer.php?  
 u='+encodeURIComponent(u)+'&t='+encodeURIComponent(t),'sharer','toolbar=0,status=0,width=626,height=436');
 return false;
 }
 </script>

<style>
    html .fb_share_button {
        display: -moz-inline-block;
        display:inline-block;
        padding:1px 20px 0 5px;
        height:15px; border:1px solid #d8dfea;
        background:url(http://static.ak.facebook.com/images/share/facebook_share_icon.gif) no-repeat top
        right;
   }
    html .fb_share_button:hover {
        color:#fff; border-color:#295582;
        background:#3b5998 url(http://static.ak.facebook.com/images/share/facebook_share_icon.gif) no-
        repeat top right; text-decoration:none;
   }
  </style>
  <a rel="nofollow" href="http://www.facebook.com/share.php?u=<;url>" class="fb_share_button" onclick="return fbs_click()" target="_blank" style="text-decoration:none;background-color: #ECEEF5;">Share</a>