Thin throws error: undefined method "call" - ruby

I'm having trouble getting thin to run my webapp. It starts up just fine, but whenever I make a request thin craps out and I get the following popping up in the log:
>> Listening on 0.0.0.0:3000, CTRL+C to stop
!! Unexpected error while processing request: undefined method `call'
for #<Rack::Request:0x7f104facb640>
This configuration worked just fine on my Debian server; I'm running Gentoo now.
This is my rackup file:
require 'toto'
# Rack config
use Rack::Static, :urls => ['/css', '/js', '/images', '/favicon.ico', '/pubkey.asc'], :root => 'public'
use Rack::Request
use Rack::CommonLogger
if ENV['RACK_ENV'] == 'development'
use Rack::ShowExceptions
end
#
# Create and configure a toto instance
#
toto = Toto::Server.new do
#
# Add your settings here
# set [:setting], [value]
#
set :author, "jibcage" # blog author
set :title, "Going to Grass" # site title
set :root, "index" # page to load on /
# set :date, lambda {|now| now.strftime("%d/%m/%Y") } # date format for articles
set :markdown, :smart

Delete the line
use Rack::Request

Related

api-pagination gem configuration error in Rails 5 when deployed to heroku

I am using the api-pagination gem and deploying to heroku in a rails 5 app. My configuration is ok in development but fails in production. Here is the config file:
config/initializers/api_pagination.rb
ApiPagination.configure do |config|
# If you have both gems included, you can choose a paginator.
config.paginator = :will_paginate
# By default, this is set to 'Total'
config.total_header = 'X-Total'
# By default, this is set to 'Per-Page'
#config.per_page_header = 'X-Per-Page'
# Optional: set this to add a header with the current page number.
#config.page_header = 'X-Page'
# Optional: what parameter should be used to set the page option
config.page_param = :page
# or
config.page_param do |params|
params[:page][:number]
end
# Optional: what parameter should be used to set the per page option
config.per_page_param = :per_page
# or
config.per_page_param do |params|
params[:page][:size]
end
end
Here is the error from the heroku logs:
[INFO ] Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms)
[FATAL] NoMethodError (undefined method `[]' for nil:NilClass):
[FATAL] config/initializers/api_pagination.rb:18:in `block (2 levels) in <top (required)>'
The controller action is very simple right now:
def index
listings = Listing.where(active: true)
paginate json: listings
end
I am including no parameters in the route.
In my situation, most of the configuration was unnecessary. I'm not sure why it was causing an error but the defaults for my case are fine, except that I use will_paginate. This is my config file and it works:
ApiPagination.configure do |config|
# If you have both gems included, you can choose a paginator.
config.paginator = :will_paginate
end
If someone follows up with a solution that addresses the error, I will accept it. It might be useful for someone else that requires more of the non-default settings.

Accessing global Sinatra object

I am trying to write a helper class in my Sinatra application. I'm trying to access Sinatra properties somehow but always getting nil. My code is as follows:
app.rb:
configure do
enable :sessions
set :session_secret, "STHSTHSTH"
# DATABASE_URL is provided by environment, or can be set on the command line
# For instance: DATABASE_URL=mysql://localhost/freecoins rackup
# will run the app with the database at localhost/freecoins.
DataMapper.setup(:default, ENV['DATABASE_URL'])
# These set it up to automatically create/change tables when
# their models are updated.
DataMapper.auto_migrate!
DataMapper.auto_upgrade!
# Here we read in the config file and parse the JSON from it.
config = JSON.parse(File.read("config/config.json"))
# Then we loop through each element in the JSON object and
# assign it to Sinatra's settings.
# They are accessed via settings.key anywhere in the app,
# especially in some of the routes.
config.each do |k, v|
set k.to_sym, v
end
end
set :views, 'views'
Dir["routes/*.rb"].each {|file| require_relative file }
Dir["models/*.rb"].each {|file| require_relative file }
Dir["helpers/*.rb"].each {|file| require_relative file }
# This has to be called once all the models have been defined.
DataMapper.finalize
helper class:
class WalletHelper
#currency = nil
#client = nil
def initialize(currency)
puts $settings #settings is nil here
end
end
How can I access properties of the app, settings for example, as I do in get blocks?
You should try Sinatra::Base.settings
you may want to see Sinatra.register and Sinatra.helpers
see http://www.sinatrarb.com/extensions.html for more details

How to make rack session cookies httponly?

I am using Ruby and Sinatra to develop an application.
I use
enable :sessions
in order to use the session variable provided by rack. How can I make all of the session cookies be HTTPOnly? Is it like this by default? I can't find any documentation on this.
Instead of enable :sessions:
use Rack::Session::Cookie, {:httponly => true }
I'd suggest using the encrypted_cookie gem instead, it's far more secure. As an example, here's what I'll probably have for a project:
# app/main.rb
module Example
class App < Sinatra::Base # this class in its own file
# stuff here
end
end
# app/config.rb
require "main"
module Example
def self.app #
Rack::Builder.app do
cookie_settings = {
:key => 'usr',
:path => "/",
:expire_after => 86400, # In seconds, 1 day.
:secret => ENV["COOKIE_KEY"], # load this into the environment of the server
:httponly => true
}
cookie_settings.merge!( :secure => true ) if ENV["RACK_ENV"] == "production"
# AES encryption of cookies
use Rack::Session::EncryptedCookie, cookie_settings
# other stuff here
run App
end
end
end
# config.ru
require "app/config"
run Example.app # this in the rackup file
(To clarify why I've laid it out this way - this kind of stucture allows me to split the app up and use it easier in tests by just requiring the app/config.rb. YMMV)

I can't get a backtrace in Rails 3

I'm trying to run the usual rails commands (rails s, rails g, rails c, etc) and I'm getting errors (because I'm migrating from MRI ruby and postgres to jruby and neo4j), which would be fine if only there was a stack trace.
It looks like this:
$ rails s
NameError: uninitialized constant Authorization::ActiveRecord
I'm expecting errors like this because Neo4j doesn't use ActiveRecord and it no longer exists, but I really need to see which file is calling ActiveRecord so I can fix this. But nothing I've found from google or tried in the code has brought the backtrace back to me. ;_;
My config/application.rb is:
require File.expand_path('../boot', __FILE__)
require 'action_controller/railtie'
require 'action_mailer/railtie'
require 'active_resource/railtie'
require 'rails/test_unit/railtie'
require 'sprockets/railtie'
require 'neo4j'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require *Rails.groups(:assets => %w(development test))
# If you want your assets lazily compiled in pro duction, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module MyApp
class Application < Rails::Application
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, chanmge this if you want to expire all your assets
config.assets.version = '1.1'
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
# this was done to load all modules in lib
# following directions at: https://stackoverflow.com/questions/3356742/best-way-to-load-module-class-from-lib-folder-in-rails-3/3962321#3962321
config.autoload_paths += Dir["#{config.root}/lib/**/"]
#for rails-ckeditor
config.autoload_paths += %W( #{config.root}/app/models/ckeditor )
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
# JavaScript files you want as :defaults (application.js is always included).
# config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
end
end
And my config/environments/development.rb is:
MyApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
#config.action_view.debug_rjs = true $ turn off for rails 3.1
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
#Devise wants this:
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
config.log_level = :debug
# Do not compress assets
config.assets.compress = false
# Expand the lines which load the assets
config.assets.debug = true
end
I'm not aware of any other files that might effect the logger/backtrace situation. I'd include more but this feels like such a general problem I'm really not sure what to include.
Update: I'm pretty sure this question is a duplicate of here (althought I'm trying to get it working in any environment).

Ruby Rack - mounting a simple web server that reads index.html as default

I'm trying to get some information from this tutorial: http://m.onkey.org/2008/11/18/ruby-on-rack-2-rack-builder
basically I want to have a file config.ru that tell rack to read the current directory so I can access all the files just like a simple apache server and also read the default root with the index.html file...is there any way to do it?
my current config.ru looks like this:
run Rack::Directory.new('')
#this would read the directory but it doesn't set the root to index.html
map '/' do
file = File.read('index.html')
run Proc.new {|env| [200, {'Content-Type' => 'text/html'}, file] }
end
#using this reads the index.html mapped as the root but ignores the other files in the directory
So I don't know how to proceed from here...
I've also tried this following the tutorials example but thin doesn't starts properly.
builder = Rack::Builder.new do
run Rack::Directory.new('')
map '/' do
file = File.read('index.html')
run Proc.new {|env| [200, {'Content-Type' => 'text/html'}, file] }
end
end
Rack::Handler::Thin.run builder, :port => 3000
Thanks in advance
I think that you are missing the the rackup command. Here is how it is used:
rackup config.ru
This is going to run your rack app on port 9292 using webrick. You can read "rackup --help" for more info how you can change these defaults.
About the app that you want to create. Here is how I think it should look like:
# This is the root of our app
#root = File.expand_path(File.dirname(__FILE__))
run Proc.new { |env|
# Extract the requested path from the request
path = Rack::Utils.unescape(env['PATH_INFO'])
index_file = #root + "#{path}/index.html"
if File.exists?(index_file)
# Return the index
[200, {'Content-Type' => 'text/html'}, File.read(index_file)]
# NOTE: using Ruby >= 1.9, third argument needs to respond to :each
# [200, {'Content-Type' => 'text/html'}, [File.read(index_file)]]
else
# Pass the request to the directory app
Rack::Directory.new(#root).call(env)
end
}
I ended up on this page looking for a one liner...
If all you want is to serve the current directory for a few one-off tasks, this is all you need:
ruby -run -e httpd . -p 5000
Details on how it works: http://www.benjaminoakes.com/2013/09/13/ruby-simple-http-server-minimalist-rake/
You can do this using Rack::Static
map "/foo" do
use Rack::Static,
:urls => [""], :root => File.expand_path('bar'), :index => 'index.html'
run lambda {|*|}
end
For me, using Ruby 2.0 and Rack 1.5.2, sinm solution worked for serving the index page (both as default page for root and loaded explicitly), but for other files I obtained errors similar to the following:
Rack::Lint::LintError: Status must be >=100 seen as integer
I combined sinm solution with this SO answer and the snippet found on Heroku documentation to obtain the desired behavior (assuming that the entire site is contained in a folder called public):
use Rack::Static,
:urls => ["/images", "/js", "/css"],
:root => "public",
:index => 'index.html'
run Rack::File.new("public")
My example for doing the exact same below:
module Rack
class DirectoryIndex
def initialize(app)
#app = app
end
def call(env)
index_path = ::File.join($documentRoot, Rack::Request.new(env).path.split('/'), 'index.html')
if ::File.exists?(index_path)
return [200, {"Content-Type" => "text/html"}, [::File.read(index_path)]]
else
#app.call(env)
end
end
end
end
require 'rack_directory_index.rb'
$documentRoot = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'build'))
Capybara.app = Rack::Builder.new do |builder|
puts "Creating static rack server serving #{$documentRoot}"
use Rack::DirectoryIndex
run Rack::Directory.new($documentRoot)
end
Capybara.configure do |config|
config.run_server = true
end
The solution is mostly a copy and paste from different answers but it works fine. You can find it as a gist here aswell, good luck

Resources