Using a config block at the top of the file throws error - sinatra

I'm trying to set a connection to the database (using Sequel) before the model appears. Well it must be that way but am getting an error
undefined method `configure' for main:Object (NoMethodError)
Here is the code, I don't see anything wrong with setting up the constants there so perhaps it is either something related to the configure block or the config.ru.
require 'sinatra/base'
require 'sequel'
require 'slim'
require 'sass'
require 'sinatra/flash'
require './sinatra/auth'
configure :development do
password = ENV["PGPASSWORD"]
DB = Sequel.postgres('development', user: 'postgres', password: password, host: 'localhost')
end
configure :production do
DB = Sequel.connect(ENV['DATABASE_URL'])
end
Here is the rack file. I tried to do the connect statement in there but failed (so far)
require 'sinatra/base'
require './main'
require './song'
require 'sequel'
map('/songs') { run SongController }
map('/') { run Website}
Not understanding why the configure block will not work.
Edit: I'm guessing because the call to the SongController is in config.ru, the connect statements need to be in there as well.
Edit: And further along , since this is a modular app, a config.yml is probably my best option.

You're using sinatra/base. That means you'll have to use a subclass:
require 'sinatra/base'
require 'sequel'
require 'slim'
require 'sass'
require 'sinatra/flash'
require './sinatra/auth'
class MyApp < Sinatra::Base
configure :development do
password = ENV["PGPASSWORD"]
DB = Sequel.postgres('development', user: 'postgres', password: password, host: 'localhost')
end
configure :production do
DB = Sequel.connect(ENV['DATABASE_URL'])
end
run! if app_file == $0
end
NB: You can just use require sinatra and all the magic without using subclasses will be abailable. Or, if you need a modular app, use Sinatra::Application and you will have all the magic included. See sinatra's readme for full coverage on the differences.

Related

Why I get 500 Error while on XAMPP while loading CodeIgniter 3 database library?

I have gone through number of threads on stackoverflow and on other forums to find the answer but could not find relevant answer. People have applied different approaches but none has worked for me thus far.
I am using CI 3 on XAMPP and whenever I load database library in the model, I run into 500 Error.
Here is my CI database config info:
'hostname' => 'localhost',
'username' => 'my_user',
'password' => 'my_pass',
'database' => 'prod_db',
'dbdriver' => 'mysqli',
'dbprefix' => '',
'pconnect' => FALSE,
PHP ini db libraries are as below:
extension=php_bz2.dll
extension=php_curl.dll
extension=php_fileinfo.dll
;extension=php_ftp.dll
extension=php_gd2.dll
extension=php_gettext.dll
;extension=php_gmp.dll
;extension=php_intl.dll
;extension=php_imap.dll
;extension=php_interbase.dll
;extension=php_ldap.dll
extension=php_mbstring.dll
extension=php_exif.dll ; Must be after mbstring as it depends on it
extension=php_mysqli.dll
;extension=php_oci8_12c.dll ; Use with Oracle Database 12c Instant Client
;extension=php_openssl.dll
;extension=php_pdo_firebird.dll
extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
;extension=php_pdo_odbc.dll
;extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll
;extension=php_pgsql.dll
;extension=php_shmop.dll
; The MIBS data available in the PHP distribution must be installed.
; See http://www.php.net/manual/en/snmp.installation.php
;extension=php_snmp.dll
My model code is as below:
class loginmodel extends CI_Model {
public function validate_login($username, $password) {
$this->load->database();
$var = 0;
return $var;
}
}
Whenever I remove $this->load->database(); from the model, my code runs and i am able to redirect to a "Login Failed" page. BUT, whenever I load my database library in autoload.php or load it in above model, code fails.
Autoload.php
$autoload['libraries'] = array('database');
Apache error logs showed below errors but I could not figure as why this was happening.
PHP Warning: PHP Startup: Unable to load dynamic library 'C:\\php\\ext\\php_mysqli.dll' - The specified module could not be found.\r\n in Unknown on line 0
PHP Warning: PHP Startup: Unable to load dynamic library 'C:\\php\\ext\\php_pdo_mysql.dll' - The specified module could not be found.\r\n in Unknown on line 0
Please advise.
EDIT:
I verified all config to be OK and as stated in the comments, I added environment variables to windows and verified through PHPInfo that mysqli and mysqlnd were loaded.
Despite getting all the config right, error still persisted and I did a clean install of CI to reproduce library load failure. This time CI returned an error that db access was denied.
I then realized that after migration, database user was not created in the new environment. So once I created the desired user and assigned it required privileges, I was able to run the code just fine.
Therefore, if anyone encounters such issue in future, below steps might help:
First and foremost, verify if your desired user can access the
database.
Modify your .htaccess to use your desired URL schemes only after
verifying that database connection is working
Then verify that absolute path is available in PHP.ini on XAMPP.
Plus, verify that PHP is added in the environment variables. My
Values on Windows 10 are as follows: Variable Name: PHP , Variable
Value: C:\xampp\php\ext
In CI, mysqli is selected as database driver
In PHP.ini mysqli extension is enabled. i.e. php_mysqli.dll
Echo PHPInfo to verify that mysqli and mysqlnd are available in your
installation.
If nothing works, do a clean install of CI on a separate directory and load database library after setting up your database configuration and before setting up .htaccess until you can reproduce the error.
Hope that error will be eliminated!

Sails.js HOWTO: implement logging for HTTP requests

With the poor default logging of Sails.js not showing http request logs(even on verbose). What is the best way implement http request logging to console so i can see if I am getting malformed requests? Expressjs's default logging would be enough.
I would prefer a Sails.js configuration way of doing it rather then a change the source code approach is possible.
Has anyone had experience with this. My google searches seem oddly lacking information.
Running Sails v0.9.8 on Mac OSX.
There's no Sails config option to log every request, but you can add a quick logging route at the top of config/routes.js that should do the trick:
// config/routes.js
'/*': function(req, res, next) {sails.log.verbose(req.method, req.url); next();}
Maybe too late, but for future references about this, I'm using Sails 0.11 and you can config that in the middleware, in the config/http.js file
Add this function (in fact it comes as an example)
// Logs each request to the console
requestLogger: function (req, res, next) {
console.log("Requested :: ", req.method, req.url);
return next();
},
And setup it on the order var:
order: [
'startRequestTimer',
'cookieParser',
'session',
'requestLogger', // Just here
'bodyParser',
'handleBodyParserError',
'compress',
'methodOverride',
'poweredBy',
'$custom',
'router',
'www',
'favicon',
'404',
'500'
]
I forked the sails-hook-requestlogger module to write all the request logs (access logs) to file.
sails-hook-requestlogger-file
All you have to do is npm install sails-hook-requestlogger-file and you are good to go!
Usage
Just lift your app as normal and all your server requests will be logged, with useful information such as response-time, straight to your console. As a default it is activated in your dev environment but deactivated in production.
Configuration
By default, configuration lives in sails.config.requestloggerfile
You can create config/requestlogger.js and override these defaults:
Parameter Type Details
format ((string)) Defines which logging format to use. Deaults to dev.
logLocation ((string)) Defines where to log: console or file. Defaults to console.
fileLocation ((string)) Location of file relative to project root (if file is specified in logLocation. This has no effect if console is specified in logLocation.
inDevelopment ((boolean)) Whether or not to log requests in development environment. Defaults to true.
inProduction ((boolean)) Whether or not to log requests in production environment Defaults to false.
Example config/requestlogger.js file:
module.exports.requestloggerfile = {
//see: https://github.com/expressjs/morgan#predefined-formats for more formats
format: ':remote-addr - [:date[clf]] ":method :url" :status :response-time ms ":user-agent"',
logLocation: 'file',
fileLocation: '/var/log/myapp/access.log',
inDevelopment: true,
inProduction: true
};
Hope that it would help someone :)
I found this matched my needs - it uses the Morgan module for Express and hooks it all up for you: https://www.npmjs.com/package/sails-hook-requestlogger

How to deploy symfony2 - my dev env works but not prod

I have read the cookbook regarding deploying my symfony2 app to production environment. I find that it works great in dev mode, but the prod mode first wouldn't allow signing in (said bad credentials though I signed in with those very credentials in dev mode), and later after an extra run of clearing and warming up the prod cache, I just get http500 from my prod route.
I had a look in the config files and wonder if this has anything to do with it:
config_dev.php:
imports:
- { resource: config.yml }
framework:
router: { resource: "%kernel.root_dir%/config/routing_dev.yml" }
profiler: { only_exceptions: false }
web_profiler:
toolbar: true
intercept_redirects: false
monolog:
handlers:
main:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: debug
firephp:
type: firephp
level: info
assetic:
use_controller: true
config_prod:
imports:
- { resource: config.yml }
#doctrine:
# orm:
# metadata_cache_driver: apc
# result_cache_driver: apc
# query_cache_driver: apc
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: debug
I also noticed that there is a routing_dev.php but no routing_prod, the prod encironment works great however on my localhost so... ?
In your production environment when you run the app/console cache:warmup command you need to make sure you run it like this: app/console cache:warmup --env=prod --no-debug Also, remember that the command will warmup the cache as the current user, so all files will be owned by the current user and not the web server user (eg: www-data). That is probably why you get a 500 server error. After you warmup the cache run this: chown -R www-data.www-data app/cache/prod (be sure to replace www-data with your web server user.
Make sure your parameters.ini file has any proper configs in place since its common for this file to not be checked in to whatever code repository you might be using. Or (and I've even done this) its possible to simply forget to put parameters from dev into the prod parmeters.ini file.
You'll also need to look in your app/logs/prod.log to see what happens when you attempt to login.

Config CarrierWave with Mongoid - GridFS

I am getting a trouble, trying to use CarrierWave for a file upload Rest API developed in Rails 3, with a MongoDB database.
What I would like to do is storing some files (not only images but every file format) with the MongoDB system GridFS.
I read many documentations that recommend my to use the CarrierWave gem.
But I have an error when I try to configure it.
My development environment :
The Gemfile :
source 'https://rubygems.org'
gem 'rails', '3.2.8'
# MongoDB
gem 'mongoid', :git => 'git://github.com/mongoid/mongoid.git'
gem 'carrierwave', :git => "git://github.com/jnicklas/carrierwave.git"
# gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
gem 'mini_magick', :git => 'git://github.com/probablycorey/mini_magick.git'
gem 'bson_ext'
gem 'json'
The application.rb :
require File.expand_path('../boot', __FILE__)
# ActiveRecord will not be use with MongoDB
# require 'rails/all'
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"
require "sprockets/railtie"
require "mongoid/railtie"
require "carrierwave"
# require "carrierwave/mongoid"
I define the database with a mongoid.yml (config/mongoid.yml) file :
development:
sessions:
default:
database: lf_rest_api_development
hosts:
- localhost:27017
options:
consistency: :strong
options:
test:
sessions:
default:
database: lf_rest_api_test
hosts:
- localhost:27017
options:
consistency: :strong
And load it with an initializer (config/initializers/mongoid.rb) :
Mongoid.load!("config/mongoid.yml")
-- I can execute the "rails server" command without problems after the last file, config/initializers/carrierwave.rb :
CarrierWave.configure do |config|
config.grid_fs_database = Mongoid.database.name
config.grid_fs_host = Mongoid.config.master.connection.host
config.storage = :grid_fs
config.grid_fs_access_url = "/files"
end
And then get the following error when I run the "rails server" command :
=> Booting WEBrick
=> Rails 3.2.8 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Exiting
/{API_path}/config/initializers/zcarrierwave.rb:4:in `block in <top (required)>': undefined method `database' for Mongoid:Module (NoMethodError)
[...]
My file model is defined as following :
require 'carrierwave/orm/mongoid'
class File
include Mongoid::Document
store_in_collection: "files", database: "lf_rest_api_developement", session: "default"
key :filename, type: String
key :content_type, type: String
key :length, type: BigDecimal
key :chunk_size, type: Integer, :default => 256
key :upload_date, type: DateTime
key :md5, type: String
key :metadata, type: Array, :default => []
mount_uploader :file, FileUploader
index({ location: "2d" }, { min: -200, max: 200 })
end
The FileUploader is just an extension of CarrierWave uploader...
class FileUploader < CarrierWave::Uploader::Base
storage :grid_fs
end
Sorry about the slow response. Firstly, the reason for your error is that Mongoid 3 no longer supports Mongoid.database. You can now find these configurations in the Mongoid::Config.sessions[:default] object.
BUT THIS AIN'T GONNA FIX YOUR PROBLEM! Mongoid 3 has no GridFS support at all. From mongoid docs:
No GridFS Support
GridFS is marketed as a core database feature, when in fact it is not. It is simply a pattern for storing chunked file data as documents in a collection, just like any other document. The implementation of this behaviour is handled in the client drivers, not in the core database itself, which can lead to discrepencies in how this is handled across > platforms.
Even if having this behaviour in the client is acceptable, the effects of this on application performance where you are not just storing file data is quite large. Since files are stored as documents, they consume RAM just as any other document in the database would, and can easily cause memory consumption on your server to max out. There are also limitations in chunking the data, such as you do not have the ability to update a file - you must delete the file and replace it with a new one.
Given this, we did not prioritize any work with GridFS at the front, but there is a gem in the pipeline for those who can wait a bit to upgrade. In the meantime you have a few options...
So rather than seek other ways to store uploads in the GridFS at the expense of performance, I would suggest just throwing them in a SQL database. If your using Mongo as your only database, don't be put off by this option. It's not very difficult to get ActiveRecord and Mongoid working together side-by-side. But from my experience, uploading binary objects to any database may not perform well. I would personally use a filesystem for storage, with carrierwave or paperclip taking care of the management. Alternatively, I would suggest checking out some cheap cloud storage options. You can use something like aws-s3, a great service. It also has very well documented compatibility with Carrierwave.
If you are determined to use GridFS, I would check out the mongoid-grid_fs gem or check out some alternative ruby MongoDB drivers on the 10gen website.
This is my first time answering a question so I hope I'm doing this right.
I was struggling with the same issue uploading an image using carrier wave in my rails application with Mongoid 3. I believe I have a solution (at least got it working locally on my laptop.) Here is what I came up with:
Add carrierwave-mongoid gem to your gemfile with the branch mongoid-3.0. This gem uses mongoid-grid_fs:
# Image Uploading
gem "carrierwave-mongoid", :git => "git://github.com/jnicklas/carrierwave-mongoid.git", :branch => "mongoid-3.0"
Make an initializer for carrier wave:
#config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.storage = :grid_fs
# Storage access url
config.grid_fs_access_url = "/upload/grid"
end
I know I didn't set config.grid_fs_database or config.grid_fs_host. This seems to work locally (on my laptop) I haven't tried it with a remote gridfs database.
Mounting looks normal:
#app/models/user.rb
class User
include Mongoid::Document
mount_uploader :avatar, AvatarUploader
end
Uploader is also standard:
#app/uploaders/avatar_uploader
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
def store_dir
"#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :resize_to_limit => [200, 200]
end
end
Create a controller for GridFS:
#app/controllers/gridfs_controller.rb
class GridfsController < ApplicationController
def serve
gridfs_path = env["PATH_INFO"].gsub("/upload/grid/", "")
begin
gridfs_file = Mongoid::GridFS[gridfs_path]
self.response_body = gridfs_file.data
self.content_type = gridfs_file.content_type
rescue
self.status = :file_not_found
self.content_type = 'text/plain'
self.response_body = ''
end
end
end
and add the route to the routes file:
#config/routes.rb
match "/upload/grid/*path" => "gridfs#serve"
Hope this helps.

