Sinatra Set Configuration File on Heroku - heroku

I have been struggling for the last couple hours with this question, and I hope someone can help me out. I'm creating my first Sinatra app and I would like to use Mongo as the backend. I have decided to use Heroku's MongoLab service, and it gave me a connection URI to use to connect with Mongo from within my Sinatra app. This does not seem like the type of info I want to keep in Version Control, but I'm having a hard time figuring out how to not hardcode it into the application. On one hand the key is stored permanently as a Heroku ENV var, but that does not help when I'm developing locally. I've tried creating a config file as outlined here: http://www.miqueloliete.com/configuring-environment-variables-in-sinatra/, but it only helps locally. I can't seem to find the way to do this.
Thanks in advance,
Ryan

There are many ways to achieve these so I can just give you ideas.
Env
You can set the enviroment variable on your local pc with export name=mongourl
configuration
Sinatra provide a way to use different configuration sections. That is what I do normaly. Like these:
configuration :development do
setup things to use your local db
end
configuration :production do
setup things for production db
end
config file
Store these informations in a yaml file.

I figured out the best way to do it for me. I didn't realize that in Ruby ENV['somevar'] accessed your environmental variables for your shell, so in order to not commit my secret keys and passwords to version control, I just make sure that all my environmental variables that I had in my Heroku (the results of heroku config) were also variables in my shell.

You can use the dotenv gem and then create a .env file locally that has the same keys as your Heroku ENV variables. That way you can keep the same environment keys in your code for both environments, and choose to have identical or different values, as needed.
#app.rb
require 'sinatra/base'
...
if Sinatra::Base.environment == :development
require 'dotenv'
Dotenv.load
end
#.env
DATABASE_URL=mongo_sinatra_connection_info

Related

How do I exclude my API KEY pushing to github?

if I exclude the file with API KEY and push to gitHub and then to Heroku the app doesn't work because the app can't get access to the api key.
What is the workaround? I'm quite a novice so comments or info with human readable language would be highly appreciated. Thanks!
You need to store the API key as an environment variable.
In heroku, go to your app, then settings and click on "Reveal Config Vars".
In there you can store your API key for your deployed server to use. This is also where you will store DB urls too, etc.
Heroku has interface for setting up environment variables.
So use environment variable locally (from environment or e.g. .env file) and remotely.
Also read on 12-factor-app
Usually this kind of stuff should be kept in Heroku config variables. I find heroku command line more convenience. You can download it here. Then, you can use this command to setup the new Heroku configVar at will.
heroku config:set API_KEY=1234567890 --app your_app_name
To see all configs,
heroku config --app your_app_name
Then, based on the language developed, you can access this configVar from code. For example, you can do this in Ruby on Rails' code.
<%= ENV["MY_API"] %>

Protecting APIs keys on Git-hosted Ruby project

I'm not really sure where to start with this. I'm making a Ruby project that interfaces with a dictionary API, and uses an API key. I don't want anybody and his uncle to be able to see this key, but the project will have to be hosted on GitHub. How can I go about doing this, and accessing the key from the Ruby program?
Clarification: this is for a class, and we have to use GitHub
Normally, you'd put such things in a file like this:
DICTIONARY_API=key_goes_here
and check in a version of the file (named .example or .sample or something) which just contains blanks:
DICTIONARY_API=
Or you could read the key from the environment, using ENV. If you host on Heroku, this is recommended. See also the Dotenv gem and the ENVied gem.
I've seen both methods combined (especially when using Dotenv) by making a .env file for local/non-heroku usage, and using Heroku's config settings on Heroku.
Use the Figaro gem. Documentation
Basically you will use a file called application.yml and store environmental variables. Double check that application.yml is listed in your .gitignore file so nobody can view it on github.
You could set:
# application.yml
API_KEY: my_api_key_here
And then you could set it to another variable in your app with:
# anywhere in your app
api_key = ENV['API_KEY']
For production, you can use Figaro's commands to sync your env variables with Heroku.

Config information for a gem

I am working on a gem that needs to be configured with a hostname, username, and password. I would prefer to store this configuration information in config/directoryservices.yml
How do I make my gem automatically create this file when installed?
I've seen a lot of places say that config information should be passed as hashes with gems. The main use of this gem will be in an app that is installed on ~15 servers. Each server will need different config information.
If it is better to include the YAML code in the app and then pass the data as a hash to the gem, I can do that, but I would still like pointers on the best way to do that.
An example of a gem that uses this kind of config is activeldap
If are you working on rails gem, you can create install generator which will copy default config file and then load it into your app.

Datamapper, use yaml for configuration

I have a Sinatra app which uses DataMapper as it's ORM, it's deployed to Heroku, but I want to change the database details.
Right now before my Models, I'm connecting to my DB like this, but I want to use a yml file to manage the connections details.
DataMapper.setup(:default, ENV['DATABASE_URL'] || "sqlite3::memory:")
If I have a file thats at config/database.yml, how can I change the DataMapper.setup to use the proper ENV? This way I can remove the need for sqlite3 as I'll be running Postgres locally too.
As far as I know, DataMapper doesn't parse .yml. You can look at https://github.com/merb/merb_datamapper/blob/master/lib/merb_datamapper/connection.rb to see how .yml config is consumed in Merb framework.

Heroku and Datamapper problems

I can launch a basic app on Heroku, displaying a message with get '/'... works just fine. However, whenever I try to add sqlite with datamapper, the thing breaks down.
In order to see my app structure, check out the project on github. I've kept the code pretty bare-bones.
In the log from heroku I'm getting:
2011-06-26T21:28:36+00:00 app[web.1]: /app/.bundle/gems/ruby/1.9.1/gems/dm-core-1.1.0/lib/dm-core/adapters.rb:163:in `require': no such file to load -- dm-postgres-adapter (LoadError)
The thing about this is that I'm not using postgres, so I'm confused why it is saying this.
"The thing about this is that I'm not using postgres, so I'm confused why it is saying this."
You're using Heroku, so you are using Postgresql.
In your app.rb you have this line:
DataMapper::setup(:default, ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/notes.db")
which I'm guessing you got from the Heroku database docs. This line basically says "check for the environment variable 'DATABASE_URL', and if it's set use it as the database url, otherwise use the Sqlite url". Running locally this environment variable won't be set, so you'll use the Sqlite url, but on Heroku this will be set to something like (see the page linked above):
postgres://username:password#hostname/database
Datamapper will see that this is a Postgresql url, and try to require the postgres adapter, which isn't installed so will result in the error that you see.
The best solution would be to install Postgresql locally, so that your development and production environments are as similar as possible. If you can't do this, or don't want to, you can specify the Sqlite adapter locally, and the Postgres adapter in production. It'll look something like this in your Gemfile:
group :development do
gem 'dm-sqlite-adapter'
end
group :production do
gem 'dm-postgres-adapter'
end
If you do this you'll need to tell Heroku to which groups to leave out when installing gems, see the Heroku Gem Bunder docs.
You are moving from sqlite to postgres-sql and thus you should include dm-postgres-adapter in your Gemfile (and install it ofcourse).
Heroku only supports a read-only file system (or at least only supports read-only operations for any files that you want to be persistent). Hence, you can't use SQLite on Heroku. Heroku only supports PostgreSQL as a database so you need to configure DataMapper to use PostgreSQL (see Yet Another Geek's answer).
I'd recommend installing PostgreSQL in your development environment if you're planning to deploy to Heroku. Every database is a little different and no ORM will protect you from the differences. A bit of searching for questions tagged heroku and postgresql should show some of the problems you'll have if you develop on top of one database but deploy on another.

Resources