codedecoder

breaking into the unknown…


Leave a comment

mixin in ruby : include prepend extend

Ruby do not support multiple inheritance directly, but implement it through Mixin . Mixin in ruby is achieved with include, prepend and extend. prepend is introduced with Ruby 2.0. Lets see, how they work and differ from each other.

Lets define few module and classes. We will experiment with them on irb or Rails console and try to understand their behaviour

module Introduction
  def introduce
    puts "Iam Arun"
  end
end

module Welcome
  def greet
    puts "Hi..How are you"
  end
end

module Host
  def serve_food
    puts "chiken biryani"
  end
end

module SeeOff
  def bye
    puts "Byee..."
  end
end

class Person
  prepend Introduction
  include Welcome
  include Host
  extend  SeeOff
end

class Celebrity
  
end

Copy paste above code in irb and keep experimenting as you proceed below :

1 => include and prepend add the module method as instance method, while extend add it as class method.

Calling as class method :

2.2.1 :058 > Person.introduce
NoMethodError: undefined method `introduce’ for Person:Class

2.2.1 :059 > Person.greet
NoMethodError: undefined method `greet’ for Person:Class

2.2.1 :060 > Person.bye
Byee…

You can see that, only bye method of module SeeOff worked as it is extended , so added as class method

Calling as instance method

2.2.1 :061 > Person.new.introduce
Iam Arun

2.2.1 :062 > Person.new.greet
Hi..How are you

2.2.1 :063 > Person.new.bye
NoMethodError: undefined method `bye’ for #<Person:0x8edec04>

Here include and prepend added the module method as instance method to the class, so it worked, but bye method of SeeOff module failed as it is added as a class method so can’t be call on the instance of Person.

Now considering the above behaviour, you may think when to use mixin as class method(using extend) and when to use as instance method(using include or prepened). It depended on the feature a module is providing and how you want to reuse it in your class. Infact in a ordinary class also, you may use the below thumb rule to define a method as a instance method or a class method.

Define a method as class method if you say want to use it within different methods of a class. say prity_print can be a class method
as it can be used in any method to well format the content before retuning it.

Second scenario is that the method behaviour not depend on the instance variable, for example it is not good idea to make full_name as class method as it depend on user’s first_name and last_name which differ from user to user, But say active_users can be a class method as it do not depend on any individual user

2. Adding module method at runtime : use extend to add method only to a specific instantiated object and use include or prepend to add instance methods to all the instance .

Above, the Celebrity class do not have any method, nor it has included or extended any of the module. Now say we want to add bye method at run time to Celebrity.

2.2.1 :065 > Celebrity.bye
NoMethodError: undefined method `bye’ for Celebrity:Class

> Celebrity.extend SeeOff
=> Celebrity
2.2.1 :067 > Celebrity.bye
Byee…

Now say. we have Katrina and Deepika as two celebrity.

2.2.1 :074 > katrina = Celebrity.new
=> #<Celebrity:0xe317eb0>
2.2.1 :075 > deepika = Celebrity.new
=> #<Celebrity:0xe3161f0>

But we want to greet katrina only

2.2.1 :076 > katrina.extend Welcome
=> #<Celebrity:0xe317eb0>

2.2.1 :077 > katrina.greet
Hi..How are you

2.2.1 :078 > deepika.greet
NoMethodError: undefined method `greet’ for #<Celebrity:0xe3161f0>

So you can see that, when extend act on katrina i,e an object already instantiated it add greet method of Welcome as instance method to it(remember it add module method as class method to person). Basically, extend can add a module method as class Method or instance method depending on who called it at the runtime. You can check that , we have extended SeeOff as the class method above, so it will not available to katrina or deepika who are basically a instance of Celebrity class.

katrina.bye
NoMethodError: undefined method `bye’ for #<Celebrity:0xe29b964>

Now say, you want to introduce yourself to any celebrity, thus the introduce method must be available to all its instance. In this case we have to use include.

2.2.1 :116 >Celebrity.include Introduction

2.2.1 :116 > salman = Celebrity.new
=> #<Celebrity:0xe26d848>
2.2.1 :117 > salman.introduce
Iam Arun

2.2.1 :118 >katrina.introduce
Iam Arun

Notice that, Introduction module is mixed to Celebrity class after creation of katrina object, but its introduce method also get available to it, this is because in ruby methods are accessed by reference, any object just contain its own variable and refer for any method in its class, so if some method is added later on then also it will be accessible to a object.

3 => Just like all classes are instances of Ruby’s Class, all modules in Ruby are instances of Module.Module is the superclass of Class, so this means that all classes are also modules, and can be used as such.

You can easily check it by calling ancestors method on Person class

2.2.1 :068 > Person.ancestors
=> [Introduction, Person, Host, Welcome, Object, PP::ObjectMixin, Delayed::MessageSending, ActiveSupport::Dependencies::Loadable, V8::Conversion::Object, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject]
2.2.1 :069 >

You can note down below from the above result

  1. extend do not add the module to the ancestors chain
  2. prepend add the module as child of the class in which it is called , see that Person become ancestor of Introduction
  3. include add the ancestors in the reverse order of their call. Host include in last, so it become first ancestor of Person

