Методы запроса в ruby ​​на рельсах - неопределенный метод `read 'для - PullRequest
2 голосов
/ 04 октября 2010

В рамках изучения ruby ​​/ rails я пытаюсь внедрить http://github.com/professionalnerd/simple-private-messages в свое приложение с нуля, а не просто установить плагин.(Я знаю, это доставляет мне неприятности, но это хороший опыт обучения.)

Я создал модель, и ассоциации кажутся нормальными, и я могу создавать новые сообщения в порядке, и они отображаются в почтовом ящике получателей.Но если я щелкаю, чтобы просмотреть одно сообщение (вызывает метод show в контроллере сообщений), оно начинает искать метод с именем read, например.

undefined method `read' for #<Class:0xb6f9ef78>

Куда я должен поместить метод read,В private_messages_extensions.rb (источник плагина) он имеет:

  module ClassMethods
    # Ensures the passed user is either the sender or the recipient then returns the message.
    # If the reader is the recipient and the message has yet not been read, it marks the read_at timestamp.
    def read(id, reader)
      message = find(id, :conditions => ["sender_id = ? OR recipient_id = ?", reader, reader])
      if message.read_at.nil? && reader == message.recipient
        message.read_at = Time.now
        message.save!
      end
      message
    end
  end

  module InstanceMethods
    # Returns true or false value based on whether the a message has been read by it's recipient.
    def read?
      self.read_at.nil? ? false : true
    end

Какая связь между методами класса и методами Instance в отношении вставки непосредственно в мой собственный контроллер и модель сообщений?Я думал, что вставил

def read(id, reader)
...
end

в модель, но читать?Метод в разделе методов экземпляра кода плагина сбивает меня с толку, и я продолжаю получать сообщение об ошибке при просмотре сообщения.

Помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 04 октября 2010

ClassMethods / InstanceMethods - это стандартная техника Ruby, основанная на этом коде:

def self.included(base)
  base.extend ClassMethods
  base.include InstanceMethods
end 

, которую вы (приблизительно) найдете в исходном коде.Между прочим, есть ActiveSupport :: Concern, который может упростить приведенный выше код (для получения дополнительной информации обратитесь к документации)

Поэтому, когда модуль включен в класс, все методы в модуле ClassMethods становятся class методы целевого класса и все методы в InstanceMethods станут методами экземпляра целевого класса.

Таким образом, ваш метод read является методом класса, который должен вызываться как:

m = MyModel.new
m.read?          # => ok, it is an instance method
MyModel.read     # => ok, it is a class method
m.read           # => oops, WRONG! FAILURE! 
                 # You are calling class method through object

Правила метапрограммирования!

Если вы переписываете код без мета-вещи, вы должны написать его как:

class MyModel
  def self.read
  end

  def read?
  end

end    
0 голосов
/ 04 октября 2010

Я не смотрел на плагин, но, основываясь на стандартах других плагинов, думаю, вам нужно что-то вроде этого:

def self.read(id, reader)
  ...
end

Это сделает метод класса доступнымпозвонив User.read.

(я предполагаю это из-за блока module ClassMethods)

...