Example parsing for Hook methods in Ruby and ruby hook instance Parsing

Source: Internet
Author: User

Example parsing for Hook methods in Ruby and ruby hook instance Parsing

By using the Hook method, we can intervene in the life cycle of Ruby classes or modules, greatly improving programming flexibility.
The following hook methods related to lifecycle are available:

Classes and modules

  • Class # inherited
  • Module # include
  • Module # prepended
  • Module # extend_object
  • Module # method_added
  • Module # method_removed
  • Module # method_undefined

Single-piece class-related

  • BasicObject # singleton_method_added
  • BasicObject # singleton_method_removed
  • BasicObject # singleton_method_undefined

Sample Code

Module M1 def self. included (othermod) puts "M1 was included into # {othermod}" endendmodule M2 def self. prepended (othermod) puts "M2 was prepended to # {othermod}" endendendclass C include M1 include M2end # output M1 was encoded into CM2 was prepended to Cmodule M def self. method_added (method) puts "New method: M ##{ method}" end def my_method; endend # output New method: M # my_method

In addition to the methods listed above, you can also rewrite a method of the parent class, perform some filtering operations, and then call the super method to complete the functions of the original function, in this way, the functions similar to the hook method are achieved. In the same way, the surround alias can also be used as an alternative to the hook method.

Use instances
Task Description:

Write a class macro similar to attr_accessor's attr_checked. This class macro is used to test the attribute value. The usage is as follows:

Class Person include CheckedAttributes attr_checked: age do | v> = 18 endendme = Person. newme. age = 39 # okme. age = 12 # throw an exception

Implementation plan:

Use the eval method to compile a kernel method named add_checked_attribute, and add simple verified attributes to the specified class.
Refactor the add_checked_attribute method, remove the eval method, and use other methods to implement it.
Add code block Verification
Modify add_checked_attribute to the required attr_checked and make it available to all classes.
By introducing modules, you can only add the attr_checked method to classes that introduce this function module.
Step 1

def add_checked_attribute(klass, attribute) eval "  class #{klass}   def #{attribute}=(value)    raise 'Invalid attribute' unless value    @#{attribute} = value   end   def #{attribute}()    @#{attribute}   end  end "endadd_checked_attribute(String, :my_attr)t = "hello,kitty"t.my_attr = 100puts t.my_attrt.my_attr = falseputs t.my_attr

In this step, the eval method is used, the class is opened with the class and def keywords respectively, and the get and set methods of the specified attribute are defined, the set method can be used to determine whether the value is null (nil or false). If yes, an Invalid attribute exception is thrown.

Setp 2

def add_checked_attribute(klass, attribute) klass.class_eval do  define_method "#{attribute}=" do |value|   raise "Invaild attribute" unless value   instance_variable_set("@#{attribute}", value)  end  define_method attribute do   instance_variable_get "@#{attribute}"  end endend

In this step, the eval method is replaced, and the previous class and def keywords are replaced by the class_eval and define_method methods. The instance_variable_set and instance_variable_get methods are used for setting and obtaining instance variables respectively, there is no difference between usage and the first step, but there are some internal implementation differences.

Step 3

def add_checked_attribute(klass, attribute, &validation) klass.class_eval do  define_method "#{attribute}=" do |value|   raise "Invaild attribute" unless validation.call(value)   instance_variable_set("@#{attribute}", value)  end  define_method attribute do   instance_variable_get "@#{attribute}"  end endendadd_checked_attribute(String, :my_attr){|v| v >= 180 }t = "hello,kitty"t.my_attr = 100 #Invaild attribute (RuntimeError)puts t.my_attrt.my_attr = 200puts t.my_attr #200

There is nothing special about it. It only adds code block verification, which increases the flexibility of verification and is no longer limited to between nil and false.

Step 4

class Class def attr_checked(attribute, &validation)   define_method "#{attribute}=" do |value|    raise "Invaild attribute" unless validation.call(value)    instance_variable_set("@#{attribute}", value)   end   define_method attribute do    instance_variable_get "@#{attribute}"   end endendString.add_checked(:my_attr){|v| v >= 180 }t = "hello,kitty"t.my_attr = 100 #Invaild attribute (RuntimeError)puts t.my_attrt.my_attr = 200puts t.my_attr #200

Here we put the Chinese method name of the top-level scope in the Class. Because all objects are Class instances, the instance method defined here can also be accessed by all other classes in Ruby, at the same time, in the class definition, self is the current class, so it eliminates the need to call the class parameter and the class_eval method, and we changed the method name to attr_checked.

Step 5

module CheckedAttributes def self.included(base)  base.extend ClassMethods endendmodule ClassMethods def attr_checked(attribute, &validation)   define_method "#{attribute}=" do |value|    raise "Invaild attribute" unless validation.call(value)    instance_variable_set("@#{attribute}", value)   end   define_method attribute do    instance_variable_get "@#{attribute}"   end endendclass Person include CheckedAttributes attr_checked :age do |v|  v >= 18 endend

The last step is to use the Hook method to extend the current class through the introduced module after the CheckedAttributes module is introduced, so that the current class supports the introduced method call, that is, the get and set method groups here.

At this point, we have obtained a class macro named attr_checked, similar to attr_accessor, through which you can verify the attributes you want.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.