As you know we can override any method in ancestors class in its child class, and also use super to keep behaviour of ancestor intact and at the same time adding our own behaviour. Let rewrite our initial code to explain this.

module Introduction
  def introduce
    puts "Iam Arun"
    super
  end
end

module Welcome
  def greet
    puts "Hi..How are you"
  end
end

module Host
  def serve_food
    puts "chiken biryani"
  end
end

module SeeOff
  def bye
    puts "Byee..."
  end
end

class Person
  prepend Introduction
  include Welcome
  include Host
  extend  SeeOff
  
  def serve_food
    super
    puts "try lassi"
  end
  
  def introduce
    puts "Happy to meet you"
  end
end

 

Now you can get below result when call different methods of the Person class.

2.2.1 :110 > person = Person.new
=> #<Person:0xb4cd9d58>

2.2.1 :111 > person.serve_food
chiken biryani
try lassi

2.2.1 :112 > person.introduce
Iam Arun
Happy to meet you

And finally, let’s see an alternative way of extending a class. I do not use it myself as I believe in keeping the things simpler. But if you go through, gems and different library, you can see the use of self.included(base) .

Basically included is a callback , which get triggered whenever a module is included into another module or class. The argument base passed to it is basically the target module or class i,e that in which the module is included. Don’t get confused as initially I was. See the example below:

module Welcome
  def self.included(base)
    base.extend SeeOff
  end
  
  def greet
    puts "Hi..How are you"
  end
end

module SeeOff
  def bye
    puts "Byee..."
  end
end

class Person
  include Welcome
end

Note that, In Person class, we have only included the Welcome module, but in the Welcome module we have defined included method within which we have extended the SeeOff class with the line base.extend SeeOff , since Welcome module is included in Person class, when included callback get fired, Person will be become base class for it.So base.extend SeeOff will evaluated as Person.extend SeeOff .

You can check the result in console now:

2.2.1 :037 > Person.bye
Byee…

So you can see that bye method of SeeOff class get added as class method to Person class.

That’s all about mixin in ruby.. ūüôā


Leave a comment

image cropping with paperclip

We are using paperclip for managing files and images in our project . I assume you all know how to use paperclip with its default behaviour .

Our user model managing user profile picture with paperclip look as below :

class User < ActiveRecord::Base
	has_attached_file :picture, 
                    styles: { medium: "300x300#", thumb: "80x80#" }, 
                    content_type: ['image/jpeg','image/jpg', 'image/png'],
                    default_url: "/images/:style/missing.png", 
                    whiny: false, 
                    use_timestamp: false
end

I have used few of the option available with has_attached_file method of paperclip . The complete list is available here .

So what it do, when ever user select his picture from UI, paperclip creates different size of it, here medium and thumb size. you can add more style as per your need.

Now we need to enhance user experience and let him to crop the picture also, which is common now a days. So know user have to go through two steps :

STEP 1 : Crop the picture

This step just allow user to select part of the picture he want to upload rather then the whole pic. You can let the user do that by providing 4 input fields crop_x, crop_y, crop_w, crop_h which is basically x cordinate, y cordinate setting the origin from where image is to cut , with the specified width and height.

But this is not user friendly. A lot of libraries are available which can serve the above purpose in better way.

I used croppic which worked well for me . I will write on its usage on some other day. Meanwhile you can try it yourself.

Our end goal in this step is to get user selected portion of image i,e crop_x, crop_y, crop_w, crop_h

STEP 3 : Make Paperclip to work on cropped part.

So, now paperclip should create different size of cropped part rather then the whole image. To make it work we first need to understand its default behaviour of paper clip and its is in this file . Below are the important lines of this file(I have taken only the line need to understood from each method)

module Paperclip
  # Handles thumbnailing images that are uploaded.
  class Thumbnail < Processor
    
    attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options,
      :source_file_options, :animated, :auto_orient
    
    def initialize(file, options = {}, attachment = nil)
      super
      geometry             = options[:geometry].to_s
      @crop                = geometry[-1,1] == '#'
      @target_geometry     = options.fetch(:string_geometry_parser, Geometry).parse(geometry)
      @current_geometry    = options.fetch(:file_geometry_parser, Geometry).from_file(@file)
    end
    
    def crop?
      @crop
    end
    
    def transformation_command
      scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
      trans = []
      trans << "-coalesce" if animated?
      trans << "-auto-orient" if auto_orient
      trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
      trans << "-crop" << %["#{crop}"] << "+repage" if crop
      trans << '-layers "optimize"' if animated?
      trans
    end
  end
end

So you can see that thumbnail class is wrapped up in paperclip module and inherit from processor class . In the initialize method it set @target_geometry and @current_geometry . The main work is handle by transformation_command method . The first line  basically give back scale of the uploaded image and its cropped part . transformation_to method is defined here .

Now we will override these methods of Thumbnail class to suit our need . Read about method overriding in this post .

We are going to create our own custom processor. Lets create a paperclip_processors folder within lib folder and add custom_processor.rb file to it. It will look as below :

