How web programmers should be more like lawyers

Posted by Jonathan | Posted in Personal | Posted on 04-01-2012

0

I got to thinking the other day how I was similar to a lawyer, but really should leverage more lawyer-ish practices.  How did this pop into my mind?  Quickbooks.  The software I love to hate.  At this point in my life, I use it for invoicing, managing client information and tax reports.  Its way more software than I need, and I got to thinking what other service industry might have software that does what I do.  I’m not aware of something (cost effective) that will do the basics that I want, granted I haven’t really done much research because I own Quickbooks (so feel free to tweet @thecodedog what you use for invoicing and book keeping).

When you set up Quickbooks, you choose a similar industry – and it goes off and sets up accounts and some of the ledgers, etc (stuff I don’t care about). Anyway I got to thinking how the functions of what I do are similar to a lawyer.  THEN I had an amazing idea that I think I’ll implement for 2012 – and we’ll see how it goes (I’ll get into that after these lists) -

Here’s how I’m similar -

  • I AM AN EXPERT AT WHAT I DO
  • I charge hourly for my expertise and work (unless its a bug fix)
  • I take on projects, small and large
  • I meet with potential clients to determine if I can help
  • I advise people with my expertise (whether they follow it or not isn’t my issue)
  • I manage multiple projects at once
  • I research and learn all the time
  • I create structured documents
  • Occasionally I build and implement templates
  • I reuse items from other projects
  • I rarely produce a physical product
  • success is determined by the client, peers and typically the public
  • everything I do is to help the client
  • I have a pretty damn good success rate

How I’m NOT like a lawyer

  • I’m honest and not seedy (I know not all lawyers are bad)
  • I’m 100% up front with pricing and charges and my clients ALWAYS know what to expect when an invoice comes
  • I don’t charge for phone calls
  • I don’t charge for quick tasks that take more effort to create the invoice than the actual work performed
  • I probably do not charge enough (thus don’t overcharge) for the work I do
  • I don’t have an assistant to do my dirty work (book keeping / phone calls, research, etc)

There is one thing that a lawyer does that is good that I don’t currently do, and it hit me and I’m curious if it will fly.  Keep me on retainer.  I looked it up and here’s a quick definition for a retainer -

A retainer is a fee paid to an attorney or other professional in advance, for services. Often, retainers are paid monthly, based on an estimate of the amount of work to be done for the client each month.

A retainer might work like this: You would pay your attorney $500 a month for legal services during that month. If you have a question or need a matter handled, it comes off the retainer amount. If you don’t use the full amount of the retainer, in most cases you would not get a refund or a credit toward the next month. If you use more time than the retainer amount will cover, you will need to pay the additional fees.

With that in mind, I’m wondering if any other programmer does this, and if clients would go for it.  In the past I’ve offered support contracts for an app I’ve built for a client.  If they wanted small changes, tweaks (all defined beforehand) they didn’t have to worry about it.  If a user had questions, needed training (again outlined specific hours) that was included.

The upside to a retainer agreement this is that you have reliable/consistent income each month, the client has the assurance you’re not going to walk away from the job.  They have the security in knowing that you’re there to call if anything comes up. They have a reliable budgeted amount to allocate for the project. And most importantly – if you have a retainer agreement with them, they would get preferential treatment and pop to the top of the workload (or as near as possible depending on what you have going on)

The downsides (two that I can think of) is that if you do this with too many clients, you might be overwhelmed with ‘high priority’ work (which would probably happen regardless of a retainer agreement and the same number of clients).  The other (seems petty) is that you probably have to invoice them every month instead of hoping they remember to pay you (which you may not have to do if you didn’t do any work for them that month).

Deciding I’m going to offer this…what’s a fair rate then?

Figuring here in Pennsylvania the typical rate for what I do is $70-$100/hr – are clients seriously going to pay me 4-5 hours ($280 – $500) a month so I’m at their beck and call?  I personally don’t have any clients that large – I think they’d say – no, that’s ok, you can just invoice us for work performed. Maybe if they do put me on retainer – I lower my rates? Even 50% seems a bit steep for some of them and then you’re just screwing yourself because now you’re performing 5 hours of work for half the price you would be if you weren’t on retainer for them.

