Sinatra settings - variables nested in environment not working? (Sinatra::ConfigFile) - ruby

I have a modular Sinatra app using Sinatra::ConfigFile and have broken out my settings into a yaml file so I can modify paths/urls when in different environments.
As a basic example, I have:
development:
url_root: 'http://127.0.0.1:9292'
production:
url_root: 'http://domain.com'
However, settings.url_root does not work (undefined method 'url_root') unless I pull it out of the nested environment block. Checking my environment: p ENV['RACK_ENV'] returns development.
I am using Sinatra 1.4.5, sinatra-contrib 1.4.2
What am I doing wrong?

OK, well it turns out it was a misunderstanding of, what I believe, is a slightly confusingly worded documentation on the Sintara page which states:
But it also can provide specific environment configuration. There are
two ways to do that: at the file level and at the setting level. They
are illustrated, repsectively, as follows:
development:
foo: development
bar: bar
test:
foo: test
bar: bar
production:
foo: production
bar: bar
and
foo:
development: development
test: test
production: production
bar: bar
So, when using a settings yaml file with Sinatra, you want to define the variable name and then nest the environments within it (not the other way around), and the working format for my question above is:
url_root:
development: 'http://127.0.0.1:9292'
production: 'http://domain.com'

Related

Access Sinatra (classic style) settings from models outside main file

I'm upgrading a Sinatra ("classic" style) app to latest released version, from 1.3.3 to 1.4.6. I also use config_file from sinatra-contrib (also upgraded from 1.3.2 to 1.4.6) with multi-environments.
My config file (config/app.yml) looks like:
development: &defaults
console_username: admin
console_password: secret
test:
<<: *defaults
staging:
<<: *defaults
production:
<<: *defaults
On the other hand, I have some POROs under lib/. Before the upgrade, I can access to the settings inside those classes under lib/, but now I can't. In summary, previously I can do something like:
settings.console_username
After the upgrade, I need to access these variables by:
Sinatra::Application.console_username
I reviewed the changelog but I can't find this change documented, am I missing something?
PS: I also found this: Access Sinatra settings from a model. I'm agree with the last answer, probably is a better idea to decouple this thing, and pass the settings to the class.

Running Cucumber tests on different environments

