我正在编写一个用于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):
答案 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找到,因为包含已命名的库确保应用程序在加载时包含(即服务器启动)