Understand Object-oriented program in Ruby

Reading time ~5 minutes

what is OOP?

class and object

blueprint/molds built from it. object can keep the sam behaviors and different states from the class. We can create an object from initialize method while we call class method new

  • encapsulation: hiding pieces of functionality and making it unavailable to the rest of code base.
  • polymorphism
  class Dog
    def initialize(name, age)
      @name = name
      @age = age
    end
  end

  shelly = Dog.new("shelly", 5)

getter/setter

we can create an object called shelly and it holds name “shelly” and age with fixnum 5. But what if we want to prints out shelly.name, it will show undefined method, then how do we do ? or if we want to change the shelly age to 6, how can we do shelly.age 6=. we can add method:

  class Dog < Animal
    def initialize(name, age)
      @name = name
      @age = age
    end
    def name
      @name
    end

    def age=(input)
      @age = input
    end
  end

with these method, now we can modify the age of shelly and call shelly.name the shelly.name is getter method, and shelly.age= is setter method, but if we have a lots of state we want to get and set, then we have to write lots of code. In Ruby, we don’t want to repeat ourself. So there is setter/getter method built in Ruby. We can use attr_*

  class Dog
    attr_reader :name
    attr_writer :age
    attr_accessor :weight

    def initialize(name, age, weight)
      @name = name
      @age = age
      @weight = weight
    end
  end

self

self in Ruby refer two things, one is class method; the other is the object itself. For example, if we want to set the name to “jonny” inside the method change_name, we can use self.name “jonny”=, we also can define a class method. We can call this method without initialize a new object. self in the class level refer to class itself. In method level, it refer the object who call the method.

class method/instance method

class method can use directly, and if we want to use instance method, we have to initialize an object first then we call the instance method on the object itself. instance method is like the behavior the object holds. the class method are directly caled from the class itself.

class variable/instance variable

class variable has @@ in front of a variable, and @ in front of a variable is instance variable. When an object is created, you can access instance variable all the time with this object. And all the object created from the same clas can access the class variable.

inheritance

unlike other languae, ruby is single inheritance, one class can inherit from superclass, the other is called subclass. But one class only inheritate from one class. we can use the inheritance to avoid duplicate code. The subclass can inherit behavior from superclass.

method lookup path

we can use method lookup path to see how a method are called. Is this method from the current class? if not, Ruby will trace back to superclass to see where is the method there. If we want to check a speak method is existed in Dog, we can use Dog.ancestors to find the method lookup chain. If there is no speak method in Dog class then it will look up in Animal, and then back to BasicObject class. If there are two class shared some code, we can use method look up chain to find there same ancestors and put this method at the superclass as their both ancestors.

super

super is when we inherit from superclass, and we want to modify some code, we can use super

  def speak(manner)
    super + manner
  end

module, mixin

namespace

we can use Module to put the similiar class into a class, if our code get larger and larger, we can avoid to pollute or get confuse with our code. For example, if we define a class called Array and put it into Rock module, if we want to use this class, we can called “Rock::Array” to avoid replace the origin built-in Array class. In this way, we can think modules as container

polymorphism

Because Ruby is single inheritance, how about we want to re use some code again and again? think if we have a Fish class, and and Dog class from Mammals class. But Fish is not a Mammal, if we have a method named swim and both Dog and Fish have the function to swim. How can we do? we can create a module can Swimmable the in Dog and Fish class we can use include Swimmable. Althogut Ruby had single inheritance, we can use this mixin way to let Ruby also have the polymorphism. But you can instantiate modules.

private/protected/public

you can not access method from outside the class in the program when the code belongs private defination. the private method only can be use by other method inside the class. How about self.something while something is private method? It doesn’t work. Because, self here is referred to the object itself, which are not allowed to use private. If we want to use self.something by other method inside class and not allowed by the rest of program. We can use protected reserve word to do that.

fake operators

In ruby, there are lots of operators not true operators. They are Ruby’s syntactical sugar. Actually, they are methods look like operators. Here are some are true operators:

operators description
&& logical “and”
.. , ... inclusive, exclusive
?: ternary if-then-else
= series assignment

so all the +, -, *, >>, <<, <=>, !, []= etc. are methods that look like operators.

  class Team
    # ... rest of code omitted for brevity

    def [](idx)
      members[idx]
    end

    def []=(idx, obj)
      members[idx] = obj
    end
  end

truthiness

block

closure

a closure is a chunk of code that let you save later to execute this code. closure in Ruby is implement in Proc object. It is called “closure” because it is said to bind its surrounding artifacts(variable, methods, obejcts etc.) and build an “enclosure”

how block works

  • do...end or {...}
  • block can passed into an existed method as parameter.
  • in Ruby, every method can take a blcok as implicit parameter
  • we can use yield keyword in the method to invoke passed-in block.
  • we can use Kernel#block_given? method to call yield it there is a block given.

when to use block in your own method?

  1. Defer some implementation code to method invocation decision

=method implementator= can defer decision to let method caller decide what kind of code(block), they want to use here.

  • example, the build-in each, select
  • more flexible
  • you want to execute your block to compare before, after action

explicit block

&block. we can pass it to another method to use this block as parameter

  def test(&block)
    puts "What's &block? #{block}"
  end

  test { sleep(1) }

  # What's &block? #<Proc:0x007f98e32b83c8@(irb):59>
  # => nil

we can use a variable to represent the block withoud yield it.

to_param in Ruby on Rails

If I want a custom slug=======================I walk through this cutstom slug.1. create migration `add_slug` to add a column inside the...… Continue reading

What is ORM in Rails mean?

Published on July 14, 2017