I am somewhat new to Ruby, especially the more advanced concepts like modules and mixins, so I might be using module totally out of context..
I am currently writing an internal test framework using Capybara and I am trying to figure out the best/easiest way of handling configuration data. I file a file called config.rb and within it I want to store configuration settings per environment. For example:
module QAConfiguration
config data goes here
end
module DevConfiguration
config data goes here
end
The simplest example of configuration data is usernames and password. QA and Dev of course use different users. I am thinking of two different ways of going about this but I want to make sure I am following at least a decent practice and not going into the weeds.
module QAConfiguration
USERNAME = 'test'
PASSWORD = 'test'
end
or..
module QAConfiguration
def username
'test'
end
end
And so on. Which is the best way of approaching this?
A module probably isn't the best way to implement this. Generally when testing (I use rspec) we use helper files that contain reusable code.
Object attributes like usernames and passwords are usually handled by Factories. A great gem for factories is FactoryGirl.
A common way to store configuration in ruby/rails is in a yaml file. You could for example create a file called config/test_conf.yml with yaml format:
username: 'your_user'
password: 'somepass'
Then where you need the config data:
config = YAML.load(File.read("#{Rails.root}/config/test_conf.yml"))
puts config['username']
And finally, you will usually only put a test_config.yml.example on git/svn and in your app setup readme note that they need to cp config/test_config.yml.example config/test_config.yml and edit the file.
Related
I currently build web app which is using external MongoDb via Mongolabs.
The api is based on personal key using in urls. As docs says e.g.:
Here’s an example of a complete Resource URL:
https://api.mongolab.com/api/1/databases?apiKey=**2E81PUmPFI84t7UIc_5YdldAp1ruUPKye**
So the question is how to securely store such api key 2E81PUmPFI84t7UIc_5YdldAp1ruUPKye
Reading Django docs about Cross Site Request Forgery but stil do not understand where the key is recorded.
There are two ways to do this.
One way is to have a local_settings.py file that's imported in the main settings.py file and put into .gitignore so it's not in git. Some people however think this isn't good practice, because it might tempt to put complex things in there that aren't in VCS, so people effectively have different environments. I however am fine with it.
try:
from local_settings import *
except ImportError:
pass # No local_settings file
The other way (recommended by dislikers of the first way) is by setting it via environment variables, and reading these in settings.py.
MONGO_API_KEY = os.environ['MONGO_API_KEY']
You'd then have to pass the environment variable somehow though. E.g. via uwsgi's environ setting, or by setting it in your bash with export, or via another way.
I would load it in the settings file from an environment variable. Have a look at the Django Settings
One alternative is to use the library django-fernet-fields that uses the library cryptography.
The usage is very simple. In your model you need to add a new field:
from django.db import models
from fernet_fields import EncryptedTextField
class MyModel(models.Model):
apikey = EncryptedTextField()
By default, the field is going to be encrypted using the SECRET_KEY from your settings. So if you change it or lose it, you will not be able to access your data.
For better security, you can save your SECRET_KEY as an environment variable, and then pass it to the settings file.
import os
SECRET_KEY = os.environ.get('APP_SECRET_KEY', 'unsafe-secret-key')
django-fernet-fields
Quick answer:
Store in .env
Read in settings.py
Can anyone tell me the difference between include and World? in my env.rb file I want to expose a module, and I can't really see the difference between the approaches...
Module example:
module Test do
...
end
In my env.rb file:
World(Test)
or
include Test
Besides that, can anyone state the pros/cons of using World rather than include in cucumber/ruby?
World(Test) is the preferred method.
The purpose to using World(Test) is that you don't pollute the global namespace yet you still have all the functionality of that module available in your stepdefs.
I have a few Ruby scripts that process text files in different ways, that many of my friends find useful. However, most of the people I know are not comfortable running scripts on the command line. The easiest thing for them would be to create a simple webpage where people could upload a file, select a few options, have it processed, and then download the result.
I know it wouldn't be too hard to build something like this in Rails or Merb or something like that, however it seems like a very common problem, so I was wondering if there was already some kind of template, or similar application that I could easily modify, i.e. let the user upload a file, choose a few options, then {fill in code to do something with file}, let the user download the resulting file?
In the past I used Carrierwave to upload user avatars.
If you are used to Rails it's really straightforward.
Let it be a TextFile resource:
gem 'carrierwave'
$ rails g scaffold textfile content:string title:string etc etc
$ rails g uploader textfile
class TextFile < ActiveRecord::Base
attr_accesible :content
mount_uploader :content, TextFileUploader
end
And that is is pretty much all you have to do to obtain the app's skeleton. However, to answer your real question, no, I don't think there is already a rails app that does exactly that.
https://github.com/jnicklas/carrierwave
I found sinatra-fileupload, which pretty perfectly answers my question. It's a very minimalistic framework which works perfectly, I can just plug in the file handling, and change the layout etc a bit. There were many examples of sophisticated Rails plugins linked to databases, with versioning and stuff, but I really wanted the most minimal example.
I've written a command-line tool for manipulating with genome scaffolds called "Scaffolder". At the moment all the tools I want to use are hard-coded into the library. For instance these tools "validate" or "build" the scaffold. I'd like to split these tools out into their own gems, make it more modular, and to allow third parties to write their own commands.
The ideal case would be that I run "gem install scaffolder-validate" and this gem-bundled command would then be available as part of scaffolder. I know a couple of libraries make it easy to build a command-line interface: thor, commander, gli, .... However I don't think any of them cater for this type of functionality.
My question is how can I use a gem structure to create a module structure for installing these commands? Specifically how can the installed commands be auto-detected and loaded? With some prefix in the gem name scaffolder-* then searching rubygems? How could I test this with cucumber?
So, one thing you can do is to decide on a canonical name for your plugins, and then use that convention to load things dynamically.
It looks like your code is all under a module Scaffolder, so you can create plugins following the following rules:
Scaffolder gems must be named scaffold-tools-plugin-pluginname
All plugins expose one class, named Scaffolder::Plugin::Pluginname
That class must conform to some interface you document, and possibly provide a base class for
Given that, you can then accept a command-line argument of the plugins to load (assuming OptionParser):
plugin_names = []
opts.on('--plugins PLUGINS','List of plugins') do |plug|
plugin_names << plug
end
Then:
plugin_classes = []
plugin_names.each do |plugin_name|
require "scaffold-tools-plugin-#{plugin_name}"
plugin_classes << Kernel.const_get("Scaffold::Plugin::#{plugin_name}")
end
Now plugin_classes is an Array of the class objects for the plugins configured. Supposing they all conform to some common constructor and some common methods:
plugin_classes.each do |plugin_class|
plugin = plugin_class.new(args)
plugin.do_its_thing(other,args)
end
Obviously, when doing a lot of dynamic class loading like this, you need to be careful and trust the code that you are running. I'm assuming for such a small domain, it won't be a concern, but just be wary of requireing random code.
Hm, tricky one. One simple idea I have is that the main gem just tries to require all the others and catches the load error when they are not there and disables the respective features. I do this in one of my gems. If HighLine is present, the user gets prompted for a password, if it isn't there has to be a config file.
begin
require 'highline'
rescue LoadError
highline = false
end
If you have a lot of gems this could become ugly though...
It appears that the best PAM module for ruby is "rpam". However this module hard codes the service name "rpam" when calling pam_start which seems to be denied by default on at least RHEL. I can get rpam to work by hacking the source to change the hardcoded service name to something present in /etc/pam.d.
Do people normally reconfigure PAM to make use of rpam? Is there a better PAM module out there? (It needs to work with Ruby 1.9.) Is there something obvious I'm missing?
Having researched more, it looks to me like people normally add an rpam file to /etc/pam.d/.
You have to provide a PAM config file in /etc/pam.d. An easy way would be to copy the existing login config.
# root required
cp /etc/pam.d/login /etc/pam.d/rpam
You can also use rpam2 gem, which lets you specify the PAM service in the function call
# 'login' is the used pam service; if nil 'rpam' is used
Rpam2.auth('login', user, password)
Sorry for being 12 years late.