According to the Pragmatic Programmers, code should be for abstractions, while configuration and details should live in metadata. Rails seems to diverge dramatically from this pattern. Much config is done in code files such as application.rb
, routes.rb
and the various environment.rb
files, while other types of config is done in yaml files (e.g. database.yml
). What is the thinking behind this design decision?
|
|||
|
We get a different picture when we read the whole page you linked to, and not just the headline.
We don't have a compiled code base, my Ruby is interpreted. There is no recompilation step, changing the configuration is as easy as changing the source file and restarting the program.
The RoR framework is already sufficiently decoupled.
Parts of the implementation may also be details that should be deferred out of the main program. In dynamic languages, there simply isn't this great dichotomy between code and data – code is just another kind of data. This has been shown with great success by the Lisp languages, and Ruby stands firmly in this Lispish tradition via its Smalltalk heritage.
Again, no recompiling is necessary with Ruby (or other dynamic languages like Python or Perl). In fact, we can monkey-patch new code into the system while it's still running.
Ruby's syntax is flexible enough that it's easy to whip up half a DSL with it. In fact, the Ruby implementation gives us a parser and compiler for free, all we have to do is to implement the semantics.
Exactly. The RoR framework takes application-specific code from your configuration files. It's easy to swap out these files for another website. |
|||
|
In Rails those boundaries always have been a bit blurred. There are several reasons for this, the first one maybe the simple fact that the Ruby language allows it to write code that looks like configurations. For example you can use methods without putting the arguments in braces, which leads to the common usage of things like this:
in the model definitions. Looks like a configuration, actually is a method call with the param :orders. Starting from this point it is often easier to chain method calls for complex configuration options. This especially in files like Actually in many places those In case of the very basic files like So there is a mix of reasons active here, some simply based on the 'Ruby culture', others for practical purposes. (Not every single one necessarily the best decision, but most of the time they make sense once you see the advanced possibilities you get from them). |
|||
|
Executable configs are a tradeoff between expressibility and safety/predictability. Using a turing-complete programming language for configuration gives you many useful features "for free": Variables make let you avoid writing a same value over and over, loops avoid repeating yourself, if statements do conditionals, etc. The disadvantage of using an executable config or a config-generator is that you can't know what the config will do without executing it. Will it execute quickly or will it get stuck in an infinite loop? What properties will it set in the end? There are also security issues it you have user-created configs - how do you sandbox the executino environment? Can they DDOS you by consuming too many resoutrces and so on... |
|||
|