Its an interesting issue I’ve been pondering.  I like the idea of offing this to clients, I guess if they take it, its a win either way.  Especially if I get a month in there where they don’t use the 5 hours.

If you do this or have done this – feel free to comment below or shoot a tweet to @thecodedog

and if you want me on retainer for you definitely contact me and we’ll talk – jonathan.wheat @ codedog.net :)

 

 

Code it right
theCodeDog
theCodeDog

Forcing SSL with PHP

Posted by Jonathan | Posted in PHP | Posted on 29-11-2011

0

Occasionally you have a registration form, login page or other php item that should be secured.  Its easy to link to something securely, however, some people play with urls ( I know, gasp ), search engines might get to the page with http, or users might somehow otherwise end up there unsecured.  Yes you can accomplish this with an .htaccess file, but sometimes you don’t have the ability to edit / create one on a server.

Add this php code to the top of your php page to have it verify and flip to secure mode if needed -

<?php
if ($_SERVER['SERVER_PORT']!=443)
{
$url = "https://". $_SERVER['SERVER_NAME'] . ":443".$_SERVER['REQUEST_URI'];
header("Location: $url");
}
?>

Conversely if yiou have to pop back to http, you can alter the code to this -

<?php
if ($_SERVER['SERVER_PORT']!=80)
{
$url = "http://". $_SERVER['SERVER_NAME'] . ":80".$_SERVER['REQUEST_URI'];
header("Location: $url");
}
?>

That’s all, just wanted to share something I found when I need this behavior on an application form.

BTW if you want to do this via .htaccess – you can use something like this -

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://domain.com/$1 [R,L]
Code it right
theCodeDog
theCodeDog

Debug Certificate expired – ugh

Posted by Jonathan | Posted in Uncategorized | Posted on 01-11-2011

0

I decided to complete an app I’ve been working on and post it to the Droid Market.  After makiing a few changes, I fire off the commands to compile it – rake run:android

after copiuos amounts of logging to the screen, I’m greeted with -

THIS TOOL IS DEPRECATED. See –help for more information.

Debug Certificate expired on 27.10.11 08:10
Error building APK file

Seriously?  Wonderful.

If or should I say WHEN you get this because apparently the debug certificates are valid for 365 days – here’s the solution -

Find and delete the file “debug.keystore”.  This is stored in your home directory under “~/.android” (OSX, Linux).  Similarly on Windows file resides in the “C:\Users\[user]\.android folder.

Just delete it, rm it, shred it, drag it to the trash, whatever.  Get it out of there.  A new one will regen much like I do in Black Ops when I get nailed by a zombie.  Its probably a good idea to do a rake clean:android as well, just to clean up from the failed compile, although this probably isn’t 100% necessary.

Now you’re good to go.

-Jon

 

 

 

 

Code it right
theCodeDog
theCodeDog

XCode and Rhodes Upgrading for iOS5

Posted by Jonathan | Posted in Mobile Connection, rhomobile, XCode | Posted on 24-10-2011

0

So I recently updated my iPhone to iOS5.  Its a 3GS … so it was less than exciting to see the end result.  Yea, there are some GUI enhancements, but nothing really worth the trouble its causing now.  What trouble?  When you build an app using XCode, and you want to deploy it to your iPhone for testing purposes, the OS on your phone MUST match the SDK on your system.

So I’m plugging along building and testing 2 apps in the simulator, they’re working great.  I decided I’m to the point where I’d like to test them on my phone, so I fire up XCode (4.1 to something) and got a nice little message that said something like the Operating system on your device does not match the SDK version on this machine.  Click here to revert the device … WHAT?  Heck no.  So that mean I now have to go through the pain of updaing XCode.