I'm using Cucumber and Capybara for my automated front end tests.
I have two environments that I would like to run my tests on. One is a staging environment, and the other is the production environment.
Currently, I have my tests written to access staging directly.
visit('https://staging.somewhere.com')
I would like to re-use the tests in production (https://production.somewhere.com).
Would it be possible to store the URL in a variable in my step definitions
visit(domain)
and define domain using an environment variable called form the command line? Like
$> bundle exec cucumber features DOMAIN=staging
if I want to point the tests to my staging environment, or
$> bundle exec cucumber features DOMAIN=production
if I want it to run in production?
How do I go about setting this up? I'm fairly new to Ruby and I've been searching the forums for a straight forward information but could not find any. Let me know if I can provide more information. Thanks for your help!
In the project's config file, create a config.yml file
---
staging:
:url: https://staging.somewhere.com
production:
:url: https://production.somewhere.com
Then extra colon in the yml file allows the hash key to be called as a symbol.
In your support/env.rb file, add the following
require 'yaml'
ENV['TEST_ENV'] ||= 'staging'
project_root = File.expand_path('../..', __FILE__)
$BASE_URL = YAML.load_file(project_root + "/config/config.yml")[ENV['TEST_ENV']][:url]
This will default to the staging environment unless you override the TEST_ENV. Then, from your step or hook, you can call:
visit($BASE_URL)
or you might need :/
visit "#{$BASE_URL}"
This will allow you to use
bundle exec cucumber features TEST_ENV=production
I don't use cucumber much but you should be able to do
bundle exec cucumber features DOMAIN=staging
then in your tests use ENV['DOMAIN'] || YOUR_DEFAULT_DOMAIN to utilize this variable. YOUR_DEFAULT_DOMAIN should probably be your test environment.
See Here

Specify environment specific configuration with Sidekiq and plain Ruby

I am trying to figure out how can you write specific Sidekiq configuration depending on the environment. I know that you can write in config/sidekiq.yml something like:
:concurrency: 5
:verbose: false
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
- [carrierwave, 7]
- [client_emails, 5]
- [default, 3]
staging:
:concurrency: 10
production:
:concurrency: 25
However, right now and based on: por.rb, I would have the Redis configuration in that file. But the Redis address changes whether the Sidekiq is running in localhost or in Amazon. So my question is, in pure Ruby, how do you write specific configuration-environment files? I know in Rails you would write specific ones under config/initializers/environment/sidekiq.rb, but what about in pure Ruby?
To support multiple environments in sidekiq - look at this: Sidekiq configuration for multiple environments
For your specific question - how to implement initializers in pure ruby, you can put them anywhere you want, but you need to require them in your main file.
If you want to be a little more sophisticated (or you have a lot of initializers), you can require all of them under a folder (initializers/ for example), and then require anything under that folder:
Dir["/initializers/*.rb"].each {|file| require file }

Using Rake, that loads my db from a YAML file, can i set environments?

My database.yml looks like:
adapter: mysql
database: my_db
username: user1
password: '123'
host: localhost
This is a non-rails application, just using rake/ruby for some scripting.
Can I set a default (dev) and production in this yaml file, or is that rails specific?
If yes, when running something like:
rake user:create
How do I pass in if it is production and therefore use the production db settings in the yaml file?
Where you read the yaml file into memory and parse it is a good place to put the logic to use the current environment (or a default if none is set). A simple way to do this is to rely on an environment variable (don't use RAILS_ENV if it's not a rails app, or RACK_ENV if it's not a rack app).
Use something like:
my_env = ENV['MY_ENV_VARIABLE'] || 'development'
db_settings = YAML::load(File.open(yml_file))[my_env]
Then you can call rake via:
MY_ENV_VARIABLE=production rake my_task
Or if you want to add a param to the task itself, you can set it up to use
rake my_task[production]
(but that can get messy depending on if you have to quote the whole thing, like in zsh).
Another approach that some libraries use (like heroku_san) is to have a separate task that sets the environment variable, and rely on calling multiple tasks, so you'd have a task :production that sets the environment variable and can then call
rake production my_task

Passing options to rackup via a Sinatra application

I'm new to ruby, learning Sinatra. While creating a Sinatra site by requiring 'sinatra' and setting up the routes directly under is pretty easy and rather well documented, creating an application by requiring 'sinatra/base' and writing a class that inherits from 'Sinatra::Base', while still relatively easy, is very poorly documented (maybe because it's a pretty recent feature of Sinatra).
And that's exactly what I am doing. I am not having too much trouble on the Sinatra part, however I am having a bit of trouble on the rackup/thin/server part. Apparently there are two ways to deploy the application: using Sinatra itself (using the run! method) and using a rackup file (typically config.ru).
Using Sinatra's run! method is extremely intuitive and works like a charm, but apparently it doesn't work if I want to deploy my app on heroku. As a matter of fact, almost all the Sinatra apps that I have encountered on GitHub use a config.ru file.
Using a rackup file might be equally intuitive, but I can't manage to understand how to pass options from the Sinatra app to the server (ir: the port). I tried to merge options to rackup's default options array:
MyApp::App.default_options.merge!(
:run => false,
:env => :production,
:port => 4567
)
run MyApp::App
by adding options directly to the app:
MyApp::App.set :port, 4567
MyApp::App.set :run, false
MyApp::App.set :env, :production
run MyApp::App
by setting options from within the application class:
module MyApp
class App < Sinatra::Base
set :port, 4567
set :run, false
set :env, :production
# ...
# config.ru
require 'app'
run MyApp::App
All the methods above failed, either by showing error messages or by just not taking any of the options into consideration. So is there any way to pass options to rackup/thin/the sever via a Sinatra app when using a rackup file? Or the options in questions should be passed directly to rackup/thin/the sever via command-line options?
As a reference to the problem, here is the little Sinatra application I am building: https://github.com/AzizLight/Wiki/
You're actully going to pass options to thin on the command line directly or via a configuration file. See all options:
$ thin -h
For production, use a configuration file:
$ thin -C thin-production.yml -R config.ru start
Here is an example thin-production.yml file:
---
address: localhost
port: 3020
servers: 4
max_conns: 1024
max_persistent_conns: 512
timeout: 30
environment: production
pid: tmp/pids/thin-production.pid
log: log/thin-production.log
daemonize: true
I know I'm resurrecting an ancient question here, but I came across another useful solution not yet mentioned. As stated in this rack wiki tutorial:
the first line starting with #\ is treated as if it was options, allowing rackup arguments to be specified in the config file.
So if you wanted to set your host to 0.0.0.0 and port to 5656, you would add the following line to the beginning of your config.ru file:
#\ -o 0.0.0.0 -p 5656

Resources