2014-03-28 65 views
3

http://api.rubyonrails.org/classes/String.html#method-i-acts_like_string-3F如何使用acts_like_string?在红宝石

我正在通过红宝石acts_like_string?,但找不到任何示例如何使用。我试过但没有运气。

puts str.acts_like_string? 
+1

我相信它检查s的对象,看它是否像一个字符串行为,所以你可以做一些像'str +'这样的字符串“if str.acts_like_string?' 或者,如果你知道你的对象的行为,你可以调用任何其他字符串方法像一个字符串!看看这个 - http://rubylearning.com/satishtalim/duck_typing.html – Huy

回答

2

这些是在寻找我的宝石夹acts_like_stringgrep --recursive --context 2 acts_like_string $(gem environment gemdir)结果:

activesupport-4.1.0.rc1/lib/active_support/core_ext/string/behavior.rb-class String 
activesupport-4.1.0.rc1/lib/active_support/core_ext/string/behavior.rb- # Enable more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>. 
activesupport-4.1.0.rc1/lib/active_support/core_ext/string/behavior.rb: def acts_like_string? 
activesupport-4.1.0.rc1/lib/active_support/core_ext/string/behavior.rb- true 
activesupport-4.1.0.rc1/lib/active_support/core_ext/string/behavior.rb- end 
-- 
activesupport-4.1.0.rc1/lib/active_support/multibyte/chars.rb-  alias to_str wrapped_string 
activesupport-4.1.0.rc1/lib/active_support/multibyte/chars.rb- 
activesupport-4.1.0.rc1/lib/active_support/multibyte/chars.rb:  delegate :<=>, :=~, :acts_like_string?, :to => :wrapped_string 
activesupport-4.1.0.rc1/lib/active_support/multibyte/chars.rb- 
activesupport-4.1.0.rc1/lib/active_support/multibyte/chars.rb-  # Creates a new Chars instance by wrapping _string_. 
-- 
mail-2.5.4/lib/mail/multibyte/chars.rb- 
mail-2.5.4/lib/mail/multibyte/chars.rb-  # Enable more predictable duck-typing on String-like classes. See Object#acts_like?. 
mail-2.5.4/lib/mail/multibyte/chars.rb:  def acts_like_string? 
mail-2.5.4/lib/mail/multibyte/chars.rb-  true 
mail-2.5.4/lib/mail/multibyte/chars.rb-  end 

正如你所看到的,acts_like_string?回报trueActiveSupport::Multibyte::Chars。它解决了哪个问题?

假设您必须检查某个对象是否为String:您可以编写类似object.is_a? String;但是通过这种方式,您可以排除那些不由String继承的类,但可以将其视为字符串,如f.e. ActiveSupport::Multibyte::Chars,它增强了一些字符串方法并将每个缺少的方法委托给它的实例变量。

相反的object.is_a? String您可以使用object.acts_like?(:string):这将正常工作,因为的ActiveSupport定义(我的意见):

# Provides acts_like? for every Ruby object, so you can call it 
# on everything without worrying about its presence 
class Object 
    def acts_like?(duck) 
    respond_to? :"acts_like_#{duck}?" 
    end 
end 

# Provides acts_like_string? for String and every class which inherits by String 
class String 
    def acts_like_string? 
    # this actually could be false or nil or whatever, 
    # since acts_like? checks only the method presence 
    true 
    end 
end 

# Provides acts_like_string? ActiveSupport::Multibyte::Chars, delegating it 
# to @wrapped_string instance variable (which in turn defines it if it is 
# a String) 
class ActiveSupport::Multibyte::Chars 
    delegate :<=>, :=~, :acts_like_string?, :to => :wrapped_string 
end 

这允许你写例如:

gem 'activesupport' 
require 'active_support/all' 

def method_which_works_only_with_a_string_argument(argument) 
    unless argument.acts_like? :string 
    raise ArgumentError, 'argument must act like a string' 
    end 
    argument.capitalize 
end 

argument = ActiveSupport::Multibyte::Chars.new 'über' 
method_which_works_only_with_a_string_argument argument 
# => "Über" 
method_which_works_only_with_a_string_argument 123 
# => ArgumentError: argument must act like a string 

铁,ActiveRecord的内部使用它values sanitization

[...] 
def quote_bound_value(value, c = connection, column = nil) #:nodoc: 
    if column 
    c.quote(value, column) 
    elsif value.respond_to?(:map) && !value.acts_like?(:string) 
    if value.respond_to?(:empty?) && value.empty? 
     c.quote(nil) 
    else 
     value.map { |v| c.quote(v) }.join(',') 
    end 
    else 
    c.quote(value) 
    end 
end 
[...]