Stateless Development

So I had a functional Model, Controller, and View. My application loaded some rows from the database, performed some string manipulation / parsing, and handed them off to the View, which using CSS, formatted them for the screen. These rows from the database represented the lottery picks from the office pool. Now, I wanted to be able to enter the lottery draw for that day and check it against the picks.

I did some research and found out about “form helpers” and was able to create a single text field form, and that in turn was able to pass the contents to the Controller. It seemed logical to me not to want to re-use the same view and objects created when the form is initially displayed, and this is where I ran into some conceptual stumbling blocks. You see, I thought that once I’d populated a Model instance with data, and I was operating within the context of the same Controller, that the data would still be available. But in reality all of the data that had been retrieved from the database vanished when I submitted the form and called a method from the same Controller. I couldn’t see where I was going wrong. Was it a scope issue? It was time to “phone a friend”.

My friend explained to me that this being a web application, it ran under different rules to the way I was used to. It was stateless. Whatever had happened in previous executions was not carried over to the subsequent ones. Now, I’d done some ASP and JSP, and even PHP programming and I knew that you could create variables that persisted, so why couldn’t do that here? He explained that it was possible, but it wasn’t a good practice, and it went against many of the design paradigms. So to fix my “vanishing data” problem, I’d have to re-query the database every time the page was displayed. This seemed like a terrible inefficiency, I’d need to make an SQL query all the time. Actually, it wouldn’t be as bad as I was making out, cached queries would be make it all quite efficient, but I still had a hard time reconciling the fact that I would be involving a database call when I already had those returned rows available. Oh well.

It was quite easy to re-jig things in the Controller to repeat the database query, and once I did that the application started working as intended. I could go to the page, which would display the lottery picks. I could enter the draw for that day and the display would alter color and format to show the matching numbers.

First Steps

The initial spec. for this project is to write a Rails application that stores the office lottery pool picks in a simple database, allowing for multiple users (a future capability), and allows the user to enter additional picks.  The user will then be able to enter the current draw and the results will be displayed.  Not the most complex application in the world, but covering some basic functionality.

First off, I created a MySQL database, and added a table for my picks.  This required me to edit the database.yml config file to change it from sqlite3 to mysql, which is how the rails command left it.  I subsequently found out that there’s a command line switch that allows you to generate a config with mysql, but…   I used a tinyint for one of the boolean columns.  Now some of you maybe thinking, why didn’t I use the generator for all of this?  The answer is I didn’t know about that stuff. I generated the application with the rails command.  I generated a controller, and a model.  I popped a simple action in the controller to test everything, being careful to match the case-sensitive model name (I hate case-sensitive languages!):

 def list_picks
   @list=Megapick.find_by_sql("select * from mega;")
 end

and created a view with <%= debug(@list) %> What could be simpler? It all failed, so I tried rake db: migrate, and restarted the server.  This now worked, so I started messing around with the query, perhaps I should use find(:all)?  So I tried, that didn’t work, which was worrying.  Dug around a bit and found something that said I should add a reference to the database table in the model set_table_name "mega".  That fixed it right up, but I was obviously doing something in the wrong way.

I poked around some more and found out about “scaffold”.  Scaffold was the method for building the framework connecting the models to the database.  You used to use it inline, but the recommended way was to use the generator.  I scrubbed the existing model and table ran the scaffold generator with a new model.  That failed.  I had used a model name that was plural.  That’s a big no no.  Fixed that, remembering to check the routes.rb file, and lo!  I had a simple Model, Controller, View.  All model searches were working, I could display the search results in the view.  I could control how they were formatted.  I had joined up all the dots.

Now I realize that I had gone about all of this in the wrong way, but there something about having a “hello world” application that covers some important aspects of web application programming.  I started planning in my head, the way I was actually going to structure this application.  Little did I realize that my “fat application” developer background was going to be thrown a loop.  Coming up next: developing in a stateless environment.

Scheduling Tasks with Network Solutions

Of course my brain is now twitching with the possibilities even with a service provider like Network Solutions. No shell access! How can I schedule jobs? Can I run Ruby as CGI? (no). What if I need to run some regular maintenance? (I know, getting a little ahead of myself, but these are the kind of things that pop into my head, while I’m putting the initial design of something together).

Rails on Network Solutions is a well-guarded affair, you get to deploy, but you’re not getting access to a command line, so make sure it’s all fine and dandy before you deploy, which is fine most of the time, but you’ll definitely trip up somewhere, sometime and then it’s a right, royal pain. Setting up your Rails application is all done through their browser-based interface, after that you either upload a ZIP or handle it through FTP.

So, how about my scheduled tasks? Well, a little poking around reveals a nice little command called “runner“. Runner lives in the script directory of each application, and allows you to run Ruby files from the command line. Now, Network Solutions provides me with the capability of scheduling scripts/commands to run (again through the browser-based interface, no cron here!). So, a little test Ruby script and the creation of a scheduled task later, and “ta-da!”, I have a way of running Ruby scripts on a schedule. This is my little command
/htdocs/rails/test_app1/script/runner /htdocs/rails/test_app1/hello.rb