module Paperclip
  class CustomCropper < Thumbnail
    def initialize(file, options = {}, attachment = nil)
      super
      if target.crop_w && target.crop_x
        @current_geometry.width  = target.crop_w
        @current_geometry.height = target.crop_h
      end
    end
    
    def target
      @attachment.instance
    end
    
    def transformation_command
      # call crop processing only if user inputs are there
      if target.crop_w && target.crop_x
        crop_command = [
          "-crop",
          "#{target.crop_w}x" \
            "#{target.crop_h}+" \
            "#{target.crop_x}+" \
            "#{target.crop_y}",
          "+repage"
        ]
        crop_command + super
      else
        super
      end
    end
    
  end
end

Our custom_cropper inherit from thumbnail class and override its initialize and transform method. In these method if user inputs for crop is not given, super is called which exhibit the behaviour of Thumbnail without any modification . This condition is put in place as sometime user sync his data from linkedin and at that time crop inputs is not available or say we have created some user in from seed.rb file which face the same issue.

Now our custom processor is defined, we just need to modify the user model to call our custom processor explicitly and so the default thumbnail processor will be not called . The user model will now look as below :

class User < ActiveRecord::Base
	has_attached_file :picture, 
                    styles: { medium: "300x300#", thumb: "80x80#" }, 
                    content_type: ['image/jpeg','image/jpg', 'image/png'],
                    default_url: "/images/:style/missing.png", 
                    whiny: false, 
                    use_timestamp: false,
                    processors: [:custom_cropper]

        attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
end

We have defined attr_accessor for the cordinates and width height.

The controller code will look something like as below

  def upload_profile_pic
    @user.crop_x = params[:imgX1].to_i
    @user.crop_y = params[:imgY1].to_i
    @user.crop_w = params[:imgW].to_i
    @user.crop_h = params[:imgH].to_i
    @user.picture = params[:user][:picture]
    @user.save
  end

That’ s all you need to make your Paperclip custom processor .

 

Resources :

https://github.com/thoughtbot/paperclip

http://www.rubydoc.info/gems/paperclip/Paperclip/ClassMethods

https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/thumbnail.rb

http://www.rubydoc.info/gems/paperclip/Paperclip/Processor


2 Comments

method overriding in ruby

method overriding refers to replacing a method of parent class in its subclass. The method definition in the subclass should have same signature as the method in the parent class. So, when a method is called on the subclass object, the overridden method in the subclass will be called.

lets create overriding_demo.rb file and add below line to it

class Person

  def welcome(name,msg,food)
	puts "Hi #{name}"
	puts "Hi #{msg}"
	puts "I will cook #{food} for you"
  end

end

class Indian < Person

  def welcome(name,msg,food)
	puts "sorry..I do not know you"
  end

end

puts "************welcome in parent class*************"
Person.new.welcome("arun", "how are you", "pizaa")

puts "\n\n************welcome in subclass*************"
Indian.new.welcome("arun", "namaste..kaise hain app", "rice")

Now when you run the above file you will get the below output:

$ ruby overriding_demo.rb
************welcome in parent class*************
Hi arun
how are you
I will cook pizaaa for you

************welcome in subclass*************
sorry..I do not know you

 

So you can see that, welcome method is overrided in the subclass .Here an important aspect is use of super keyword , which allow the overriding method in subclass to execute the parent method and modify or add on its output.

So basically, super call the parent method implicitly. Obviously , you need to pass the arguments to the parent method. but super is not invoked as a normal method. super itself decide what argument to passed to the parent method when it is invoked in the subclass method, depending on the way , it is called.

Below are the convention used by super to pass argument to the parent method :

-> super called without any argument i,e simply as super then the argument passed to subclass method will be passed as argument to parent class .

-> super called with empty argument i,e as super() then no argument is passed to the parent method. It is useful if the parent method set some defaults and you want to stick to that . But, it will throw error, if the parent method expecting some arguments.

-> super called with arguments i,e as super(a,b,c) then only the argument a,b,c will be passed to the parent method.

To demo it, replace overriding_demo.rb file with below line of code:

class Person

  def welcome(name,msg,food)
	puts "Hi #{name}"
	puts "#{msg}"
	puts "I will cook #{food} for you"
  end

end

class Indian < Person

  def welcome(name,msg,food)
    super
    puts "I will show you bollywood movie"
  end

end


puts "************welcome in subclass*************"
Indian.new.welcome("arun", "namaste..kaise hain app", "rice")

 

run it, you will see below output

$ ruby overriding_demo.rb
************welcome in subclass*************
Hi arun
namaste..kaise hain app
I will cook rice for you
I will show you bollywood movie

So in the above code, the subclass call super to maintain the behavior of parent class and at the same time add some feature itself. Also note that the argument passed to the welcome method in the subclass get passed to the parent method implicitly.

now try to call the code again after replacing super with super() i,e calling with empty argument