how to solve 'Mysql2::Error: This connection is still waiting for a result' error with mysql2 and activerecord

Not duplicate of this question with the same title
I am using activerecord with mysql2 and I am designing to handle 10 queries to the same activerecord model/class at a time. Please note I am using strict activerecord and not using mysql queries directly.
I get the calls in Sinatra and then use activerecord to get the data from the DB.
I don't wan't the calls to be blocking so therefore I used mysql2 and I do NOT want to use em-synchrony.
But now I get the following "Mysql2::Error: This connection is still waiting for a result, try again once you have the result:" on subsequent simultanous calls.
I am not establishing connection with pool=10
my class
class User < ActiveRecord::Base
and my code to call
user.find(:all, :conditions => ["id=?", userid])
The mysql2 doc says "To use the ActiveRecord driver (with or without rails), all you should need to do is have this gem installed and set the adapter in your database.yml to "mysql2". That was easy right? :)"
And that is exactly what I have done when I moved from mysql to mysql2.
Why am I getting this error.
Here is a fully working example:
require 'rubygems'
gem 'activerecord', '~> 3.1.0'
gem 'sinatra', '~> 1.3.1'
gem 'mysql2', '~> 0.3.11'
require 'active_record'
require 'sinatra/base'
require 'mysql2'
# thin use the eventmachine thread pool
# you should have at least one connection per thread
# or you can expect errors
EM::threadpool_size = 10
# connect to the database
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:database => "test",
:username => "root",
:encoding => 'utf8',
# number of connections openened to the database
:pool => 10
)
class App < Sinatra::Base
get '/db' do
ActiveRecord::Base.connection.execute("SELECT SLEEP(1)")
end
end
run App
to run it save the file as "config.ru" and run it with thin in threaded mode:
thin start -e production --threaded
You can use ab to check that everything is working, I used a tool called siege:
siege -c 10 -r 1 http://localhost:3000/db
You should use a ConnectionPool... Somehow you have 2 connections in a race condition.
I dont use Sinatra, I use Rails, but I had the same problem and solved it like that:
# class ActiveRecord::Base
# mattr_accessor :shared_connection
# ##shared_connection = nil
#
# def self.connection
# ##shared_connection || retrieve_connection
# end
# end
#
# ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || ConnectionPool::Wrapper.new(:size => 1) { retrieve_connection }
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
You have to use a connection pool. mysql2 allows the queries to be async, but you can still only send one query at a time to MySQL through one connection. If you send multiple queries through one connection you get the waiting for results message.
Use a connection pool and you should be fine.