如何在RubyOnRails中实现魔术函数?

时间:2012-07-20 16:49:29

标签: ruby-on-rails ruby

如果访问属性且其属性没有数据,我有一个动态加载REST API数据的模型:

class Issue
  attr_accessor :ticket_title, :priority, :description
  @ticket_title
  @priority
  @description

  def priority
    if !@priority.empty?
      updateProperties()
    end
    @priority
  end
  def description
    if !@description.empty?
      updateProperties()
    end
    @description
  end
  def ticket_title
    if !@ticket_title.empty?
      updateProperties()
    end
    @ticket_title
  end

  def updateProperties
    # loads all data from REST API
  end

  def initialize (hsh = {})
      hsh.each { |key, value|
        self.instance_variable_set("@#{key}", value) 
      }
  end

end

有两个问题:

  1. 如果我使用RedmineIssue.new :ticket_title => 'test'初始化模型,我不希望模型调用updateProperties,但不管怎么说。
  2. 有没有办法神奇地宣布功能?即,如果没有真正的函数,请尝试运行元函数?

2 个答案:

答案 0 :(得分:3)

要动态添加方法,请阅读method_missing 好文章解释了它的一些方面。
http://www.trottercashion.com/2011/02/08/rubys-define_method-method_missing-and-instance_eval.html

答案 1 :(得分:1)

嗯,这里有“神奇”的东西。在您的课程中,如果您希望能够通过名为get_whateverthekeyis的方法获取哈希的任何部分(愚蠢的例子,我知道),您将使用method_missing

class Foo
  def initialize
    @h = {}
  end
  def method_missing(name, *args, &block)
    if(name =~ /\Aget_(.+)\Z/)
      #Name is valid
      sig_class.class_exec($1) do |n|
        define_method("get_"+n) {@h[n]}
      end

      @h[$1]
    elsif(name =~ /\Aset_(.+)\Z/)
      #Name is valid
      sig_class.class_exec($1) do |n|
        define_method("set_"+n) {|v| @h[n]=v}
      end

      @h[$1] = args[0]
    else
      super
    end
  end
  private
  def sig_class
    class << self
      self
    end
  end
end

未定义方法时,会转到method_missing。当发生这种情况时,method_missing对哈希执行请求的操作,然后动态定义方法,以便下次它是一个直接方法调用,这意味着它更有效,因为该方法已经存在。这有点类似于Ruby自己的OpenStruct使用的method_missing