RoR - MetaProgramming

Posted vixennn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RoR - MetaProgramming相关的知识,希望对你有一定的参考价值。

ruby是动态语言,它有动态语言的优势与劣势

动态语言,像python与ruby 你不用提前去定义method - they need to only be "found" when invoked

calling method dynamically: 

class Dog
    def bark
         puts "Woof, woof!‘
    end
    def greet(greeting)
        puts greeting
    end
end

dog = Dog.new
dog.bark # => Woof, woof!
dog.send("bark") # => Woof, woof!
dog.send(:bark) # => Woof, woof!
method_name = :bark
dog.send method_name # => Woof, woof!

dog.send(:greet, "hello") # => hello

  Dynamic Dispatch:

  不需要call method 用 xxx.xxx 

  能用string和symbol call methods dynamically

 

优点:*can decide at runtime which methods to call 

           *The code doesn‘t have to find out until runtime which method it needs to call 

 

Dynamic method: 

class Whatever 
    define_method :make_it_up do 
        puts "Whatever..."
    end
end

whatever = Whatever.new 
whatever.make_it_up # => Whatever...

写动态方法能有效降低code量

require_relative store
class ReportingSystem 

    def initialize 
        @store = Store.new 
        @store.methods.grep(/^get_(.*)_desc/) { ReportingSystem.define_report_method_for $1 )
    end

    def self.define_repot_methods_for (item)
        define_method ("get_#{item}_desc") {@store.send("get_#{item}_desc) }
        define_method ("get_#{item}_price") {@store.send("get_#{item}_desc) }
    end   
end

r3 = ReportingSystem.new 
puts "#{rs.get_piano_desc} costs #{rs.get_piano_price.to_s.ljust(6.‘0‘)}"

# => Excellent piano costs 120.00

 

Ghost method: 

如果我们使用了不存在的method,会自动跳转到method_missing  method,不过method_missing 可以被复写:

class Mystery 
    #no_methods defined 
    def method_missing (method, *args)
        puts "Looking for..."
        puts ""#{method}" with params {#{args.join(‘,‘)}} ?"
        puts "Sorry... He is on vacation... "
        yield "Ended up in method_missing" if block_given?
    end
end 

m = Mystery.new 
m.solve_mystery("abc", 123123) do |answer|
    puts "And the answer is: #{answer}" 
end

# =>  Looking for...
# =>  "solve_mystery" with params (abc,123123) ?
# =>  Sorry... He is on vacation...
# =>  And the answer is: Ended up in method_missing

* method_missing gives you the power to "fake" the methods

* 这被叫做ghost methods 是因为 它并不真正意义上的存在

*ruby built-in classes use method_missing and dynamic methods all over the place... 

 

Struct and OpenStruct:

Struct: 特定类的生成器,每个类都被定义为保存一组变量及其访问器(动态
方法)

OpenStruct: 对象(类似于Struct),其属性在第一次分配时动态创建(“Ghost方法”)。

Customer = Struct.new(:name, :address) do #block is optional 
    def to_s 
        "#{name} lives at #{address}"
    end
end 
jim = Customer.new("Jim", "-1000 wall Street")
puts jim # => Jim lives at -1000 wall Street


require ostruct # => need to require ostruct for OpenStruct 

some_obj = OpenStruct.new(name: "Joe", age: 15)
some_obj.sure = "three"
some_obj.really = "yes, it is true" 
some_obj.not_only_strings = 10
puts "#{some_obj.name} #{some_obj.age} #{some_obj.really}"
#=> Joe 15 yes,it is true

method_missing and Performance:

因为调用是直接的,所以可能会慢一些,但大多数情况下不影响。

如果考虑响应速度的话,可以考虑hybird approach 

*Define a real method from inside method missing after an attempted ‘call’

 

Ghost methods allow you to call methods as if they are there even though they are not
Method behavior can be defined at runtime , for example based on database columns existing or not .

 

以上是关于RoR - MetaProgramming的主要内容,如果未能解决你的问题,请参考以下文章

Metaprogramming

ruby Ruby:Metaprogramming

C++ template —— template metaprogram

Android在活动视图中附加片段获取片段已添加错误

ruby 来自https://www.jimmycuadra.com/posts/metaprogramming-ruby-class-eval-and-instance-eval/

我的RoR项目的远程协作