Ruby Metaprogramming Online Tutorial

Ruby metaprogramming online tutorial

The above article does refer to this but I'll post it for clarity:
http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html

Why is it important to learn about metaprogramming and eigenclasses in Ruby?

  • What benefits are gained when using metaprogramming?

    You can create more expressive APIs than without it (for example ActiveRecord uses metaprogramming to define accessor methods based on a table's column names, so you can write things like person.age instead of something like person.read_attribute("age"), where person is an active record object and the people table has a column called age) and you can accomplish some things with significantly less code than you otherwise would.

  • What is an eigenclass and how is it different from a singleton?

    The terms "eigenclass" and "singleton class" are used interchangeably in the context of ruby.

  • In what situations is using metaprogramming common?

    In situations where you'd otherwise have a lot of boiler plate code or when creating DSLs.

    Example of use case 1:

    Instead of writing something boiler-plate code like this:

    class Foo
    def bar
    @bar
    end

    def bar=(b)
    @bar = b
    end

    def baz
    @baz
    end

    def baz=(b)
    @baz = b
    end
    end

    You can write this much shorter code using the metaprogramming method attr_accessor, which automatically defines getter and setter methods with names based on the arguments you give it:

    class Foo
    attr_accessor :foo, :bar
    end

    If attr_accessor didn't already exist in the standard library, you could define it yourself like this (to give you an idea what metaprogramming in ruby looks like):

    class Module
    def attr_accessor(*variable_names)
    variable_names.each do |variable_name|
    define_method( variable_name ) do
    instance_variable_get( "@#{ variable_name }" )
    end

    define_method( "#{ variable_name }=" ) do |value|
    instance_variable_set( "@#{ variable_name }", value)
    end
    end
    end

    end

  • What ethical implications are there around using code to modify the behaviour of other code, especially code which is not your own?

    None.

Very simple DSL in Ruby

There're many different ways in which you can implement something like this. To keep it simple, you can just evaluate the block within a new Screen object and return the result.

class Screen
attr_reader :texts

def initialize
@texts = []
end

def label(hash)
# Validation + check for other keys
texts << hash[:text]
end

def to_s
texts.join
end

def self.write(&block)
raise "No block given" unless block_given?

Screen.new.tap do |s|
s.instance_eval(&block)
end
end
end

text = Screen.write do
label text: 'Something'
label text: 'stupid'
end

p "Rendered: #{text}"

How does RoR's magic namespace resolution work?

Rails' "Magic" makes extensive use of method_missing and const_missing.

When you try and call a method that is not defined, ruby fires a call to method_missing.
This is used by libraries like ActiveRecord to implement dynamic finders.

method_missing example:

SomeModel.find_by_some_field("some_value") is not defined.

This calls SomeModel.method_missing(:find_by_some_field, "some_value").

ActiveRecord then translates this call to `SomeModel.where(:some_field => "some_value")

(for performance purposes, ActiveRecord then dynamically defines this method, so next time find_by_some_field is defined)

const_missing example:

SomeModel has not yet been required.

The Ruby interpreter calls const_missing with the param "SomeModel"

Rails follows the convention "SomeModel" should be defined in a file called some_model.rb so const_missing just tries require "some_model".

Just started learning rails. What to do now?

Python and Ruby are pretty close.

You should simply have a look at http://railsforzombies.org to get some Rails knowledge.

class methods syntax in ruby

Look at this:

person.instance_of?(Person) #=> true
Person.instance_of?(Class) #=> true

You have defined an instance method add_accessor for all the instances of the class Class, so Person class can use that method because it is an instance of Class.

I recommend yout to take a look at metaprogramming and Ruby Object Model.

Hoep this helps



Related Topics



Leave a reply



Submit