Ruby Symbols and Strings


I had good timing with one of rubyist yesterday. He asked me, what is major difference between Ruby string and symbols. Honestly speaking i had no words expect symbols definition(Symbols are immutable. Mutable objects can be changed after assignment while immutable objects can only be overwritten). Finally he explained me with a nice example, Again i googled and come up with few new addition. That what i want to explain here, May it will help some one.

All are self explanatory, put a comment if need more details.

1. Single word String and Symbol

1.9.2p320 :226 > “test”
=> “test”
1.9.2p320 :227 > :test
=> :test

2. Multiple words String and Symbol

1.9.2p320 :230 > “test string”
=> “test string”
1.9.2p320 :231 > :”test string”
=> :”test string”

3. Symbol may also contain special characters like string

1.9.2p320 :234 > :”test string #”
=> :”test string #”
1.9.2p320 :235 > :”test string $”
=> :”test string $”

4. Convert string to Symbol:

1.9.2p320 :239 > “I am Ruby developer”
=> “I am Ruby developer”
1.9.2p320 :240 > “I am Ruby developer”.to_sym
=> :”I am Ruby developer”
1.9.2p320 :241 > “I am Ruby developer”.intern
=> :”I am Ruby developer”

5. Convert symbol to String:

1.9.2p320 :244 > :”I am Rails developer”
=> :”I am Rails developer”
1.9.2p320 :245 > :”I am Rails developer”.to_s
=> “I am Rails developer”

6. Strings are mutable(Mutable objects can be changed after assignment):

1.9.2p320 :250 > text = “I belongs to the”
=> “I belongs to the”
1.9.2p320 :251 > puts text << ” India”
I belongs to the India

7. Symbols are immutable(immutable objects can only be overwritten):

