我在Ubuntu / Apache2 / Passenger上运行了一个Sinatra应用程序。
这是一个简单的URL缩短程序,可以在我的登台服务器上运行,但在导入旧数据库(包含缩短的URLS)时开始抛出以下错误:
undefined method `include?' for nil:NilClass
file: resource.rb location: block in attributes= line: 332
完全回溯在这里:
/usr/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/resource.rb in block in attributes=
if model.allowed_writer_methods.include?(setter = "#{name}=")
/usr/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/resource.rb in each
attributes.each do |name, value|
/usr/lib/ruby/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/resource.rb in attributes=
attributes.each do |name, value|
/websites/sinatra/shortener/application.rb in block in <top (required)>
ct.attributes = {
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in call
proc { |a,p| unbound_method.bind(a).call } ]
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block in compile!
proc { |a,p| unbound_method.bind(a).call } ]
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in []
route_eval { block[*args] }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block (3 levels) in route!
route_eval { block[*args] }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in route_eval
throw :halt, yield
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block (2 levels) in route!
route_eval { block[*args] }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block in process_route
block ? block[self, values] : yield(self, values)
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in catch
catch(:pass) do
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in process_route
catch(:pass) do
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block in route!
pass_block = process_route(pattern, keys, conditions) do |*args|
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in each
routes.each do |pattern, keys, conditions, block|
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in route!
routes.each do |pattern, keys, conditions, block|
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in dispatch!
route!
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block in call!
invoke { dispatch! }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block in invoke
res = catch(:halt) { yield }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in catch
res = catch(:halt) { yield }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in invoke
res = catch(:halt) { yield }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in call!
invoke { dispatch! }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in call
dup.call!(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-protection-1.2.0/lib/rack/protection/xss_header.rb in call
status, headers, body = @app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-protection-1.2.0/lib/rack/protection/path_traversal.rb in call
app.call env
/usr/lib/ruby/gems/1.9.1/gems/rack-protection-1.2.0/lib/rack/protection/json_csrf.rb in call
status, headers, body = app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-protection-1.2.0/lib/rack/protection/base.rb in call
result or app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-protection-1.2.0/lib/rack/protection/xss_header.rb in call
status, headers, body = @app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-1.4.1/lib/rack/logger.rb in call
@app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-1.4.1/lib/rack/commonlogger.rb in call
status, header, body = @app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-1.4.1/lib/rack/head.rb in call
status, headers, body = @app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/rack-1.4.1/lib/rack/methodoverride.rb in call
@app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/showexceptions.rb in call
@app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in block in call
synchronize { prototype.call(env) }
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in synchronize
yield
/usr/lib/ruby/gems/1.9.1/gems/sinatra-1.3.2/lib/sinatra/base.rb in call
synchronize { prototype.call(env) }
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/rack/request_handler.rb in process_request
status, headers, body = @app.call(env)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_request_handler.rb in accept_and_process_next_request
process_request(headers, input_stream, connection, full_http_response)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_request_handler.rb in main_loop
if !accept_and_process_next_request(socket_wrapper, channel, buffer)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/rack/application_spawner.rb in start_request_handler
handler.main_loop
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/rack/application_spawner.rb in block in handle_spawn_application
self.class.send(:start_request_handler, MessageChannel.new(b),
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/utils.rb in safe_fork
yield
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/rack/application_spawner.rb in handle_spawn_application
safe_fork('application', true) do
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server.rb in server_main_loop
__send__(@message_handlers[name], client, *args)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server.rb in start_synchronously
server_main_loop(password, server_socket)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server.rb in start
start_synchronously(@socket_filename, @password, server_socket, b)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/rack/application_spawner.rb in start
super
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/spawn_manager.rb in block (2 levels) in spawn_rack_application
spawner.start
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server_collection.rb in lookup_or_add
server = yield
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/spawn_manager.rb in block in spawn_rack_application
spawner = @spawners.lookup_or_add(key) do
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server_collection.rb in block in synchronize
yield
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server_collection.rb in synchronize
@lock.synchronize do
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/spawn_manager.rb in spawn_rack_application
@spawners.synchronize do
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/spawn_manager.rb in spawn_application
return spawn_rack_application(options)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/spawn_manager.rb in handle_spawn_application
app_process = spawn_application(options)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server.rb in server_main_loop
__send__(@message_handlers[name], client, *args)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/lib/phusion_passenger/abstract_server.rb in start_synchronously
server_main_loop(password, server_socket)
/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.12/helper-scripts/passenger-spawn-server in <main>
spawn_manager.start_synchronously(socket_filename, socket_password, server_socket, owner_socket)
主application.rb文件如下:
require 'rubygems'
require 'bundler/setup'
require 'sinatra'
require File.join(File.dirname(__FILE__), 'environment')
configure do
set :views, "#{File.dirname(__FILE__)}/views"
end
configure :development do
DataMapper.auto_upgrade!
# very useful for debugging parameters sent via the console
before do
puts '[Params]'
p params
end
end
error do
e = request.env['sinatra.error']
Kernel.puts e.backtrace.join("\n")
'Application error'
end
helpers do
include Rack::Utils
alias_method :h, :escape_html
def random_string(length)
rand(36**length).to_s(36)
end
def get_site_url(short_url)
SiteConfig.url_base + short_url
end
def generate_short_url(long_url)
@shortcode = random_string 5
su = ShortURL.first_or_create(
{ :url => long_url },
{
:short_url => @shortcode,
:created_at => Time.now,
:updated_at => Time.now
})
get_site_url(su.short_url)
end
end
# root page
get '/' do
if params[:url] and not params[:url].empty?
generate_short_url(params[:url])
else
# you can use this page to redirect to another location
# or to display a front-end form for any site visitors
# get the current count of all links stored
# @urls = ShortURL.all;
# erb :index
end
end
post '/' do
if params[:url] and not params[:url].empty?
generate_short_url(params[:url])
end
# you can use this page to redirect to another location
# or to display a front-end form for any site visitors
# get the current count of all links stored
# @urls = ShortURL.all;
# erb :index
end
# display short url from root
["/get/:short_url", "/:short_url"].each do |path|
get path do
@URLData = ShortURL.get(params[:short_url])
if @URLData
# log the click in the database
ct = ClickTrack.new
ct.attributes = {
:short_url => params[:short_url],
:url => @URLData.url,
:clicked_at => Time.now
}
ct.save
redirect @URLData.url
else
'no short url found'
end
end
end
# expand url data
get '/expand/:hash/?' do
@URLData = ShortURL.get(params[:hash])
if @URLData
content_type :json
{ :url => get_site_url(@URLData.short_url), :long_url => @URLData.url, :hash => params[:hash] }.to_json
else
content_type :json
{ :message => 'No hash parameter was specified or no short URL was found to match the provided hash' }.to_json
end
end
返回缩短的网址(#shrom short url from root)
时发生错误如果有人能帮助我弄清楚它失败的原因,我会非常感激。
非常感谢
答案 0 :(得分:9)
技巧是读取堆栈跟踪。我猜测ClickTrack是一个DataMapper对象,你在它上面调用attributes=
。堆栈跟踪足以从dm-core中提供一些代码:if model.allowed_writer_methods.include?(setter = "#{name}=")
显然,从数据映射器中,model.allowed_writer_methods
返回nil。我根本没有使用过数据映射器,但有一种可能性就是谷歌搜索:
https://github.com/datamapper/dm-core/issues/152
根据http://datamapper.org/getting-started.html,您应该在使用模型之前致电DataMapper.finalize
。
无论如何,这看起来像是一个DataMapper问题。查看ClickTrack并确保它已完成(如果我正确读取)和/或检查DataMapper的使用情况。