2011-08-08 109 views
1

我错过了一些愚蠢的东西。帮帮我?红宝石(导轨) - 包括模型

的lib/api.rb

require 'httparty' 

module API 
    def self.call_api(query) 
    base_url = "http://myapi.com" 
    return HTTParty.get("#{base_url}/#{query}.json") 
    end 
end 

型号/ job.rb

require 'api' 

class Job 
    include API 

    def self.all(page=1) 
    self.call_api "jobs?page=#{page}" 
    end 

end 

Job::all NoMethodError: undefined method `call_api' for Job:Class

如果我提出我的 “call_api” 直接进入作业类,它的工作原理。我错过了什么?

回答

2

其他的答案都指出你的问题,您应该延长,而不是包括:

class Job 
    extend API 

您也不妨考虑采用以下模式这除了是有用的也可以帮助缓解混乱,因为你可以直接告诉你的类方法在ClassMethods模块中,而你的实例方法直接在MyModule模块中。

module MyModule 

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

    module ClassMethods 
    def my_class_method 
    end 
    end 

    def my_instance_method 
    end 
end 

这将使用Ruby的included回调(这被激发每个时间包含在类模块),我们重新定义回调(通常什么都不做),以扩展该模块是班上包含在ClassMethods子模块中。这是Ruby中非常常见的元编程模式。如果你使用这种模式,你再也不用担心扩展,只需使用include

class MyClass 
    include MyModule 

则:

MyClass.my_class_method 
MyClass.new.my_instance_method 

你也可以采取这种模式得远一点:

module MyModule 
    include ClassMethods 

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

    module ClassMethods 
    def my_class_method 
    end 
    end 

    def my_instance_method 
    end 
end 

请注意,父模块直接包含其子模块ClassMethods模块。这样my_class_method同时成为一个实例和类方法:

class MyClass 
    include MyModule 

MyClass.my_class_method 
MyClass.new.my_class_method 

你,如果你做的是有点小心,你怎么ClassMethods子模块代码的方法。但我偶然发现这种模式非常方便。

0

问题是您直接在API模块上定义方法call_api,而不是在Job类的继承链上。

您可以拨打API.call_api就好了,但问题是,API的“实例方法”不继承链(所包含的模块的接收器定义不是实例方法的一部分,但API的单实例的方法 - 记住API是类模块的用自己的方法的实例)

这是做什么你正在尝试做的方式:

module API 
    def self.included(base) 
    def base.call_api(...) 
     ... 
    end 
    end 
end 

但也有可能使用extend而不是更简洁的方式include你的类。