Ошибка: попытка вызвать приватный метод

Исходя из долгой истории синтаксиса в стиле C и теперь пытаясь изучить Ruby (на Rails), у меня была своя доля проблем с его идиомами и тому подобным, но сегодня я столкнулся с одной, я не ожидал, что возникнут проблемы с и я не могу видеть то, что должно быть прямо перед моим лицом.

У меня есть класс Binary, который включает частный метод для получения значения URI из значения пути (uri и путь являются атрибутами класса). Я звоню self.get_uri_from_path() из Binary.upload(), но получаю:

Attempt to call private method

Фрагмент модели выглядит так:

class Binary < ActiveRecord::Base
  has_one :image

  def upload( uploaded_file, save = false )
    save_as = File.join( self.get_bin_root(), '_tmp', uploaded_file.original_path )

    # write the file to a temporary directory
    # set a few object properties

    self.path   = save_as.sub( Rails.root.to_s + '/', '' )
    self.uri    = self.get_uri_from_path()
  end

  private

  def get_uri_from_path
    return self.path.sub( 'public', '' )
  end
end

Я неправильно звоню? Я упускаю что-то еще более фундаментальное? Единственное место, откуда Binary.get_uri_from_path() вызывается - на данный момент - это Binary.upload(). Я ожидаю, что смогу вызывать частный метод из того же класса, если только Ruby не делает что-то заметно отличное от других языков, которые я использовал.

Спасибо.


person Rob Wilkerson    schedule 19.08.2009    source источник


Ответы (3)


Не делай

self.get_uri_from_path()

do

get_uri_from_path()

Потому что...

  class AccessPrivate
    def a
    end
    private :a # a is private method

    def accessing_private
      a              # sure! 
      self.a         # nope! private methods cannot be called with an explicit receiver at all, even if that receiver is "self"
      other_object.a # nope, a is private, you can't get it (but if it was protected, you could!)
    end
  end

через

person marcgg    schedule 19.08.2009
comment
Спасибо. Еще немного копания помогло мне понять разницу между частными методами Ruby и другими языками. Я просто не ожидал различий на таком уровне. - person Rob Wilkerson; 19.08.2009
comment
пожалуйста. Это правда, это немного сложнее, но на самом деле это имеет смысл через некоторое время :) - person marcgg; 19.08.2009
comment
Я нахожу, что многие Ruby потрясающие — лаконичные, но выразительные — но мне определенно приходится бороться с дельтами идиом. :-) - person Rob Wilkerson; 20.08.2009

Я считаю, что правильной идиомой в данном случае будет не self.get_uri_from_path(), а просто get_uri_from_path(). Самость избыточна. Дополнительные примечания: * self.path вызывает метод пути для себя, который предположительно определен в родительском классе. Если бы вы хотели получить прямой доступ к переменной экземпляра, вы могли бы сказать @path. (@ — символ переменных экземпляра.) * Круглые скобки для аргументов метода необязательны, за исключением случаев, когда их отсутствие может привести к двусмысленности. При желании вы можете заменить get_uri_from_path() на get_uri_from_path. Это отличается от Javascript, где функция без скобок представляет эту функцию как значение, а не приложение этой функции.

person Thom Smith    schedule 19.08.2009
comment
Да, я знаю о необязательных скобках, но я продолжаю видеть вещи без них, и мне не нравится двусмысленность. Это переменная или метод? Я бы предпочел не задавать себе этот вопрос каждый раз, когда вижу это. Возможно, со временем это станет легче. - person Rob Wilkerson; 20.08.2009

есть черт возьми, где вы можете вызвать частный метод в любой ситуации, а именно:

object.send(:private_method)

Я считаю, что в 1.9 есть другая реализация этого трюка.

person penger    schedule 20.08.2009
comment
Да, в 1.9 есть отправка! метод. - person Thom Smith; 20.08.2009
comment
На данный момент я просто пытаюсь выучить и понять правила. Я буду беспокоиться о том, чтобы сломать их позже. :-) - person Rob Wilkerson; 20.08.2009
comment
1.9.2 не имеет метода send!. Хотя у него есть send. - person Dex; 22.07.2011