Ruby,如何控制调用instanciated对象的返回值

时间:2015-10-21 20:33:15

标签: ruby

如果我这样做:

class PseudoRelationship
    def my_method(args)
         args
    end
end

a = PseudoRelationship.new

我得到了输出

x
#<PseudoRelationship:0x109c2ebb0>

我希望它的行为类似于枚举器或数组,所以我得到了这个输出

x = PseudoRelationship.new [1,2,3]
x
[1,2,3]

的Pd。这不适用于rails。

我想要做的就是表现得像阵列。

rails 2.3似乎使用的东西,例如,你可以做

my_model.relationship # returns an array
my_model.relationship.find #is a method

我正试图复制这种行为。

3 个答案:

答案 0 :(得分:1)

jholtrop很接近,你想要覆盖inspect方法

2.0.0p645> 
class PseudoRelationship
    def initialize(args)
        @args = args
    end

    def inspect
        @args.inspect
    end
end

2.0.0p645> PseudoRelationship.new [2, 3, 5]                                                                                                                                                                 
[2, 3, 5]

- 根据OP 想要此行为的原因进行修改 -

虽然上面的类在控制台中显示了我们想要查看的内容,但实际上并没有以一种将args视为Enumerable的方式假设任何args管理。 OP的灵感来自Rails构造,ActiveRecord::Relation *。要模仿这种行为方式,您必须包含Enumerable。

class PseudoRelationship
    include Enumerable

    def initialize(args)
        @args = args
    end

    def each(&block)
       @args.each(&block)
    end

    def inspect
        @args.inspect
    end

    # Add extra functions to operate on @args
    # This is obviously a silly example
    def foo?
      @args.include? :foo
    end

    def [](key)
      @args[key]
    end

    def last
      @args[-1]
    end
end


2.0.0p645> PseudoRelationship.new [2, 3, 5]                                                                                                                                                                 
[2, 3, 5]
2.0.0p645> x = PseudoRelationship.new [2, 3, 5]
[2, 3, 5]
2.0.0p645> x.each 
#<Enumerator: [2, 3, 5]:each>
2.0.0p645> x.each_with_index
#<Enumerator: [2, 3, 5]:each_with_index>
2.0.0p645> x.each_with_index { |e, i| puts "#{i} => #{e}" }
0 => 2
1 => 3
2 => 5
[2, 3, 5]
2.0.0p645> x.foo?
false
2.0.0p645> x.first
2
2.0.0p645> x.last
5
2.0.0p645> x[1]
3
2.0.0p645> x[5]
nil
2.0.0p645> x
[2, 3, 5]

*这个结构没有明确说明,但我根据具体情况假设

答案 1 :(得分:-1)

如果希望变量x与实例化对象时传递的参数相等,则需要在类中添加initialize方法。这样的事情应该有效:

class PseudoRelationship
  def initialize(args)
    args
  end

  def my_method(args)
    args
  end
end

x = PseudoRelationship.new [1, 2, 3]
x == [1, 2, 3] #=> true

编辑:

是的,上面的工作真的没有用。如果您希望它的行为类似于数组,则可以从Array继承,但这可能会导致奇怪的问题,通常不建议这样做。但是,以下内容可行:

class PseudoRelationship < Array
end

x = PseudoRelationship.new [1, 2, 3]
x.class #=> PseudoRelationship < Array
x == [1, 2, 3] #=> true

答案 2 :(得分:-1)

听起来你要求改变对象的“表示”,而不是“返回值”。要为对象提供新的String表示,可以在类上定义#to_s方法。例如:

class PseudoRelationship
  def initialize(v)
    @v = v
  end

  def to_s
    @v.to_s
  end
end

然后在irb中,例如:

1.9.3-p551 :021 > x = PseudoRelationship.new [:a, 42, false]
 => [:a, 42, false]