Where “test_app1 is the rails application name.

As I said, I’m not sure why I’m going to need this, but I bet I will.

Interlude – Think Different!

A few years ago Apple ran a campaign picturing some famous and renowned “free thinkers” under the concept “Think Different!”. The idea being that people who used Apple products were creative and able to put their stamp on the technology being used.

My wife asked to put one of my sounds on her iPhone for use as a ringtone. Simple, right?

Turns out that getting your own content onto an iPhone is much harder than it should be. Even once you’ve achieved that, assigning your file to be a ringtone exceeded my patience. I understand that Apple makes systems that are “simple” to use, removing a lot of the sometimes unnecessary clutter, but time and time again, I find that they leave out key features, or actively prevent you from being able to perform the simplest of actions. The default Mail program in OSX has no ability to download “headers only”, which seems to me, to be a fundamental option.

It’s not so much “Think Different”, as “Think the same as us”, which seems to be reflected in the new platforms such as the iPhone and iPad. These devices are “consumer” interfaces, portals into functionality, which you, the user have little or no control.

The Application

The company I used to work for, like so many, had a lottery pool for playing the MegaMillions lottery. A few years ago, I wrote a simple VB program that read a CSV file, which stored everyone’s “lucky numbers” (little evidence exists that these are, in fact at all lucky) and after you entered the latest draw, displayed a visual representation of the results (see right).

Now, I’ve never had much luck with the widget-style programming exercises. Things like the awful Northwind database examples in Microsoft Access, and countless recipe XML samples have always left me cold. So I decided that I needed to pick something that had some “use” even if it was something as mundane as matching numbers in a lottery. I figured that this would give me a reasonable target, it would cover some basic Rails concepts, and would remain interesting enough to go that extra mile in order to get it to work the way I wanted.

First up, I needed to poke around in the Interactive Ruby shell to get a handle on the text manipulation functions. Stuff like “split” and CSV handling, brush up on my RegExp, and other such things. It also gave me a chance to experiment with some of the lessons I learned through online tutorials. Once I’d played around a bit, I felt that I should shift to the Rails model and start designing.

Intermission – Install Debian on an old IBM Thinkpad 240

Why did I decide to do this? Completely sucked two days of my life. Who knew that the lack of a CDROM, or more precisely, a reliably working CDROM, would have made this so difficult. I doesn’t seem unreasonable to be able to perform an install from any medium. Having found DOS drivers for USB devices, including a thumb drive, It really thought this was going to be a snap. In the end the USB CDROM drive performed long enough for the installation to work. So now I have a little 10″ IBM Thinkpad 240 running Linux. It’s just a shame that the battery life on this little thing is about 10 minutes!

Setting up the development environment

OK. So against all advice I’m going to be working on a Windows XP setup. There are several good reasons for this, that I won’t bore you with, and many bad reasons, which although outnumber the good ones, would cause me massive organizational problems.

For this I’ve downloaded InstantRails. I’ve done a lot of enterprise software installations in my time, and quite frankly, had my fill of tweaking massive and annoying Apache configurations. When I first came across WAMP, some years ago, I thought it was the best thing since sliced bread. It couldn’t have been easier. I expected a similar experience with InstantRails. Sadly, this really wasn’t the case.

Firstly, it’s old, so get ready for some upgrading once it’s installed. Secondly, there are a couple of things that just didn’t fly. Possibly, because I’d already installed Ruby on this box and the environment variables were tripping over each other (this was definitely one of the culprits).

The MySQL part of the image was surprisingly messed up.

  • The libmysql.dll file was missing in the ruby/bin directory. I needed to copy that from the mysql/bin directory.
  • I was getting “Error #2003 The server is not responding“, which turned out to be a Windows specific problem associated with ODBC. The fix is to:
  1. Log in to mySQL as root. Open a Command Window, cd to the app directory (probably ‘depot’ in your case), and enter: mysql -u root -p Then just hit enter when prompted for the root password, or enter one if you’ve set one up for the root user.
  2. Enter the following line to grant access to the “ODBC” user grant all on depot_development.* to ‘ODBC’@’localhost‘;
  3. Exit

There were several other headaches, which amidst the shouting, cursing and thumping of desk and floor, I failed to document.

The only other thing I need to do each time I start InstantRails is manually run mysqld.exe from the mysql/bin directory. Possibly because it’s conflicting with an ancient MySQL installation on this box, who knows.

After all of this, which ended up taking a couple of days, I ended up with a functioning setup. Now to decide on my first app.

Ruby and Ruby on Rails

At the suggestion of an old programming friend of mine, I’ve decided to teach myself Ruby and Ruby on Rails.

Ruby seemed like a good idea. Scripting languages have always been an important aspect of how I use computers, and the opportunity to select a single language that will work across multiple operating systems is very seductive.

I’m starting completely from scratch on this one, so I fully expect to encounter some interesting and challenging problems, which I intend to document in this blog.

I started this process a couple of months ago, so the first few entries in this will be an attempt to transcribe my development/learning diaries into this blog format.