views:

1612

answers:

5

I am developing a Ruby on Rails website and I have an "architectural" question : my application needs some parameters and I'm wondering where to store them.

In concrete terms, my application receive some requests which are evaluated and then sent. So, the Request model must have attributes concerning these treatments : a validation status and a sending status. For instance, validation status can be "accepted", "rejected" or "waiting". Sending status can be "sent", "waiting", "error during sending" or stuff like that. I have to store those status codes parameters somewhere, but I don't know what is the best solution.

I could create a model for each one and store them in the database (and having an active record model ValidationStatus for instance) but : wouldn't it be a bite excessive to create a database/model for storing data like that?

I could also just use them in the code without "storing" them, I could store them in a YAML file...

So, a more simpler question: how do you deal with your application parameters in RoR?

+5  A: 

There are lots of global configuration plugins, most of them revolve around the idea of loading a YAML file at some point. Check this page, this plugin and even this Railscast.

pantulis
+1  A: 

I put them in the database. I have a lot of these, and they are all pretty straightforward lists of strings. The tables are all the same - id, name, description.

I generate models for them rather than having an actual model file for each one. In app/models I have a file called active_record_enums.rb, which in your case would look something like this:

ACTIVE_RECORD_ENUMS = %w{
  ValidationStatus
  SendingStatus
}

ACTIVE_RECORD_ENUMS.each do |classname|
  eval "class #{classname} < ActiveRecord::Base; end"
  classname.constantsize.class_eval do 
    # Add useful methods - id_for(name) and value_for(id) are handy
  end
end

This file has to be required in a config file somewhere; other than that it's pretty straightforward.

Sarah Mei
So, in your database, you have one table per parameter? It means that you have numerous tiny tables? Another solution could be to have just one ActiveRecord model 'Parameter' with fields id, type, name and description. What do you think about it?
Flackou
You could do it via STI, yep. You'd just need to change the generated class code to include it. In my case most of the tables are fairly large, so it was worth splitting them up.
Sarah Mei
A: 

I am not using Ruby but I will tell you that I started out (in ASP.NET) placing lots of settings in a Web.Config file (similar to a YAML). As time went on, though, the system evolved to the point where different instances needed different settings. So, almost all of them have migrated to the database. So...if you'll be deploying multiple instances of your site, I'd strongly recommend keeping settings in a table of your database (mine has just one record, with fields for various settings). If I had done this to start, I'd have saved a significant amount of time.

Mark Brittingham
A: 

I tend to just make a string column for each, and use validates_inclusion_of to set what's acceptable for them.

class Request < ActiveRecord::Base
  validates_inclusion_of :validation_status, :in => ['accepted','rejected','waiting']
  validates_inclusion_of :sending_status, :in => ['sent','waiting','...']
end

If you need to have things happen (ie. emails sent) when the status changes, look into using the Acts As State Machine plugin to manage it.

Luke
+1  A: 

(Have since viewed that rails cast mentioned above [episode 85] - it looks like a bit more 'the rails way' than below)

Another approach is to build on the existing configuration mechanism in Rails. Lets presume there are two types of configs:

  1. App wide configs common to dev/test/prod environments
  2. Configs specific to envrionments dev/test/prod

For the first scenario, items in "RAILS_ROOT + '/config/environment.rb'" work. Just see that the names are captialised so they are Ruby constants. A variation to this is have a reference to another file in that environment.rb file ...

require RAILS_ROOT + '/config/appConfigCommon.rb'

and place relevant config items in that file. This has the advantage of being able to be referenced independant of Rails.

For scenario 2, a similar approach can be taken. Place items for development in "RAILS_ROOT + '/config/environments/development.rb'" or something like

require RAILS_ROOT + '/config/environments/appConfigDev.rb'

and place environment specific items in that required file, making sure they start with caps. And follow the same pattern for test/prod (and others if need be).

The config items are directly accessible in views and controllers (not sure about models) by simply using the constant name.

Straff