This has happened multiple times to me as I’ve progressed up through OS versions on my phone, so this time I figured I’d document it – so next time its not so much guess work, and it might help someone else too.

  • Download XCode : Log into your developer account at http://developer.apple.com click downloads, and download the latest SDK version (4.2 includes iOS5 SDK)
  • Install XCode.  This can take a while, so grab a book or make a sandwich.  DON’T listen to music on iTunes, because that’ll have to be closed during this upgrade.

If you’re developing with Rhodes (http://rhomobile.com) you might possibly have to upgrade this as well.  Since you have your sandwich and a drink, you might as well.

Rhodes Upgrade (optional)

From a terminal prompt

  • sudo gem update rhodes
  • rhodes-setup
  • set-rhodes-sdk (from your application’s root folder)
  • rake clean:iphone

If you get an error like this -

=== CLEAN NATIVE TARGET rhorubylib OF PROJECT rhorubylib WITH CONFIGURATION Distribution ===
Check dependencies
Unsupported compiler 'GCC 4.2' selected for architecture 'i386'

Welcome to the club.

It seems that XCode 4.2 removes the older 4.x simulators.  I found this out when I opened XCode trying to debug the message above, and there was only iPhone Simulator 5.0 listed.  So to fix the error above, you much edit your build.yml file and set these lines -

iphone:
  sdk: iphonesimulator5.0
  iphoneemulator: 5.0
Then you can run your rake commands and it’ll all work including rake run:iphone
XCode usage
To compile it in XCode run this from your project root

rake switch_app

Then from XCode you can choose your simulator and compile away for your simulator.

 

Code it right
theCodeDog
theCodeDog

redirect with parameters

Posted by Jonathan | Posted in rhomobile | Posted on 07-10-2011

0

I posted a while back about passing parameters between views from within a link.

Today I’ll post this code to remind myself how to do that from within a redirect.

Sometimes in your view or controller, you might call a method to do something – say store something in the database and pop up a message, and you might need to redirect to a new view/method after that.  Well sometimes you need to get some parameter(s) to that new page as well.  If you search the system-api-samples project Rhomobile has – you won’t find this in there. Ok, you might, I didn’t.

I had a ‘duh’ moment when I got this to work, because its pretty dang near identical to passing parameters in a link.

Here it is in all its glory :

Where list_details is the destination method and we’re passing session_id with the variable @session_id

redirect :action => :list_details, :query => {:session_id => @session_id}

If you had more parameters, you’d separate them with a comma like this -

:query => {:session_id => @session_id, :session_title => @my_title, :message => 'it worked'}

Easy, right?
Code it right
theCodeDog
theCodeDog

PABUG Status & Screenies

Posted by Jonathan | Posted in rhomobile | Posted on 03-10-2011

0

So – I’ve neglected to write posts as I’ve worked on this, mostly because I’ve been trying things, and need to complete this as soon as possible.  I’ve gotten a few emails asking about the progress, so instead of dragging out the time until the next post about it, I’ve decided to attach some screenshots of what I have so far.

Still have some formatting / tweaks to do, but the bulk of this is now working.

Enjoy.

Main Floorplan

Exhibitor Info

Home Screen

 

Twitta Feed

Session Breakout

Session Details

 

Code it right
theCodeDog
theCodeDog

Formatting Dates

Posted by Jonathan | Posted in rhomobile | Posted on 28-09-2011

0

Dates suck.  Simple fact, no matter what language you’re using, formatting, date-math, converting or parsing dates … it all sucks.

So in an effort to try to limit the suck you have to go through if/when you have to deal with dates, I hope this helps.

My app, when first loaded, pulls a feed from our oracle database.  The date is listed in the ‘typical’ format – 22-NOV-11, stores this in the device’s database (FixedSchema) (  property :session_date, :date ) – so you would think that would be the type date.  In my controller I do this little query -

@days = Session.find_by_sql("SELECT distinct(session_date) _
   FROM Session ORDER BY session_date")

In my view I loop through with something like this -

<% @days.each do |session| %>
typical, nothing special

so we essentially have session.session_date inside this loop – and I don’t want to display it in the default format (22-NOV-11).  So I endevored on a painful journy – pulling in 3 other developers on the rhomobile list. 10 emails later, I got it working.  I used this code -

@display_date = Date.strptime(session_date,"%d-%b-%y").strftime("%A, %B %d")

This gets me really close to the format I wanted, – Monday, November 23

But I wanted what I’ve found is called the ordinal suffix on the end ( the ‘rd’,'st’,'nd’,'th’).  In rails there is an .ordinalize method – but that’s not available in ruby (maybe you could include a library or gem or something, but by this point, I’ve suffered 3 days to deal with this), so I created my own.

This is the final code I ended up with -
in my index.erb :
session_date = session.session_date
@display_date = format_date(session_date)

in my session_controller.erb:
def format_date (date_in)
prefix = Date.strptime(date_in,”%d-%b-%y”).strftime(“%A, %B %d”)
day = Date.strptime(date_in,”%d-%b-%y”).strftime(“%d”).to_i
if day == 11 or day == 12
return prefix + “th”
else
case day % 10
when 1 then return prefix + “st”
when 2 then return prefix + “nd”
when 3 then return prefix  +”rd”
else return prefix + “th”
end
end
end
might be a little klunky coding, I’m sure I could just set the suffix and append / return them at the end, but this works, and I need to move on to another part of my app.

 

Code it right
theCodeDog
theCodeDog

Appcelerator – a second chance

Posted by Jonathan | Posted in Appcelerator | Posted on 06-09-2011

0

I subscribe to the TechZing podcast and the two hosts, Justin Vincent and Jason Roberts have used Appcelerator for a couple projects of theirs and talk about it in many of the older episodes.  I had tried Appcelerator on my old windows box and it was a disaster. Could have been them, could have been me – didn’t care.  Then I moved to Mac – and tried it.  I still had problems, think I even tweeted about that back in February.

Since I respect the guys from TechZing and with the on going praise, I figured I’d try it again.  I googled how to remove it completely from my mac, just to make sure the old broken / mis-configured stuff was gone, downloaded and installed it.

To my amazement, it installed easily, and I was able to quickly open Titanium Studio (essentially eclipse customized for Titanium) and run a new empty app.  Granted it wasn’t an exciting app, but it did open in the simulator.  After about 40 minutes of dinking around, I was able to get everything in order (thanks Apple) and deployed it to my iPhone.  Again, no awesomeness in that app, but still – a huge leap.  Titanium has an app called Kitchen Sink – where they add all of their features, and show off the framework.  I downloaded that, imported it, and was able to deploy that on my phone as well.  This rocked.  10 minutes later, I had it running in the Android simulator. It only took 10 minutes because I had to get the Android SDK stuff in order.

Within an hour of downloading, I had both created and imported apps, built them, tested them on the simulator and deployed them to my iPhone.  Amazing.

Appcelerator uses Javascript as a programming language, yea, not just a scripty thing you use on a webpage, as the language. Pretty cool.  The code gets compiled using the device SDKs so so the deployed app runs natively on the phone.  This gives you access to the device’s features like calendar, GPS, accelerometer, camera, video, photo libraries, file system etc.

I have yet to really start playing around with it, but I’m planning on building an app for a friend, so keep watching this blog for that.

All in all – when I can go from download to deployment on my device in about an hour, that rocks. Titanium Appcelerator gets an A+ from me. Thanks Justin and Jason for influencing me to try it again.

 

 

Code it right
theCodeDog
theCodeDog

ezSQL – database wrapper/abstraction layer

Posted by Jonathan | Posted in PHP | Posted on 15-08-2011

0

I was looking for a database wrapper / abstraction layer to use for PHP a couple weeks ago.  I’m working on a large PHP project and its using Oracle.  I started out with the app using oci calls throughout.  Launched the beta – and its working pretty well.    Now I’m going through cleaning up sections of code gearing up for a 1.1 release and thought I’d look for something to make the database coding easier.  Not that its difficult, but each database call is bloated with multiple lines of code for each call, I wanted something easier.  Enter ezSQL.

ezSQL was created by Justin Vincent – and its nothing short of amazing. ezSQL can sit on a multitude of databases including – mySQL / Oracle8/9 / InterBase/FireBird / PostgreSQL / MS-SQL / SQLite / SQLite c++ … I mean WOW.  One thought I had was to possibly have a development version of the database as MySQL – and the production version as Oracle.  The data structure won’t change, I’m pretty much building screens off of that, so table changes would be minimal. But seriously, in practice who does that ?  Hmmm, maybe me.  We’ll see after I get out from under the mound of work I have.  My problem is – while I have VPN access to the Oracle database, if I don’t have a net connection – I can’t work on the app – since I have no database, not good.  So this may help me be more productive, if I’m sitting at the pool waiting for my kids to finish swim practice, I can code, or if I’m out in the park or at my mother-in-law’s place (yea – she’s got no wireless).  Anyway, the more I think about this – I could easily create a config option as to which database to use.

Back to ezSQL…

Once configured (which took a whole 2 minutes, and that was because I moved the files from the demo into my app) you can make calls like this -

$users = $db->get_results("SELECT name, email FROM users");

Typically, results are stored in an object, but you can alter the call to return associative arrays, or numerical arrays.

So using the example above, you’d pull out the name and email like this -

foreach ( $users as $user )
  {
      // Access data using object syntax
      echo $user->name;
      echo $user->email;
  }

If you have just one row you use get_row, if you’re simply getting 1 item like a count, you use get_var.  A simple to read instruction page explains it all.  There are many examples on that page to help get you started.

Probably the best feature is $db->debug();  this little gem (can’t thank Justin enough for this one) spits out a pile of information about the query, as well as the data that’s coming back.  So if you’re having a problem with the database call – toss in this command and it’ll help you out.

Another gem is the $db->vardump($users); which displays the contents and structure of the variable / object.  Again great for determining what is happening with a query.

I know I sound like a paid advertisement for this, but the support was amazing too.  I had a problem with the version I had downloaded, and emailed Justin.  The next day – he fixed it right away and posted a new version, which is currently posted on his site (2.10)

Overall, this is a big win for me.

Code it right
theCodeDog
theCodeDog

PABUG (Pt3) – Mobile Connection 1.1

Posted by Jonathan | Posted in Mobile Connection, PABUG, rhomobile | Posted on 22-07-2011

0

<QUICKNOTE>
A coworker here has created a set of web forms, reports and database tables to collect all the conference information including presenters, sessions, tracks, attendance, exhibitors, vendors, etc.  I won’t go into any of that, other than to mention I now have at my disposal all the data I need to make an app, Yea !  Oh yea, and there’s some screenies way down below if you want to check out what I’ve done.  I’ve also made it further than this post as you can see in the screenie below, I’ll continue to work through posts to explain what I’m doing though so you can see the app mature over the next couple months.
</QUICKNOTE>

The Home Screen for the PABUG app

Sungard Higher Education released Mobile Connection 1.1 last week, which caused some great excitement in the developer world.  … ok, in my world it did.  I had obtained a pre-release version and started building out the PABUG app using that.  It was going well, but when the release version came out I decided to essentially start over due to some improved performance and bug fixes.  Enough had changed that it was worth doing.

So where do we start coding.  Firstly – we want to be able to list the conference sessions, tap on a session and view the session details.  Ideally, since this is a multi-day conference, I’d like to alternately be able to select a day and list only that days’ sessions.  To get even more granular – maybe list the tracks as well and list that tracks sessions.

So where to start.  Using Mobile Connection we need to create what is called an mApp … or MApp … or Mapp … not sure the proper spelling, but its pronounced – em-app <G>  Anyway an m-app (I’ll keep using creative ways to type it to keep your interest) – is essentially some functionality you pack up in a single directory in your apps code tree.  In our case, we create a directory called Session.  Rhodes (the underlying framework we’re using) uses the MVC architecture so we need a model (database – more on that soon), View – what the user sees, and the Controller – where all the magic happens.

When you’re at a conference, they typically have wireless throughout.  That said – this particular conference venue has partial wireless and the part that works is crap.  So we can assume you’ll be in sessions that have no connectivity.  Its an older building – so its also quite possible that you will not get a cell signal either (aka No Data).  You’re unplugged.  Not good for a mobile app.  So we need to plan accordingly.

Luckily – we can use the device to create a database for us, store the information we’ll need for later, we’ll call that caching – because its a much cooler term than storing.  So our app now needs a database, a model if you will.  We’ll need to grab the session list and all its data, presenters, tracks, level, etc and store it on the phone then render it to the user depending on what they tap on.

We create a session_controller.rb file and in the index method, check the Session model for data.  If the data count is <1 then we know its the first time the app has run, and we need to load ‘er up.

  def index     
    @sessions = Session.find(:all)
    if @sessions and @sessions.size<1
      sessions_result = fetch('Session Data',@@session_file_name, 'http://apps3.messiah.edu/mobile/pabug/session_load.php')
      insert_sessions  
    end
    @days = Session.find_by_sql("SELECT distinct(session_date) FROM Session ORDER BY session_date")
    render
  end

So we’ll go get the session list.  Hmmm, we’ll need to build a way to generate the session list.  Using PHP on a server here at Messiah, I quickly put together an SQL call to pull the session data I need from the database tables I mentioned above.  I concatenate that data in a format that my app will process when it creates the database on the device.  Below is an example of what that looks like -

"session_id"=>"321","session_title"=>"Testing a really long session title name.","session_date"=>"21-NOV-11","session_time"=>"10:10 AM - 11:10 AM","session_level"=>"Advanced","session_notes"=>"Session Notes","session_desc"=>"Session Description","session_room"=>"Regency","session_track"=>"--","primary_presenter"=>"Dorie Minich","other_presenters"=>""
"session_id"=>"113","session_title"=>"Mobile BOF","session_date"=>"24-NOV-11","session_time"=>"11:20 AM - 12:20 PM","session_level"=>"Beginner","session_notes"=>"","session_desc"=>"","session_room"=>"TBD","session_track"=>"Mobile |  Technical","primary_presenter"=>"Jonathan Wheat","other_presenters"=>""
"session_id"=>"114","session_title"=>"Imaging BOF","session_date"=>"24-NOV-11","session_time"=>"11:20 AM - 12:20 PM","session_level"=>"Beginner","session_notes"=>"","session_desc"=>"","session_room"=>"TBD","session_track"=>"Technical","primary_presenter"=>"Dorie Minich","other_presenters"=>""
"session_id"=>"141","session_title"=>"Mobile Connect : A Starting Point","session_date"=>"25-NOV-11","session_time"=>"1:30 PM - 2:30 PM","session_level"=>"Beginner","session_notes"=>"This is an intro to Mobile Connection and the framework.  Will allow users to get a feel for what you actually need to get started.","session_desc"=>"The Beginner&apos;s Guide to Mobile Connection and what you need to dig in","session_room"=>"TBD","session_track"=>"Mobile |  Technical","primary_presenter"=>"Jonathan Wheat","other_presenters"=>""
"session_id"=>"82","session_title"=>"BDMS Are the possibilities endless?","session_date"=>"24-NOV-11","session_time"=>"3:00 PM - 4:00 PM","session_level"=>"Intermediate","session_notes"=>"","session_desc"=>"Discussion of options available to load documents into imaging.","session_room"=>"Regency","session_track"=>"Technical","primary_presenter"=>"Dorie Minich","other_presenters"=>"Jonathan Wheat "
"session_id"=>"115","session_title"=>"Upgrade Planning","session_date"=>"25-NOV-11","session_time"=>"3:00 PM - 4:00 PM","session_level"=>"Intermediate","session_notes"=>"","session_desc"=>"","session_room"=>"TBD","session_track"=>"Accounts Receivable |  Accounts Receivable |  DBA |  Technical","primary_presenter"=>"Robert Getty","other_presenters"=>"Dorie Minich "

 

Since I now know what fields I’ll have in my device’s database, I need to set up the database in the app.  With Rhodes there are two types of database you can use.  PropertyBag, and Fixed Schema (more on those here).  Anyway, let me say, I’ve chosen Fixed Schema so I can perform real SQL on the table.  PropertyBag has a different type of syntax, and doesn’t allow for a distinct(x) ability, which I’ll need shortly.

With Fixed Schema, I have to specify the structure because, well, its fixed.  I do that in the session.rb file like this -

  property :session_id, :integer
  property :session_title, :string
  property :session_date, :date
  property :session_time, :string
  property :session_level, :string
  property :session_notes, :string
  property :session_desc, :string
  property :session_room, :string
  property :session_track, :string
  property :primary_presenter, :string
  property : other_presenters, :string

That just sets up the fields and types in the Session model.

Back in session_controller.rb I have a method I created called fetch, that pulls that data into the phone and stores the file on the device.  it looks like this -

  def fetch(desc,local_filename,remote_url)
    ## Use to pull down .JSON files for system loading
    if File.exists?(local_filename)
         File.delete(local_filename)
     end
     Rho::AsyncHttp.download_file(
       :url => remote_url,
       :filename => local_filename,
       :headers => {},
       :callback => {},
       :callback_param => "" )
  end

I use this method many times and in different apps I’ve worked on.  Sending it a URL and a temporary filename, the file is downloaded to the phone.  I can then process the file using my insert_session method like this to build my model -

  def insert_sessions
       Alert.show_popup :message=> 'Indexing Session Data',:title => 'One Moment Please'
       sleep 2
       Alert.hide_popup

      #READ FILE AND ASSEMBLE 'data'
         f = File.new(@@session_file_name)     
          f.each_line do |line|
             #take line and convert it into a hash
             h = {}
             line.split(',').each do |substr|
                ary = substr.strip.split('=>')
                h[ary.first.tr('"','')] = ary.last.tr('"','')
             end
             app_info "\n\n\n PROCESSING : " + line + "\n\n\n"

             @params['session'] = h
             @session = Session.new(@params['session'])
             @session.save
         end
    end

That builds a record for each session in the file I’ve pulled down (our model is complete and now loaded with data). Since this can take 3-5 seconds, I pop up an alert message to let the user know what’s going on and that the app didn’t lock up.  Once we have the sessions in a database on the phone, we can do just about anything with them.

I’ll create an array called @days and fill it with the distinct days from the database that sessions occur, and display that to the user so they can choose one day of sessions to look at.

@days = Session.find_by_sql("SELECT distinct(session_date) FROM Session ORDER BY session_date")

The find_by_sql method is NOT available with a Property Bag type database, thus the Fixed Schema decision.

On to the view, and I don’t mean that stupid talk show that bashes men all the time.  Our view (in this case index.erb) is rendered by the index method in our session_controler.rb file.  The overall function of view.erb is to render the data to the screen, this is where your HTML is used, along with some ruby code.  Below is my index.erb file, and you’ll notice there is some default Mobile Connection code still in there as well as necessary JQuery Mobile code.

<div id="session-page" data-role="page">

    <div data-role="header" data-position="fixed" data-theme="f" id='header'>
        <a href="<%= Mshell.show_url %>" data-direction="reverse"><img src="<%= Mshell.path %>/images/icon-back.png"/></a>
        <h1>&nbsp;</h1>
        <img src="<%= Mshell.path %>/images/icon-menu.png">
    </div><!-- /header -->

    <div data-role="content">
        <div><img src="<%= Mshell.path %>/images/icon-menu.png"></div>
        <div>    
            <ul>
                <% if Mshell.is_logged_in? %>
                    <li><a href="<%= url_for({ :controller => :Mshell, :action => :async_logout}) %>" data-transition="pop" data-direction="reverse"><%= Locale::Mshell[:label_logout] %></a></li>
                <% else %>
                    <li><a href="<%= url_for({ :controller => :Mshell, :action => :show_login}) %>" data-transition="pop"><%= Locale::Mshell[:label_login] %></a></li>
                <% end %>
                <li><a href="<%= Mshell.show_url %>" data-direction="reverse"><%= Locale::Mc[:label_home] %></a></li>
            </ul>
            <br/>
        </div>

        <ul data-role="listview">
            <div id='mappTitle'><%= Mshell.current_mapp.title %></div>
            <!-- ul style='margin-left:10px;margin-right:10px;'-->
            <li data-role="list-divider" role="heading">
                Full Session List
            </li>
            <li data-theme="c">
              <div>
                  <div>
                      <a href ="<%= url_for :action => :list_sessions %>">
                        List All Sessions
                    </a>    
                </div>
                <span></span>
              </div>
            </li>
        </ul>
        <br/><br/><br/>
        <ul data-role="listview">    
            <li data-role="list-divider" role="heading">
                Sessions By Day
            </li>
            <% @days.each do |session| %>
            <li data-theme="c">
              <div>
                  <div style='height:24px;'>
                      <% @session_date = session.session_date  %>
                      <a href ="<%= url_for :action => :list_sessions_byday, :query => {:session_date => session.session_date} %>">
                        <%= session.session_date %> <br/>
                    </a>    
                </div>
                <span></span>
              </div>
            </li>
            <% end %>        
        </ul>
    </div><!-- /content -->
</div><!-- /page -->

We’re using an unordered list to create this display.  JQuery Mobile has some fantastic theme-able elements and we’re exploiting them here.

The blue-ish code code is creating a list item with a link to list sessions

<a href ="<%= url_for :action => :list_sessions %>">

This is the Rhodes way of creating internal links to other methods.  Takes a little getting used to, but works great.  This method (list_sessions) will lists ALL of the sessions for the conference alphabetically.  We’ll add a way to filter those quickly using JQuery later.

The green bits of code are where we spin through the @days array, assign each element to an object called session and then we can access each one with dot (.) notation.  For example session.session_date displays 21NOV11 for us (only because I haven’t formatted the date yet). Each day then becomes a link off to our list_sessions_byday method that list all the sessions for one day.

<a href ="<%= url_for :action => :list_sessions_byday, :query => {:session_date => session.session_date} %>">

You’ll notice to pass a parameter in the querystring we’re using :query and setting up key/value pairs.  This equates to ?session_date=21NOV11. Our list_session_byday method pulls out the session_date parameter which we then use to query the Session model (database) to grab the sessions for that particular day

    def list_sessions_byday
      @session_date =  @params['session_date']
      @sessions = Session.find(:all,:conditions => {'session_date' => @session_date},:order => 'session_date')
      render
    end

Then we render the list_sessions_byday.erb view file, where we display all of the sessions for that particular day.  Be aware, the syntax for the find seems a bit goofy, since you’re telling it – find all of the records, and then applying the condition.  You’d think you would leave off the :all portion, and just say find records with this condition.

Without boring you with even more code, the list_sessions_byday.erb file spins through the sessions and lists the session.session_title and some other bits (See screenies below) and creates a link like this for each session -

<a href ="<%= url_for :action => :list_details, :query => {:session_id => session.session_id} %>">

This is passing the session_id off to list_details method

    def list_details
      @session_id = @params['session_id']
      @sessions = Session.find(:all,:conditions => {'session_id' => @session_id})
      render
    end

This again grabs that parameter from the query string, does a quick find against the Session model where session_id = @session_id and calls the view, which like the other views displays the session information, although this time we display everything we have about a session in a nice detail page.

Next up – I’ll either tackle the “By Track” functionality or Exhibitor information.  Only time will tell :)

Till then -keep coding and enjow the screenies below.

 


 

Code it right
theCodeDog
theCodeDog