$ ruby overriding_demo.rb
************welcome in subclass*************
welcome.rb:3:in `welcome’: wrong number of arguments (0 for 3) (ArgumentError)

So you get error which is expected as the welcome method need 3 arguments but you are not passing any

Again, modify the super in above code with super(“ajay”, “how are you”, “chinese”) and see the ouput again

$ ruby overriding_demo.rb
************welcome in subclass*************
Hi ajay
how are you
I will cook chinese for you
I will show you bollywood movie

So you can see that, this time welcome method of parent is invoked with argument passed to super.

That’s all about method overriding. just want to add that, you can override any thing in ruby, but avoid overriding inbuilt library methods as it may break other things in your class if that depend on the original method.


Leave a comment

method overloading in ruby

method overloading in programing refers to invoking different behavior of a method of class depending on its arguments. Making it simpler, you can say that a class can have more then one method with the same name, but with different argument i,e different signature of the method.

You can implement different signature of method in any of the below way:

1 : Arguments with different data types, eg: method(int a, int b) vs method(String a, String b)
2:  Variable number of arguments, eg: method(a) vs method(a, b)

Let’s try to do method overloading in ruby.

create a overloading_demo.rb file and add below lines to it

class Person

  def print_details(name)
    "Hey My Name is #{name}"
  end

  def print_details(name,age)
    "Hey My Name is #{name} and #{age}"
  end
end

person1 = Person.new
puts person1.print_details("arun")
puts person1.print_details("arun",25)

So, with overloading, you expect to get different message detail when you pass only name, and when pass both name and age.

Let see what we get by running the above code.

$ ruby overloading_demo.rb
overloading_demo.rb:7:in `print_details’: wrong number of arguments (1 for 2) (ArgumentError)

So, you can see that, overloading not happening here. ruby expecting print_details to have two argument, but since in the first call, you passed only one argument, it throws error. So we can say that:

Ruby do not support method overloading

In ruby there can be only one method with a given name. If there is multiple methods with the same name,the last one prevail i,e the last method will be invoked when called.

In above case, the last print_details method have two argument, so this will prevail and any call to print_details will expect two arguments. Since the first call to print_details passing only one argument, you are getting the above error.

But why ruby not support method overloading, when it is known feature in other language like C.

This is because¬† “Overloading” is a term that simply doesn’t even make sense in Ruby. It is basically a synonym for “static argument-based dispatch”, but Ruby doesn’t have static dispatch at all. So, the reason why Ruby doesn’t support static dispatch based on the arguments, is because it doesn’t support static dispatch, period. It doesn’t support static dispatch of any kind, whether argument-based or otherwise.

At the beginning, I have mentioned two way in which method overloading takes place : one when argument type differ and other when number of argument differ.

But ruby is dynamic typed language i,e type of the method argument is evaluated at the run time. You can see that, you have not specified the type of argument while defining print_details method, it is decided at run time so… print_details(int name,int age) and print_details(string¬† name, string age) is same in ruby. for variable no of argument implementation print_details(name, age=25) and print_details(name) definition is same, as they can be invoked with single argument.

Due to these issues ruby get rid of method overloading. Personally, I never felt its harming me in any way. In any case if you want to execute different behavior  for a method based on argument, you can write your own customize code. Lets modify our overloading_demo.rb to get what we want, without method overloading.

class Person

  def print_details(*args)
    case args.size
    when 1
      "Hey My Name is #{args[0]}"
    when 2
      "Hey My Name is #{args[0]} and #{args[1]}"
    end
  end

end

person1 = Person.new
puts person1.print_details("arun")
puts person1.print_details("arun",25)

No when you run the above code you can get the result you expect from overloading

$ ruby overloading_demo.rb
Hey My Name is arun
Hey My Name is arun and 25

Hope, you now have clear idea of method overloading in ruby


Leave a comment

polymorphism in ruby: duck typing with example

If you interested in technical jargon about polymorphism read here . Keeping it simple, polymorphism is object oriented programing approach where a interface behave differently depending on nature of the object.

what ? .. you still feel it is technical jargon.

O.K…lets make it more simple. being human we tend to meet people, greet them, treat them. Have you observed that people from different country, state or city do it in different way. A Englishman greet you with “Hi..How are you?” , a Indian from north say “namaste..kaise hain aap” …and so on.

So if you, program a welcome interface, its behavior should change depending on the person. This is known as Polymorphism.If you still didn’t get it, continue with the example, by end your concept will be clear.

class Welcome

  def meets
    puts "meets a person"
  end

  def greet(person)
    person.greet
  end

  def treat(person)
    person.treat
  end

end

class Englishman

  def greet
    puts "Hi..how are you?"
  end

  def treat
    puts "Iam serving you English food"
  end

end


class Indian

  def greet
    puts "Namste...kaise hain app"
  end

  def treat
    puts "Iam serving you Indian food"
  end

end

welcome = Welcome.new
puts "********Englishman***********"
person = Englishman.new
welcome.greet(person)
welcome.treat(person)


puts "********Indian***********"
person = Indian.new
welcome.greet(person)
welcome.treat(person)

If you run the above file on console, you will again get the same output as in template implementation of inheritance.

$ ruby welcome.rb
********Englishman***********
Hi..how are you?
Iam serving you English food
********Indian***********
Namste…kaise hain app
Iam serving you Indian food

 