1.9.2p320 :252 > text = :”I belongs to the”
=> :”I belongs to the”
1.9.2p320 :253 > puts text << :” India”
NoMethodError: undefined method `<<‘ for :”I belongs to the”:Symbol
from (irb#1):253

8.Frozen Strings

We can freeze the String and thus making it immutable. Once a String is frozen it cannot be changed.

1.9.2p320 :277 > test = “This is ruby string”
=> “This is ruby string”
1.9.2p320 :278 > test.upcase!
=> “THIS IS RUBY STRING”
1.9.2p320 :280 > test.freeze
=> “THIS IS RUBY STRING”
1.9.2p320 :281 > test.downcase!
RuntimeError: can’t modify frozen string
from (irb#1):281:in `downcase!’
from (irb#1):281

9. String Performance:

Because Strings are mutable, the Ruby interpreter never knows what that String may hold in terms of data. As such, every String needs to have its own place in memory. We can see this by creating some Strings and printing their object id.

1.9.2p320 :295 > puts “This is string performance test”.object_id
76899900
=> nil
1.9.2p320 :296 > puts “This is string performance test”.object_id
76884690
=> nil
1.9.2p320 :297 > puts “This is string performance test”.object_id
76870210
=> nil
1.9.2p320 :298 > puts “This is string performance test”.object_id
76855080
=> nil
1.9.2p320 :299 > puts “This is string performance test”.object_id
76842070
=> nil

NOTE: Our object id’s will be different then the ones above.

What we see above might not seem like a big issue, but behind the scenes is some heavy waste. To understand why, we first have to understand what is going on under the hood. An abridged explanation is as follows:

  1. First, a new String object is instantiated with the value of "This is string performance test".
  2. The Ruby interpreter needs to look at the heap (your computers memory), find a place to put the new string and keep track of it via its object id.
  3. The String is passed to the puts method, and output to the screen.
  4. The Ruby interpreter sees that the String will not be used again as it is not assigned to a variable, and marks it for destruction.
  5. Back to step one four more times.

Conclusion: In above example, we are creating a new object, storing and ultimately destroying.

10. Symbol Performance:

1.9.2p320 :301 > puts :”This is string performance test”.object_id
233758
=> nil
1.9.2p320 :302 > puts :”This is string performance test”.object_id
233758
=> nil
1.9.2p320 :303 >
1.9.2p320 :304 > puts :”This is string performance test”.object_id
233758
=> nil
1.9.2p320 :305 > puts :”This is string performance test”.object_id
233758
=> nil
1.9.2p320 :306 > puts :”This is string performance test”.object_id
233758

In above, every Symbol shares the same object id, and as such the same space on the heap. To further increase performance, Ruby will not mark Symbols for destruction, allowing you to reuse them again and again. As Symbols stay in memory throughout the programs operation, we can quickly snag them from memory instead of instantiating a new copy every time. In fact, Symbols are not only stored in memory, they are also keep track of via an optimized Symbols dictionary.

10. We can see all Symbol by running the below command.

1.9.2p320 :340 > puts Symbol.all_symbols.inspect

[:example, :”test string”, :”test string #”, :”test string $”, :”I am Ruby developer”, :”I am Rails developer”, :”I belongs to the”, :” India”, :text=, :”This is string performance test”]

Conclusion:

In ruby programming language, We should to use Symbol as much as we can instead of String, To optimize performance and save memory.

example:

hash = {“a” => “something”, “b” => “else”}
hash1 = {:a => “something”, :b => “else”}

I hope it will help to understand String and Symbol, shot a comment if i missed any things 🙂

Advertisements

Passing Blocks in Ruby methods


Today moving around Proc class in Ruby. I come across details about Ruby Blocks and How ruby methods receive block.

There are two way to receive blocks in Ruby methods.

1. Yield

Ruby’s yield statement gives control to a user specified block from the method’s body.

def test
   yield 5,10
   puts "You are in the method test"
   yield 100,200
end

test {|i,j| puts "You are in the block"}

OutPut:

You are in the block
You are in the method test
You are in the block

Even we  can pass parameters with the yield statement.

def test
   yield 5,10
   puts "You are in the method test"
   yield 100,200
end
test {|i,j| puts "You are in the block #{i} and #{j}"}

OutPut:

You are in the block 5 and 10
You are in the method test
You are in the block 100 and 200

2. Proc

If the last argument of a method is preceded by &(Object=Proc.new), then you can pass a block to this method and this block will be assigned to the last parameter. In case both * and & are present in the argument list, & should come later.

The & calls ‘to_proc’ on the object, and passes it as a block to the method.
In Rails, to_proc is implemented on Symbol, so that these two calls are equivalent:
something {|i| i.foo } and  something(&:foo)

def test(b=Proc.new)   
   b.call(10,20)
   puts "You are in the method test"
   yield 100,200
end
OR
def test(&b)
   p b    
   b.call(10,20)
   puts "You are in the method test"
   yield 100,200
end

test {|i,j| puts "You are in the block #{i} and #{j}"}

Output:

You are in the block 10 and 20
You are in the method test
You are in the block 100 and 200

I hope, it will give sense of how ruby methods call blocks and yield. You can get code from my github Passing-Blocks-in-Ruby-methods.

Multiple Inheritance, Ruby



Multiple inheritance is a feature of object-oriented computer programing
languages in which a class can inherit(Inheritance is a relation between two classes)
characteristics and features from more than one superclass.  It is distinct
to single inheritance, where a class may only inherit from one particular superclass.

Ruby doesn't support Multiple inheritance . Ruby has single inheritance(each class has one and only one parent class). Example: All cats are mammals, and all mammals are animals.The benefit of inheritance is that classes lower down the hierarchy get the features of those higher up, but can also add specific features of their own. If all mammals breathe, then all cats breathe. class ClassA puts :A end class ClassB puts :B end # will not work class Inheritor < ClassA, ClassB puts :A puts :B end # To make things work: module ModuleA puts :A end module ModuleB puts :B end # class Inheritor mixin ModuleA,ModuleB modules class Inheritor include ModuleA include ModuleB puts :I end I hope it give small clarification on ruby inheritance features.

Rails Counter Cache


Counter Cache is a mechanism to cache the counts of associated model.Enabling counter cache will simply make Rails to increment and decrement the counter of associated objects. Whenever you need to execute size on ActiveRecord, Rails will use the cached counter.

Necessary steps.

  1. Add the counter_cache column as an integer.
  2. Make sure that the column is set to disallow null values and defaults to 0.
  3. Reset the counters for existing records. The reset_counters method is not smart enough to take an array of ids, so you have to call it for each record you want updated.

Example:

class Organization < ActiveRecord::Base
    has_many :seasons
  end

  class Season < ActiveRecord::Base
    belongs_to :organization, :counter_cache => true
  end

That's it.

Cheers!!!