我最近继承了一个Rails+Spine.JS项目。尽管它的主题不是非常神秘的(面向市场:人们制作自己的邮件列表,在发送内容之前准备内容,实际发送内容等),但它的实现是特定的,并且依赖于多个Rails覆盖(如下面问题2中指定的)。
我有两个问题需要帮助。
问题一:
关键是:在Spine.JS应用程序(前端)中,我们得到了发票的预览操作,该操作应该(而且确实)打开一个新的选项卡来执行。在我真的这么做之前,一切看起来都很正常。没有太多毫无意义的解释,下面是发生的事情:
Started GET "/me/invoices/22/preview?oauth_token=XE03DFCGyCDYjdu8oWuU9zrN56Z6Wr7eZDuIjCbT&origin=http://localhost:9294" for 94.26.14.131 at 2013-12-08 00:55:27 +0200
Oauth2Token Load (0.3ms) SELECT `oauth_tokens`.* FROM `oauth_tokens` WHERE `oauth_tokens`.`type` IN ('Oauth2Token') AND (invalidated_at IS NULL AND authorized_at IS NOT NULL and token = 'XE03DFCGyCDYjdu8oWuU9zrN56Z6Wr7eZDuIjCbT') LIMIT 1
Processing by InvoicesController#preview as HTML
Parameters: {"oauth_token"=>"XE03DFCGyCDYjdu8oWuU9zrN56Z6Wr7eZDuIjCbT", "origin"=>"http://localhost:9294", "id"=>"22"}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 270932 LIMIT 1
Invoice Load (0.2ms) SELECT `receipts`.* FROM `receipts` WHERE `receipts`.`type` IN ('Invoice') AND `receipts`.`id` = 22 LIMIT 1
Completed 500 Internal Server Error in 8.3ms
NoMethodError (undefined method `identifier' for "preview":String):
newrelic_rpm (3.6.9.171) lib/new_relic/agent/instrumentation/rails3/action_controller.rb:157:in `render_with_newrelic'
actionpack (3.2.16) lib/action_view/renderer/renderer.rb:36:in `render_template'
actionpack (3.2.16) lib/action_view/renderer/renderer.rb:17:in `render'
actionpack (3.2.16) lib/abstract_controller/rendering.rb:110:in `_render_template'
actionpack (3.2.16) lib/action_controller/metal/streaming.rb:225:in `_render_template'
actionpack (3.2.16) lib/abstract_controller/rendering.rb:103:in `render_to_body'
actionpack (3.2.16) lib/action_controller/metal/renderers.rb:28:in `render_to_body'
actionpack (3.2.16) lib/action_controller/metal/compatibility.rb:50:in `render_to_body'
actionpack (3.2.16) lib/abstract_controller/rendering.rb:88:in `render'
actionpack (3.2.16) lib/action_controller/metal/rendering.rb:16:in `render'
actionpack (3.2.16) lib/action_controller/metal/instrumentation.rb:40:in `block (2 levels) in render'
activesupport (3.2.16) lib/active_support/core_ext/benchmark.rb:5:in `block in ms'
/usr/local/rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/benchmark.rb:296:in `realtime'
如您所见,单词preview
是控制器操作的名称。
删除NewRelic没有帮助。然后错误被替换为:
NoMethodError (undefined method `formats' for "preview":String):
顺便说一句,Ruby版本为2.0.0-p353,Rails版本为3.2.16。Rails项目有一些自定义,比如大多数操作的OAuth参数,因为Rails应用程序主要是Node.JS项目的服务器存储单元。
查看API文档(如:http://www.rubydoc.info/docs/rails/3.1.1/ActionView/Template)给我留下的印象是determine_template
Rails方法(在第二种情况下是一个未指定的方法,没有newrelic_rpm
)不会返回ActionView::Template
,而是返回String
。你知道为什么会这样吗?
问题二:
调用rake cucumber
实际上在大多数情况下都会产生这样的结果:
stack level too deep (SystemStackError)
以前的开发人员确实将其作为ActiveRecord::Base
:的扩展
module ActiveRecord
class Base
include Documentable
...
def self.has_url
include Rails.application.routes.url_helpers
self.default_url_options = Rails.application.default_url_options
define_method :url do
send "#{self.class.to_s.underscore}_url", self
end
end
end
end
当然,这可能是原因。我已经尝试过用ActiveRecord::Concern
方法替换那个(相当过时的)方法来扩展ActiveRecord,遗憾的是,这没有什么区别。我已经对这个项目进行了相当广泛的编译,这是其中唯一一个真正包含Rails模块的地方,所以现在应该是这个错误的唯一候选者,是吗?
对于这两个问题,我都不知所措。我在Rails方面有一定的经验(大约15个项目),从未遇到过这样的一年级问题。
感谢您的关注。任何想法都将不胜感激,即使我已经尝试过了。
更新#1:
根据请求,在ApplicationController
中粘贴before_filter
。
def remove_oauth_params
params.reject! {|k,_| %w[oauth_token bearer_token access_token].include? k}
end
def save_action
@current_action = params[:action]
end
def set_access_header
if request.path == "/users/sign_out"
headers["Access-Control-Allow-Credentials"] = "true"
headers["Access-Control-Allow-Headers"] = %w{Origin Accept Content-Type X-Requested-With X-CSRF-Token X-File-Name X-File-Size Cache-Control}.join(",")
headers["Access-Control-Allow-Methods"] = "DELETE"
headers["Access-Control-Allow-Origin"] = "http://#{Settings.app_domain}"
else
headers["Access-Control-Allow-Origin"] = "*"
headers["Access-Control-Allow-Methods"] = %w{GET POST PUT DELETE PATCH}.join(",")
headers["Access-Control-Allow-Headers"] = %w{Origin Accept Content-Type X-Requested-With X-CSRF-Token X-File-Name X-File-Size Cache-Control}.join(",")
end
head(:ok) if request.request_method == "OPTIONS"
end
def set_limit_and_offset
@limit = params.delete(:limit).to_i
@limit = default_limit unless (1..default_limit).include?(@limit)
@offset = params.delete(:offset).to_i
@offset = 0 unless @offset > 0
end
至于InvoiceController
,相当基本:
class InvoicesController < ApplicationController
oauthenticate :interactive => false
layout "invoice"
def preview
@i = Invoice.find(params[:id])
@origin = params[:origin]
end
end
更新#2:
$ rake cucumber --trace
** Invoke cucumber (first_time)
** Invoke cucumber:ok (first_time)
** Invoke db:test:prepare (first_time)
** Invoke db:abort_if_pending_migrations (first_time)
** Invoke environment (first_time)
** Execute environment
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:abort_if_pending_migrations
** Execute db:test:prepare
** Invoke db:test:load (first_time)
** Invoke db:test:purge (first_time)
** Invoke environment
** Invoke db:load_config
** Execute db:test:purge
** Invoke environment
** Execute db:test:load
** Invoke db:test:load_schema (first_time)
** Invoke db:test:purge
** Execute db:test:load_schema
** Invoke db:schema:load (first_time)
** Invoke environment
** Invoke db:load_config
** Execute db:schema:load
** Invoke db:seed (first_time)
** Execute db:seed
** Invoke db:abort_if_pending_migrations
building users for ce and ce-int brands
building example CE app owner
building CE beta app
** Execute cucumber:ok
/usr/local/rvm/rubies/ruby-2.0.0-p353/bin/ruby -S bundle exec cucumber --profile default
Using the default profile...
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Feature: Creation of robinson entries
Create a robinson entry to prevent recipients from being mailed
Background: # features/blocked_address/blocked_address_creation.feature:4
Given there is the example customer with id 200 # features/step_definitions/data_steps.rb:41
stack level too deep (SystemStackError)
features/blocked_address/blocked_address_creation.feature:5:in `Given there is the example customer with id 200'
编辑:有关解决方案,请参阅dimitkos注释
恐怕我没有简单的答案,但只有两个调试建议:
对于问题1:
- 包括Ruby调试器
- 在控制台中,调用
app.get "/me/invoices/22/preview?oauth_token=XE03DFCGyCDYjdu8oWuU9zrN56Z6Wr7eZDuIjCbT&origin=http://localhost:9294"
- 一路往上爬,看看字符串是从哪里来的
至于2:你使用git进行源代码管理吗?
如果是,现在是试用git bisect
的最佳时机。您可以找到一个rake cucumber
仍然有效的旧提交,git可以帮助您在很短的步骤内找到破坏它的提交。更多信息:使用Git调试-二进制搜索