You can see that the welcome interface’s greet and treat method behaving differently for different person. This is known as polymorphism in Object oriented programing. The implementation is known as Duck Typing . The name come from initial proposed theory that a bird can speak and fly, but can do it in any ways, but still be treated as bird. They can be a duck or penguin or crow and so on

You can demo it on same line as welcome interface above. create a bird.rb file and add below code to it.

class Duck
  def speak
    puts "Quack I am #{@name}"
  end
 
  def fly
    puts 'Up up and away...'
  end
end
 
class Penguin
  def speak
    puts "Squak I am #{@name}"
  end
 
  def fly
    puts 'Nope. I swim...'
  end
end

class Bird
  def speak(bird)
    bird.speak
  end
 
  def fly(bird)
    bird.fly
  end
end

bird = Bird.new

puts "***behave as duck****"
duck = Duck.new
bird.speak(duck)
bird.fly(duck)

puts "***behave as penguin****"
penguin = Penguin.new
bird.speak(penguin)
bird.fly(penguin)

If you run the above file you will get below output:

$ ruby bird.rb
***behave as duck****
Quack I am
Up up and away…
***behave as penguine****
Squak I am
Nope. I swim…

Hope now you know what is Duck Typing and what is Polymorphism.

 

Reference:

https://practicingruby.com/articles/duck-typing-in-practice-2


Leave a comment

copy object in ruby

When ever, you pass any object to any other method for manipulation, you should pass its copy rather then the original object to prevent any risk on the original object. See the below example.

we have below classes in bank_account.rb

class BankAccount
  attr_accessor :name, :balance
  def initialize(name,balance)
    @name = name
    @balance = balance
  end
end

class Invoice
  def print_account_holder_name(account_holder)
    puts account_holder.name.upcase
    account_holder.balance = 1000000
  end
end

BankAccount is the class which hold detail of accounts. Invoice class, generate the account report. Let us demonstrate the involved risk on console

1.9.3-p194 :014 > load “/home/arun/Documents/bank_account.rb” # give path of your bank_account.rb
1.9.3-p194 :016 > a = BankAccount.new(“arun”, 10000)
=> #<BankAccount:0xc9553d8 @name=”arun”, @balance=10000>
1.9.3-p194 :017 > Invoice.new.print_account_holder_name(a)
ARUN
1.9.3-p194 :019 > a.balance
=> 1000000

So you can see that, when print_account_holder_name method of invoice class is passed object of BankAccount class, it accidently or intentionally(in our case), increased the balance from 10000  to 10000000 . This can be avoided by passing the copy of object rather then the original object.

With the above background, we now understand the need of creating copy of object before passing to any other method or doing any manipulation over it. Let us see how we can do that i,e copy a object.

In ruby, everything is a object, even the data types. consciously or unconsciously, you have many a time created copy of these objects with assignment operator while programming.

try this in console

1.9.3-p194 :020 > a = 1
=> 1
1.9.3-p194 :023 > b = a
=> 1
1.9.3-p194 :024 > b += 1
=> 2
1.9.3-p194 :025 > a
=> 1
1.9.3-p194 :026 > b
=> 2

You can see that, you created b as a copy of a, when you add 1 to b, a do not changed i,e the manipulation occurred only on the copy b . But this way of creating copy work only for plain data type integer, string , text etc.

See again the above with a array value.

1.9.3-p194 :027 > a = [1,2]
=> [1, 2]
1.9.3-p194 :028 > b = a
=> [1, 2]
1.9.3-p194 :029 > b << 3
=> [1, 2, 3]
1.9.3-p194 :030 > a
=> [1, 2, 3]

So you can see that, creating copy with assignment operator = not worked and array assigned to a also get changed when the copy b is modified.¬†This is because the Array object is not a primary data type. The assignment operator doesn’t make a copy of the value, it simply copies the reference to the Array object. The a and b variables are now references to the same Array object, any changes in either variable will be seen in the other.

Here dup and clone come to our rescue

1.9.3-p194 :031 > a = [1,2]
=> [1, 2]
1.9.3-p194 :032 > b = a.dup # a.clone also work
=> [1, 2]
1.9.3-p194 :033 > b << 3
=> [1, 2, 3]
1.9.3-p194 :034 > a
=> [1, 2]

So now you can see that with dup or clone, the changes on the copy not alter the original object a . Good… let us check the real scenario we have created in our¬† bank_account.rb.

1.9.3-p194 :039 > load “/home/arun/Documents/bank_account.rb”
=> true
1.9.3-p194 :040 > a = BankAccount.new(“arun”, 10000)
=> #<BankAccount:0xc94549c @name=”arun”, @balance=10000>
1.9.3-p194 :041 > b = a.clone
=> #<BankAccount:0xc936ce4 @name=”arun”, @balance=10000>
1.9.3-p194 :042 > c = a.dup
=> #<BankAccount:0xc929fa8 @name=”arun”, @balance=10000>
1.9.3-p194 :043 > Invoice.new.print_account_holder_name(b)
ARUN
1.9.3-p194 :044 > Invoice.new.print_account_holder_name(c)
ARUN
1.9.3-p194 :046 > a.balance
=> 10000

