Есть ли способ переопределить оператор << в Ruby? - PullRequest
10 голосов
/ 02 марта 2012

Я пытаюсь сделать что-то вроде:

account.users << User.new

Но мне нужно, чтобы пользователи были методом для учетной записи. Итак, я пробовал такие вещи, как:

def users<<(obj)

Но мне не повезло с этим. Это вообще возможно сделать в Ruby? Я бы предположил, потому что отношения ActiveRecord, кажется, работают так в Rails.

Ответы [ 6 ]

9 голосов
/ 02 марта 2012

Проверьте этот ответ: Rails: переопределение метода ассоциации ActiveRecord

[этот код полностью из другого ответа, здесь для будущих искателей]

has_many :tags, :through => :taggings, :order => :name do
    def << (value)
      "overriden" #your code here
    end     
  end
5 голосов
/ 02 марта 2012

Возможно, вы описываете не вашу настоящую проблему, а ответ на свой вопрос - да, вы можете переопределить оператор <<:

class Foo
  def <<(x)
    puts "hi! #{x}"
  end
end

f = Foo.new
=> #<Foo:0x00000009b389f0>
> f << "there"
hi! there
2 голосов
/ 19 декабря 2012

Полагаю, у вас есть такая модель:

class Account < ActiveRecord::Base
  has_and_belongs_to_many :users
end

Чтобы переопределить Account#users<<, вам нужно определить его в блоке, который вы передаете has_and_belongs_to_many:

class Account < ActiveRecord::Base
  has_and_belongs_to_many :users do
    def <<(user)
      # ...
    end
  end
end

Вы можете получить доступ к соответствующему Account объекту, обратившись к proxy_association.owner:

def <<(user)
  account = proxy_association.owner
end

Чтобы позвонить оригиналу Account#users<<, позвоните Account#users.concat:

def <<(user)
  account = proxy_association.owner
  # user = do_something(user)
  account.users.concat(user)
end

Подробнее см. На этой странице: Расширения ассоциации - ActiveRecord

1 голос
/ 02 марта 2012

В данном случае это класс << вашего пользователя. Так может быть Array или AssociationProxy.

Самое простое - создать новый метод, чтобы делать то, что вы хотите.

Вместо этого вы можете переопределить метод экземпляром.

account.users.instance_eval do
  def <<(x)
    put 'add'
  end
end

account.users << User.new
# add

Но вам нужно делать это все время, прежде чем добавить к << </p>

0 голосов
/ 03 марта 2012

Если вы пытаетесь выполнить действие после добавления User в коллекцию users, вы можете использовать обратные вызовы ассоциации вместо переопределения << (поскольку существует много добавить объект в ассоциацию).

class Account
  has_many :users, :after_add => :on_user_add

  def on_user_add(user)
    p "Added user : #{user.name} to the account: #{name}"
  end
end
0 голосов
/ 02 марта 2012

users вернет объект, у которого есть переопределенный оператор <<, такой как Array, IO, String, или любой другой тип, который вы создадите.Вы переопределяете это так:

class SomeType
  def <<(obj)
    puts "Appending #{obj}"
  end
end
...