使用符号作为ruby方法的参数

时间:2011-11-05 16:44:05

标签: ruby-on-rails ruby symbols hash

我正在学习rails并回到ruby来理解rails中的方法(以及ruby真正起作用)。当我看到方法调用时:

validates validates :first_name, :presence => true

我感到困惑。你如何在ruby中编写接受符号或哈希的方法。验证方法的源代码也令人困惑。有人可以简化这个主题,在我的ruby类和实例方法中使用符号作为参数吗?

更新:

好的@Dave!但我尝试的是:

def full_name (:first_name, :last_name)
  @first_name = :first_name
  @last_name = :last_name
  p "#{@first_name} #{last_name}"
end

full_name("Breta", "Von Sustern")

这显然会引发错误。我试图理解:如果符号与任何其他值一样,为什么将这样的符号作为参数传递错误?

5 个答案:

答案 0 :(得分:22)

符号和散列是与其他值相同的值,可以像任何其他值类型一样传递。

回想一下,ActiveRecord模型接受哈希作为参数;它最终与此类似(它不是这么简单,但它最终是相同的想法):

class User
  attr_accessor :fname, :lname

  def initialize(args)
    @fname = args[:fname] if args[:fname]
    @lname = args[:lname] if args[:lname]
  end
end

u = User.new(:fname => 'Joe', :lname => 'Hacker')

除非你需要消除参数的歧义(并且当你跳过parens时还有一个块解析问题),这利用了不必将散列放在花括号{}中。

类似地:

class TestItOut
  attr_accessor :field_name, :validations

  def initialize(field_name, validations)
    @field_name = field_name
    @validations = validations
  end

  def show_validations
    puts "Validating field '#{field_name}' with:"
    validations.each do |type, args|
      puts "  validator '#{type}' with args '#{args}'"
    end
  end
end

t = TestItOut.new(:name, presence: true, length: { min: 2, max: 10 })
t.show_validations

输出:

Validating field 'name' with:
  validator 'presence' with args 'true'
  validator 'length' with args '{min: 2, max: 10}'

从那里你可以开始看到这样的事情是如何运作的。

答案 1 :(得分:9)

我以为我会为Ruby 2+添加更新,因为这是我找到的'符号作为参数'的第一个结果。

从Ruby 2.0.0开始,您还可以在定义方法时使用符号。调用方法时,这些符号的行为与其他语言中的命名可选参数几乎相同。见下面的例子:

def variable_symbol_method(arg, arg_two: "two", arg_three: "three")
  [arg, arg_two, arg_three]
end

result = variable_symbol_method :custom_symbol, arg_three: "Modified symbol arg"

# result is now equal to:
[:custom_symbol, "two", "Modified symbol arg"]

如示例所示,我们在调用方法时省略了arg_two:,在方法体中,我们仍然可以将其作为变量arg_two来访问。另请注意,函数调用确实改变了变量arg_three

答案 2 :(得分:5)

在Ruby中,如果在参数列表的末尾调用一堆name => value对的方法,它们会自动包装在Hash中并作为最后一个参数传递给您的方法:

def foo(kwargs)
  p kwargs
end

>> foo(:abc=>"def", 123=>456)
{:abc=>"def", 123=>456}

>> foo("cabbage")
"cabbage"

>> foo(:fluff)
:fluff

关于你如何编写方法没有什么“特别”,这就是你如何称呼它。将常规Hash对象作为kwargs参数传递是完全合法的。此语法快捷方式用于在API中实现命名参数

Ruby符号只是一个值,因此在您的示例中,:first_name只是一个常规的位置参数。 :presence是用作哈希键的符号 - 任何类型都可以用作哈希键,但符号是一种常见的选择,因为它们是不可变的值。

答案 3 :(得分:2)

符号不仅限于哈希。它们是标识符,没有字符串的额外存储空间。这只是说“这是......”的一种方式。

验证调用的一个可能的函数定义可能是(只是为了简化,我不知道它的真正含义):

def validates(column, options)
   puts column.to_s
   if options[:presence]
     puts "Found a presence option"
   end
 end

注意第一个符号是一个独立的参数,其余的是哈希值。

答案 4 :(得分:2)

我认为所有回复都没有提到问题;事实上,有人问我 - 我猜 - 不清楚符号是什么?

作为Ruby的新手,我有类似的困惑,对我来说,像下面这样的答案会更有意义

方法参数是由传入的值填充的局部变量。

您无法将符号用作自己的参数,因为您无法更改符号的值。