Rails无法识别继承的类方法

时间:2015-04-16 16:25:37

标签: ruby-on-rails-4

我正在编写一个用于API的rails应用程序。我绕过活动记录编写自己的超级类,负责进行api调用。 似乎Rails不喜欢父级中的某些方法名称并接受其他方法名称。当我致电ModelClass.parent_method时,我得到NoMethodError (undefined method parent_method' for ModelClass:Class): 我的代码结构如下:

 #./lib/accounts_api
 module AccountsAPI
   class SomeOtherClass
     . . .
   end

   class AccountModel
     class << self

       #this method works without fail:
       def get id
        url = "path to fetch object"
        response = HTTParty.get(url)
        return self.new response.parsed_response
       end
       # this method cannot be found
       def update_existing options   
        url = "path to update object"
        response = HTTParty.put(url, :body => options)
        return self.new response.parsed_response
       end
    end
 end

然后,派生类:

class BankAccount < AccountsApi::AccountModel
  attr_accessor :id, :customer_id, :reference
  def initialize(options={})
    if options.respond_to? :each
      options.each do |key,val|
        target = "#{key}=".to_sym
        self.send(target, val) if self.respond_to?(target)
      end
    end
  end
end

我的控制器,错误源自:

class BankAccountsController < ApplicationController
  #Works just fine without fail
  def show
    @bank_account = BankAccount.get params[:id]
    respond_to do |format|
      format.json { render :json => @bank_account, :status => :ok }
    end
  end
  #Throws:
  # NoMethodError (undefined method `update_existing' for BankAccount:Class):
  # app/controllers/bank_accounts_controller.rb:21:in update
  # without fail
  def update
    @bank_account = BankAccount.update_existing params[:bank_account]
    respond_to do |format|
      format.json { render :json => @bank_account, :status => :ok }
    end
  end
end

注意:为了清楚起见,我已经从方法(错误处理,验证,赋值等)中省略了一些内部。

解决方法修复:

如果我将update_existing方法名称更改为更加困难的内容,例如put,则可以正常使用。

还有什么是奇怪的,是没有Stacktrace。我刚看到日志中的Rendered rescues layout消息:

Rendered /home/eggmatters/.rvm/gems/ruby-2.1.1@my-gemset/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.6ms)
Rendered /home/eggmatters/.rvm/gems/ruby-2.1.1@my-gemset/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.7ms)
Rendered /home/eggmatters/.rvm/gems/ruby-2.1.1@my-gemset/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (7.0ms)
Rendered /home/eggmatters/.rvm/gems/ruby-2.1.1@my-gemset/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (16.6ms)

更奇怪,从irb调用方法效果很好:

> options = {:id => "23", :customer_id => "123", :reference => "update"}
> BankAccount.update_existing options
=> (:bank_account => { {:id => "23", :customer_id => "123", :reference => "update"}, :id => "23"}

所以我猜,我正在搞乱Rails的消息。我也猜测我的AccountModel父类需要从ActiveRecord或其他rails lib继承一些内容,但这对于研究它来说太过奇怪了(对我而言)。

注意:AccountsAPI模块设置为包含在我的app/initializers目录中。

另外,我忘了提及,重启Passenger和/或Apache没有效果。

更新:执行临时修复/解决方法。将方法名称更改为put仍然不起作用。如果我重新启动乘客很多次,我可以更新它,但它只会工作一次或两次然后回到问题。

更新:我也无法在子模型上调用方法。在模型中,我添加了方法:

class BankAccount < AccountsApi::AccountModel
  . . .
  def self.update_wrapper options
    return self.update options
  end
  . . .
end

现在抛出:

NoMethodError (undefined method `update_wrapper' for BankAccount:Class):

2 个答案:

答案 0 :(得分:0)

看起来在模块中包含父类是某种方式搞乱了rails映射方法的方式。将其拉出(并重新启动乘客)似乎有效:

class BankAccount < AccountModel
  . . .
end

和父母:

module AccountsAPI
  class SomeOtherClass
  . . .
  end
end

class AccountModel
  class << self
    def get id
    . . 
    end

   def update_existing options   
       . . .
   end
end

看起来很有效。不知道为什么。我以前见过:class Child < Module::Parent模式。正如我在帖子中暗示的那样,我错过了一些Railsy(可能是红宝石)的配置方面。

我发现这是另一个模型(只是调用get)实际上是“SomeOtherClass”的一个实例,因此,它将暴露给模块中的类。我仍然愿意接受建议!

答案 1 :(得分:0)

看起来Passenger是全局缓存模块而不是在应用程序重启时更新它。将两个类移动到lib文件夹中各自的脚本以及模块声明一起工作:

# ./lib/some_other_class.rb
class SomeOtherClass
  . . .
end

# ./lib/account_model.rb
class AccountModel
 . . .
end

Rails显然将这些映射到应用程序级别的namspace,因此声明如下:

class MySomeOtherClassModel < SomeOtherClass

class MyAccountModel < AccountModel
通过rails找到

,因为包含已命名的库确保应用程序在加载时包含(即服务器启动)