send方法如何在没有任何符号的情况下工作?

时间:2014-10-14 08:56:28

标签: ruby ruby-on-rails-4

我不明白send在以下代码中是如何工作的,因为它没有使用符号。为什么它设法返回属性的值?

以下是代码:

module FormatAttributes
    def formats(*attributes)
        @format_attributes = attributes
    end

    def format_attributes
        @format_attributes
    end
end

module Formatter
    def display
        self.class.format_attributes.each do |attribute|
            puts "[#{attribute.to_s.upcase}] #{send(attribute)}"
        end
    end
end

class Resume
    extend FormatAttributes
    include Formatter
    attr_accessor :name, :phone_number, :email, :experience
    formats :name, :phone_number, :email, :experience
end

resume = Resume.new
resume.name = "Superman"
resume.email = "superman@gmail.com"
resume.phone_number = "12345"
resume.experience = "Ruby"

resume.display

结果是:

[NAME] Superman
[PHONE_NUMBER] 12345
[EMAIL] superman@gmail.com
[EXPERIENCE] Ruby

3 个答案:

答案 0 :(得分:0)

您将attribute变量作为参数传递,该变量可能包含SymbolString个对象。

答案 1 :(得分:0)

self.class.format_attributes访问者将在类对象上获取@format_attributes,该对象已由[:name, :phone_number, :email, :experience]行设置为formats

当您对attribute进行迭代时,它会获得值:name,然后是:phone_number等。 因此,在each循环内,您将执行send(:name)send(:phone_number)等。

attribute在第一次迭代中的值:name时,send(attribute)将与send(:name)执行相同的操作,与name的操作相同,"Superman"将返回{{1}}。

答案 2 :(得分:0)

请阅读send方法的文档。它说:

  

调用symbol标识的方法,并将指定的参数传递给它。如果名称发送与obj中的现有方法发生冲突,则可以使用发送。当方法由字符串标识时,字符串将转换为符号。

现在,您已在Formatter课程中添加extend模块并使用FormatAttributes Resume模块。毋庸置疑,它实际上使display方法来自Formatter实例方法。此外,来自formats的{​​{1}}和format_attributes将作为FormatAttributes类的类方法提供。现在,您的显示方法:

Resume

调用 def display self.class.format_attributes.each do |attribute| puts "[#{attribute.to_s.upcase}] #{send(attribute)}" end end ,这是format_attributes方法,因此你执行:class,因为这个方法假设返回一个属性数组,它们作为符号传递:

self.class.format_attributes

因此:

formats :name, :phone_number, :email, :experience

现在@format_attributes = [:name, :phone_number, :email, :experience] 阻止了each,你有:

attribute

对于一个实例,可以翻译为:

puts "[#{attribute.to_s.upcase}] #{send(attribute)}"

因此,puts "[#{:name.to_s.upcase}] #{send(:name)}" 将在name类的实例方法上调用,这就是你看到所有输出的原因。

编辑:为什么Resume:name:phone_number:email可用作方法?

这是因为这一行:

:experience

详细了解attr_accessor here