O.K, so this time we pass the copy b(created with dup) and copy c (created with clone) to the print_account_holder_name method of invoice class, and you can see that the balance of the original object a is secure .

Great…we will now onward create a copy of sensitive object before handing over it to any other interface for manipulation. But what is this … both dup and clone seems to doing the same thing : – copying the object . Yaa… superficially they are same, but do exhibit different behaviour. the difference can be stated in a single line as below.

clone maintain internal characteristic of copied object but dup do not .

Let us see the difference in the console.

=> dup do not maintain the frozen state of the object

1.9.3-p194 :011 > a = BankAccount.new(“arun”, 10000)
=> #<BankAccount:0x9997470 @name=”arun”, @balance=10000>
1.9.3-p194 :012 > a.freeze
=> #<BankAccount:0x9997470 @name=”arun”, @balance=10000>
1.9.3-p194 :013 > a.frozen?
=> true
1.9.3-p194 :014 > b = a.dup
=> #<BankAccount:0x99a1254 @name=”arun”, @balance=10000>
1.9.3-p194 :015 > b.frozen?
=> false
1.9.3-p194 :016 > c = a.clone
=> #<BankAccount:0x99a5cf0 @name=”arun”, @balance=10000>
1.9.3-p194 :017 > c.frozen?
=> true

So, you can see that, object a is frozen, but when it id copied with dup it become unfrozen, but remain same when copied with clone.

 

=> dup do not copy the singleton method of the object .

1.9.3-p194 :018 > a = BankAccount.new(“arun”, 10000)
=> #<BankAccount:0x99b1e38 @name=”arun”, @balance=10000>
1.9.3-p194 :019 > def a.iam_singleton
1.9.3-p194 :020?>   end

1.9.3-p194 :021 > a.methods
=> [:iam_singleton, :name, :name=, :balance, :balance=,:clone, :dup, :initialize_dup, :initialize_clone…]

1.9.3-p194 :023 > b = a.dup
=> #<BankAccount:0x99c3c3c @name=”arun”, @balance=10000>
1.9.3-p194 :024 > b.methods
=> [:name, :name=, :balance, :balance=,:clone, :dup, :initialize_dup, :initialize_clone…]

1.9.3-p194 :025 > c = a.clone
=> #<BankAccount:0x99d2110 @name=”arun”, @balance=10000>
1.9.3-p194 :026 > c.methods
=> [:iam_singleton, :name, :name=, :balance, :balance=,:clone, :dup, :initialize_dup, :initialize_clone…]

so we have added iam_singleton method to the object a . It is available to the copy c created with clone but not available to copy b created with dup.

NOTE : You can’t make copy of all the object. for example fixnum can’t be copied

 1.9.3-p194 :033 > 1.dup
TypeError: can’t dup Fixnum
1.9.3-p194 :033 > 1.clone
TypeError: can’t clone Fixnum

 

NOTE : you can customize the dup and clone method by redefining initialize_dup and initialize_clone method in your class, so overriding the original behaviour. Both initialize_dup and initialize_clone call initialize_copy method internally

O.K..so we now know the difference between dup and clone. But which one we should use. Well it is upto you. Personally, I prefer dup, as I know that Iam having only the copy of the object, so I can mess with it. I do not want any limitation on the copy I’ am having . Limitation is always a pain..isn’t it…go with dup. ūüôā

 

Reference:

http://ruby-doc.org/core-2.1.2/Object.html#method-i-dup

http://ruby-doc.org/core-2.1.2/Object.html#method-i-clone

http://m.onkey.org/ruby-i-don-t-like-3-object-freeze

 


2 Comments

difference between private protected public in ruby

private, protected and public control the visibility of methods in ruby class .By default methods in ruby are public except global and initialize method which are private by default. As far as variable are concerned they are private by default as variable can’t be seen by them self but through getter and setter method defined for a variable. you can define the getter and setter method yourself, which is not actually needed as it can be achieved by using :attr_accessor. the variables for which you have defined getter and setter methods behave as public. constants are effectively public , there is no way to define a constant that is inaccessible to outside use. we can say that public, private and protected apply only to methods

private, protected and public are not any keyword but actual method of object class that operate on any other class, dynamically altering the visibility of its methods . you can get the list of private, protected or public method of a class by using private_methods , protected_methods and public_methods on it.

private, protected and public take methods name as argument. If you do not pass argument all the method following them will have the same visibility until it is changed by applying the other. Let us illustrate it with examples in visibility_demo.rb files

# this global method defined outside class so private
def iam_global
  puts "Iam global"
end

class VisibilityDemo

  def initialize
    @message = "Iam the class demonstrating visibility in ruby"
  end
  # No visibility specifier given so public by default

  def pub_method
    puts "Iam public"
  end

  private
  # This method appears after the private' visibility specifier so private
  def pri_method
    puts "Iam private"
  end

  # This method is also private because the previous visibility not overridden
  # specifier has not been overridden
  def pri_method2
    puts "Iam private"
  end

  protected
  # This method appears after the protected visibility specifier so protected
  def pro_method
    puts "Iam protected"
  end

  public
  #this method overridden above protected specifier and become public
  def pub_method2
    puts "Iam public"
  end
