Well, not really. Not yet, anyway. But I did have some success with DSLs. Couple of tricks to it.
First – controller code can just be jammed in the rails controllers directory. This seems to get rid of at least some of the “you must bounce rails for your code changes to be visible” aspect.
So. My controller has
data_source.rb defines classes
QbeDataSource – the thing we are trying to make,
QbeDataSourceBuilder – the thing implementing the DSL, and the bootstrap method
qbe_data_source. At the end, it calls
Now – eventually I’ll work out how to make it scan the code directory and find those files, but at the moment I’m concerned that something like that might not work on the production environment.
qbe_taxon.ds looks like this:
So what happens? When load is executed, in invokes a function
qbe_data_source with two arguments – the symbol that will be used to talk about the data source (which the user should never see), and a block to be executed. The function looks like this:
def qbe_data_source(name, &block)
src = QbeDataSourceBuilder.new(name)
Create a new
QbeDataSourceBuilder object (with a constructor parameter) and execute the block in the context of that object.
QbeDataSourceBuilder names a new
QBEDataSource and remembers it:
@ds = QbeDataSource.new(name)
QbeDataSource remembers the fact that a data source got built in a class variable:
@@data_sources = Hash.new
@name = name.to_sym
@@data_sources[@name] = self
THis is available to the rest of the app as
Next, the block is executed in the context of the builder. When the block invokes
view 'APNI_PORTAL_TAXON', the view method of the builder is called. It uses reflection to set the instance variable of the
And so on.
So, how does this all get used?
Well, QbeDataSource has a test method. It’s pretty minimal at the moment:
raise 'no data source name' unless defined? @name and @name
raise 'no view name' unless defined? @view and @view
The goal is that we should be able to run a basic test of all the queries in the app, so that we don’t get the situation of a mess of old, broken web pages as a result of movement in the underlying data model. We therefore have a test action in the QbeController:
flash_warn 'QBE test page should not be visible in production'
@results = Hash.new
QbeDataSource.sources.each_pair do |k, v|
rescue Exception => e
@results[k] = e
@results[k] = nil
render 'qbe/test', layout: 'no_sidebar'
And that does the job. All the methods are called, all the results stuck in a results hash, and the html page displays it. Naturally, we will rig up the menu bar so that the link to the test page is not displayed in production.
And that, at this stage, is it. Ruby DSL on-track.