A Weekend on Rails - Day Two
Last time, I built a standard scaffolded Rails application with a modified database, controller (admin) controlling a model named programme. The next step is to add a view and import mechanism. The standard scaffold mechanism uses a list.rhtml as the entry point, so we will create one of these to override the scaffold, and display a list of the current programmes, along with the import button.
<h1>Listing programmes</h1>
<table>
<tr>
<% for column in Programme.content_columns %>
<th><%= column.human_name %></th>
<% end %>
</tr>
<% for programme in @programmes %>
<tr>
<% for column in Programme.content_columns %>
<td><%=h programme.send(column.name) %></td>
<% end %>
</tr>
<% end %>
</table>
<%= link_to ‘Previous page’, { :page => @programme_pages.current.previous } if @programme_pages.current.previous %>
<%= link_to ‘Next page’, { :page => @programme_pages.current.next } if @programme_pages.current.next %><br />
<%= link_to ‘Import XML’, :action => ‘load_xml’ %>
and add a new “load_xml.rhtml” template
<h1>Load XML<h1>
<%= form_tag({ :action=> ‘import_xml’}, {multipart => true }) %>
<%= file_field :document, :file %>
<%= submit_tag ‘Import’ %>
<%= end_form_tag ‘Import’ %>
<%= link_to ‘Back’, :action => ‘list’ %>
Ok.So much for the easy part. We need to add an entry to the controllerfor the ‘import_xml’ action that has just been declared. This will haveaccess to the embedded file uploaded using the file_field :document,:file instruction.
The decision to make the database table columns have exactly the same namesas the XML attributes allows for the following code to populate thedatabase. So the final app/controller/admin_controller.rb looks like:
class AdminController << ApplicationControllerscaffold :programme
def import_xml
require ‘rexml/document’
file=params[:document][:file]
doc=REXML::Document.new(file.read)
doc.root.each_element(’//programme’) do |p|
if not Programme.find(:first, :conditions => [ “name=?”, p.attibutes[:name] ]) then
@programme=Programme.new
@programme.update_attributes(p.attributes)
end
end
redirect_to :action => ‘list’
end
end
Ok. That’s it for now. I’ve scratched the rails surface and learnt something new. More discoveries soon.
A Weekend on Rails - Day One
Since I’ve been laid up and not supposedto be working, Ruby on Rails seemed like an interesting, low-impact thing to do. I’m a complete n00b when it comes to Ruby, so it was pretty much a jump in at the deep-end for me. I’d like to think that I was swimming with Ruby rather than sinking within a matter of hours,and I’d recoded a file autostore/autorename utility in a couple of days.
I picked up the basics of array handling, regular expression manipulation, and some of the syntax of Ruby learnt, I still hadn’t quite made the leap of faith into the “Convention rather than Configuration” paradigm, so I figured it was time to get more deeply immersed in the full Ruby/Rails methodologies by building a Rails based utility.
I like to do something useful when trying out something new. Not production ready coding, but enought to move a personal project ahead and I was writing a TV programme recording prioritisation module for my next stage refinement of the PVR project.
Requirements for this were to have an input which contains the Programme name, a single aka (if appropriate), imdb and tv.com id number, and a recording priority. At this top level, I didn’t care about episodes, season information or anything else. Next extension was going to be for Genres, but I didn’t want to worry about that yet.
I already have XML files which contain the information, and I’d decided to use SQLite V3 as the database, so the Rails task I set myself was to convert the XML to the database.
As I have complete control over the XML file, I didn’t require any validation. If there was a problem, I could trash the database, correct the source file and run again.
The form of the xml file was:
<programmes>
<programme priority=”3″ name=”Time Gentlemen Please”>
<programme priority=”4″ name=”Time Trumpet”>
<programme priority=”1″ name=”Torchwood”>
<programme priority=”1″ name=”Torchwood Declassified”>
</programmes>
with possible additional attributes of aka, imdb_com, tv_com which contain other programme names, and the imdb.com and tv.com ids for the programme.
I’d read a number of Rails articles about moving image files into the database, and decided that I would do this as an import file from a webform.
Since this is my first Rails program, I’ve decided to post it here so I can point and snigger at it later. Feel free to do the same. Assumption is that all of the build prerequisites have already been installed, and I can skip straight to code generation and development work.
First step is to create the rails application framework for this, which goes by the name of BorgTest. Since I’m using SQLite3, I have a slightly modified commandline for the creation.
Checking inside the config/database.yml shows that the correct database is being used
# SQLite version 3.x
# gem install sqlite3-ruby
development:
adapter: sqlite3
database: db/development.sqlite3
# Warning: The database defined as ‘test’ will be erased and
# re-generated from your development database when you run ‘rake’.
# Do not set this db to the same as development or production.
test:
adapter: sqlite3
database: db/test.sqlite3
production:
adapter: sqlite3
database: db/production.sqlite3
Next thing to do is generate a model and controller for the database and associated views.
script/generate model programme admin
Since I already know the exact format of the XML file, I’m going to create a database table with exactly the same columns as the names of the XML attributes.
db/migrate/001_create_programmes.rb
class CreateProgrammes < ActiveRecord::Migration
def self.up
create_table :programmes do |t|
t.column :name, :string
t.column :aka, :string, :default => “”
t.column :priority, :integer, :default => 0
t.column :tv_com, :string, :default => “”
t.column :imdb_com, :string, :default => “”
end
end
def self.down
drop_table :programmes
end
end
Save the above file and run
to create the initial table. Add the scaffold :programme to the app/controllers/admin_controller.rb file
class AdminController << ApplicationController
scaffold :programme
end
Fire up script/server and point the webrowser to http://localhost:3000/admin and check that it is working.
Ok. Initial build completed and I had the basic scaffolded CRUD application. Next post will cover the addition of the controller and model to actually upload the file and perform the import.