end

The risk in above way of defining the visibility (visibility specifier without arguments) is that all following method will have same behaviour(try by changing the position of say private, keep it at top), which we not always want, so it is better to use them in argument form if the list of particular visibility is not very long. Let us redefine it in argument form and also add some other piece of code, needed to demo visibility behaviour.

def iam_global
  puts "Iam global"
end

class VisibilityDemo

  def initialize
    @message = "Iam the class demonstrating visibility in ruby"
  end

  def pub_method
    puts "#{self}"
    puts "Iam public"
  end

  def pri_method
    puts "Iam private"
  end

  def pri_method2
    puts "Iam private"
  end

  def pro_method
    puts "Iam protected"
  end

  def demo_explicit_object_calling_pro(obj)
    #call the protected method on explcit object
    obj.pro_method
  end

  def pub_method2
    puts "Iam public"
  end

  #specifying visibility specifier with argument
  private :pri_method, :pri_method2
  protected :pro_method
end

#class inheriting from VisibilityDemo class
class InheritVisibility < VisibilityDemo
  # the will call methods of parent class with self as explicit receiver
  def call_methods_with_self
    self.pub_method
    self.pro_method
    self.pri_method
  end

  # the will call methods of parent class without any receiver
  def call_methods_without_receiver
    pub_method
    pro_method
    pri_method
  end

  #overriding private method of parent class
  def pri_method2
   puts "I have overrided parent and become public"
  end

end

#class not inheriting from VisibilityDemo
class AnyClass
  def call_methods
    pub_method
    pro_method
    pri_method
  end  
end

Now let us list all the types of method on irb console
> load “/home/arun/Desktop/visibility_demo.rb” #load the visibility_demo.rb file
=> true
> @visbiility_demo = VisibilityDemo.new # create instance of VisibilityDemo class
=> #
> @visbiility_demo.public_methods # list the public methods
=> [:pub_method, :pub_method2,…]
> @visbiility_demo.protected_methods # list the protected methods
=> [:pro_method]
> @visbiility_demo.private_methods  # list the private methods
=> [:initialize, :pri_method, :pri_method2, :iam_global, ..] # see that initialize and iam_global listed under private

O.K, so we now know how to set the visibility of a method. Let us now see how the visibility specifier change the behaviour of methods in its own class and its inherited classes.

NOTE : before you proceed you must be clear on self and implicit and explicit receiver of a method . You should also know that, there is three way of calling any method : method_name , self.method_name, @object.method_name

1 => irrespective of its visibility any method can be called only in its class hierarchy

See the below output on irb :

> @any_class = AnyClass.new # create instance of any class
 => #<AnyClass:0x942b25c>
> @any_class.pub_method # call the pub method of VisibilityDemo class
NoMethodError: undefined method `pub_method’ for #<AnyClass:0x942b25c> #give error , can’t be called
> @any_class.pro_method # call the protected method of VisibilityDemo class
NoMethodError: undefined method `pro_method’ for #<AnyClass:0x942b25c> #give error , can’t be called
> @any_class.pri_method # call the private method of VisibilityDemo class
NoMethodError: undefined method `pri_method’ for #<AnyClass:0x942b25c> #give error , can’t be called
> @any_class.call_methods # call method of AnyClass calling VisibilityDemo class method implicitly
NoMethodError: undefined method `pub_method’ for #<AnyClass:0x942b25c>

2 => Public method can be called on any object in the class hierarchy as the explicit receiver, but protected and private can’t

See the below output on the irb console :

> self
=> main
> @visbility_demo = VisibilityDemo.new # creating object of  VisibilityDemo class
¬†=> #<VisibilityDemo:0x970c214 @message=”Iam the class demonstrating visibility in ruby”>
> @visbility_demo.pub_method #call the public method
Iam public
> @visbility_demo.pro_method #call the protected method
NoMethodError: protected method `pro_method’ called for #<VisibilityDemo:0x970c214> # give error
> @visbility_demo.pri_method #call the private method
NoMethodError: private method `pri_method’ called for #<VisibilityDemo:0x970c214>¬†# give error

NOTE : Here there is one exception for protected method, protected method can also be called on a object if its belongs to the same class as self.

In the above output , you are running the code from irb and so at this point of program self is main, but the object @visbility_demo belongs to VisibilityDemo class, since the class of self and the class of object is different, the protected method throw error. See the below output where protected method called on explicit object and worked fine.

> @visbiility_demo = VisibilityDemo.new # creating object of VisibilityDemo
¬†=> #<VisibilityDemo:0x955e034 @message=”Iam the class demonstrating visibility in ruby”>
> obj = VisibilityDemo.new # creating another object of VisibilityDemo
¬†=> #<VisibilityDemo:0x9531408 @message=”Iam the class demonstrating visibility in ruby”>
> @visbiility_demo.demo_explicit_object_calling_proc(obj) #for demo_explicit_object_calling_proc method self is VisibilityDemo and since object passed to it is also of same class, the protected method worked this time
Iam protected

3 => Public and Protected both can be called with self as explicit receiver but Private can’t

See the below output on the irb console

> @inherting_visibility = InheritVisibility.new # create instance of the inheriting class
¬†=> #<InheritVisibility:0x96e068c @message=”Iam the class demonstrating visibility in ruby”>
> @inherting_visibility.call_methods_with_self # call the method calling parent class method with self
Iam public # public method called successfully with self
Iam protected # protected method called successfully with self
NoMethodError: private method `pri_method’ called for #<InheritVisibility:0x96e068c> # private method give error

4 => public protected and private all can be called implicitly i,e without any receiver

See the below output on irb console:

> @inherting_visibility = InheritVisibility.new
¬†=> #<InheritVisibility:0x96e068c @message=”Iam the class demonstrating visibility in ruby”>
> @inherting_visibility.call_methods_without_receiver
Iam public
Iam protected
Iam private

5 => If a private method overridden in its subclass, the method exhibit visibility as defined in subclass

see the below output in irb console

> @visibility_demo = VisibilityDemo.new # create object of VisibilityDemo class
¬†=> #<VisibilityDemo:0x9e49734 @message=”Iam the class demonstrating visibility in ruby”>
> @visibility_demo.pri_method2 # call the private method
NoMethodError: private method `pri_method2′ called for #<VisibilityDemo:0x9e49734> # error as expected
> @inherit_visibility = InheritVisibility.new # create object of subclass of VisibilityDemo class which override the method
¬†=> #<InheritVisibility:0x9f01e4c @message=”Iam the class demonstrating visibility in ruby”>
> @inherit_visibility.pri_method2 # call the private method of parent again
I have overrided parent and become public # it worked this time as it is overridden in the subclass 

So, from the above points we can summarized the behaviour as below :

Private method can be called only implicitly (i,e without any receiver) . Protected method can be called with a explicit receiver but that should be self or if a object, the object must belong to same class as self . Public method can be called in any way in its class hierarchy .

So through above point ruby ensure that private method should never we called on a object and let ruby invoke it by its own. Remember that you can create instance of any class anywhere and if a highly secure method say which manipulate user balance, call it current_account_balance is not private, then any person can misuse it by creating the object of class and calling the method.

Here, ruby differ in private implementation in C and c++ . In C ++¬† ‚Äúprivate‚ÄĚ means ‚Äúprivate to this class‚ÄĚ, while in Ruby it means ‚Äúprivate to this instance‚ÄĚ. What this means, in C++ from code in class A, you can access any private method for any other object of type A. In Ruby, you can not: you can only access private methods for your instance of object, and not for any other object instance (of class A).

It should be also noted that, ruby prevent accidental misuse of private method, but not prevent it strictly. So if you want, you can invoke a private method on an object also with send, see the below output on console

> @visibility_demo = VisibilityDemo.new
¬†=> #<VisibilityDemo:0x9e8c804 @message=”Iam the class demonstrating visibility in ruby”>
> @visibility_demo.pri_method # trying to call the private method on object
NoMethodError: private method `pri_method’ called for #<VisibilityDemo:0x9e8c804> #throw no method error
> @visibility_demo.send(:pri_method) # # trying to call the private method on object with send
Iam private #it worked

Since, private method can’t be called on its own object also, but there are some cases where we me need it, so there we can make the method protected. Let us take a simple example below in file say my_bank.rb

class BankRate

  def initialize(bank_name, rate)  
    @bank_name = bank_name
    @rate      = rate  
  end 

  def bank_name
     @bank_name
  end 

  def current_rate  
    @rate  
  end 

  def comparative_rate(bank)  
    if bank.current_rate > current_rate  
      "#{bank.bank_name} have higher rate then #{@bank_name}"  
    else  
      "#{bank.bank_name} have higher rate then #{@bank_name}"  
    end  
  end 

  private :current_rate  
end  

# call the comprative_rate method
@sbi = BankRate.new("sbi", 12)  # first object of BankRate class
@icici = BankRate.new("icici", 14)  # secone object of same BankRate class
puts  @sbi.comparative_rate(@icici) # calling comprative_rate method on first object and passing second as argument

So, we have a BankRate class dealing with bank rate. We want that, the current_rate should not be misused so we have made it private. This class also have a method which compare the rate of the bank with another bank . Try to load the my_bank.rb file on console

> load “/home/arun/Desktop/my_bank.rb” #load my_bank.rb file
NoMethodError: private method `current_rate’ called for #<BankRate:0x9f90d90 @bank_name=”icici”, @rate=14>

So you can see that, although the @sbi¬† and @icici bot are object of the same class, still they can’t invoke the private method. Now change the visibility of current_method to protected in above file i,e protected :current_rate and run it again.

> load “/home/arun/Desktop/visibility_demo.rb” #load my_bank.rb file again
icici have higher rate then sbi # it worked this time

So, this worked this time. This demonstrate when to use private and when to use protected.

Reference :

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes

http://lylejohnson.name/blog/2003/12/09/private-methods-in-c-and-ruby/ # comparison with c, c++