ActiveRecord UML Diagrams 3

Posted by Bob Silva Sun, 30 Jul 2006 23:57:00 GMT

Boredom set in this weekend so while playing with my UML modeling software, I decided to model some pieces of ActiveRecord. I found that UML doesn't lend itself too well to the Ruby language. Since UML doesn't provide for mixins and modules, I modeled them as stereotyped dependencies and classes. Don't know if they are useful for anyone but they are nice to have for a quick reference to figure out how ActiveRecord is structured with all the mixins and modules.


ActiveRecord

Associations

ConnectionAdapters

Exceptions

YAML Cookbook 3

Posted by Bob Silva Fri, 30 Jun 2006 07:18:09 GMT

While researching what some of the YAML syntax was doing in Ben Bleything's article on DRY'ing up your database config, I ran across the YAML Cookbook. I've only ever used YAML for my database.yml and test fixtures, so I was really surprised to see the power YAML affords the Ruby programmer. Check it out, you will find a few things useful in your fixtures and I'm sure other ideas on it's use will come to you as you see how powerful it is.

Installing Raspell on Intel Mac 8

Posted by Bob Silva Fri, 30 Jun 2006 02:55:00 GMT

I'm working on an app that Special Education therapists use to track service logs on their clients for medicaid billing purposes. While the application requirements are pretty simple (with the exception of the PDF Reports), the requirement that was at the top of their list was spell checking.

Most of the work for a Rails based Spell Checker has been done already by Dee Zsombor in his How to build an AJAX-ed spellchecker with Ruby On Rails article. In his article he shows how to use Raspell (the Ruby ASpell bindings) to implement an AJAX based spell checker in Rails. While his tutorial worked great on Linux, Raspell failed to compile (manually or using the gem) on Intel Mac. The compiler was complaining of multiple symbol errors defined in raspell.h. Even though it had pre-processor IFNDEF statements, it still acted like it was including the header multiple times. While there may be another way to fix this, the quick and simple way was to take all the code from dictinfo.c and aspell.c and inject it into raspell.c. Problem solved.

Hopefully, in a few weeks, I'll be able to release a Rails SpellChecker Plugin which will enable spell checking on any text field/area with a simple Rails helper method.

Macbook Battery Dead 7

Posted by Bob Silva Sat, 24 Jun 2006 12:13:45 GMT

Well, finally ran into my first problem with the new Macbook. My battery will only power a laptop for about 10 minutes before shutting down (actually it just turns off). Jeremy Hubert was nice enough to swap batteries with me and sure enough, within a few minutes, his laptop shut down as well. Hoping to get to the Apple Store here in Chicago to get a replacement.

RailsConf Update 3

Posted by Bob Silva Sat, 24 Jun 2006 12:05:00 GMT

The first day has been filled with ups and downs. It started great with Dave Thomas challenging DHH's philosophies on Rails. His call for foreign keys and non-integer primary keys I think was dead on. I hope it gains some traction among the core developers. I started work on this awhile back but got no feedback whatsoever from core. Its definately not a very elegant solution but I think it will benefit Rails in the long run.

Mike Clarks Introduction to Capistrano was pretty good. Although I don't personally plan to use it until it works in parallel, it's still a pretty nice piece of software, although I still prefer my multicast notification and ftp-diff pull solution better. Maybe I should make Castripano???

The next session doesn't even deserve any mention, if you were stuck in it then you know what I'm talking about.

Dr. Stefan Kaes' session on Optimizing Rails had a lot of excellent material presented, although his presentation style was pretty dry. Much better talking to him in person.

I'm sure Martin Fowlers keynote was filled with insight, unfortunately, most of the caboosers were busy negotiating how many and what type of pizzas to get for dinner.

Afterwards, we acquired a room in the hotel and had some famous Chicago Deep Dish pizza from Giordanos. Think this is the first time in my life 2 pieces of pizza has filled me up, gotta love Chicago pizza!

Paul Graham's poetic speech was excellent and dealt with some items that I struggle with, mainly about taking risk. I have a lot of good ideas for applications, but my inner self talks me out of them before I even start coding.

To cap off the night, Why the lucky stiff did his thing. While I can certainly appreciate Why's artistic creativity, it was beyond the scope of my understanding. The only thing that I understood was Robert Scoble killing David Heinemeier Hansson. Others really seemed to enjoy it though. I imagine better acoustics would have improved the act.

Let's hope tomorrow continues to improve on the quality of the sessions and keynotes.

Hello Chicago!

Posted by Bob Silva Thu, 22 Jun 2006 03:29:14 GMT

After a 2 hour delay due to severe thunderstorms, I finally arrived in Chicago to slightly overcast skies and warm humid air. I'm checked into the Wyndham (room 151) and it turns out most of the caboosers went out to eat. I found Amy Hoy (eriberri on irc) and Blake and enjoyed a quiet dinner with them. I didn't realize the main conference doesn't actually start until Friday so I hope the "self-organizing" sessions are worthwhile tomorrow.

I haven't flown anywhere for quite awhile and I guess lighters are on the "banned" list of items for carry on (ironically, matches are ok????). So after my lighters got confiscated, I had to pay $6 for a pack of matches. The good news is, they came with a free pack of cigarettes.

More later as the conference progresses....

Blogging is hard work 4

Posted by Bob Silva Tue, 06 Jun 2006 03:55:00 GMT

Well, I lost control of my blog for a little while but I think I have it back to a sane usable state. Hopefully the new Typo engine will handle spam a little better than it's predecessor. Once I started getting traffic all the spammers started having a field day with my site and I didn't have the time to stay on top of it. We'll see how it goes now.


Unfortunately, I had to lose all the existing comments to fix it. Haven't looked into the exact method of how they are spamming it but I have a feeling that I will need to add some sort of verification system to Typo to maintain it.

Generating PDF Documents with Rails and PDFlib - Part II

Posted by Bob Silva Sat, 22 Apr 2006 21:09:00 GMT

Here is Part II of my series on PDF generation from Rails. Part I covered installing and configuring the PDFlib-Lite library from PDFlib.com. In this part, I will walk you through creating this from scratch.


Ready to begin?

First you need to download this zip file which contains a PDFlib wrapper which makes generating PDFs so much easier. It also contains the source code and images used in this tutorial. Extract the zip file and copy the pdf.rb into the lib directory of your Rails application. Then copy the rails.gif image somewhere on your filesystem. Doesn't matter where, we'll tell PDFlib where to find it later.

Open an existing controller or create a new one and addan action named pdftest as shown below:

  def pdftest
    send_data(render_to_string(:action => 'pdftest', :layout => false),
      :filename => "pdftest.pdf", 
      :type => "application/pdf", 
      :disposition => "inline")
  end
This method will render the PDF generated in the rhtml file to a string, and pass it through to the web browser using the send_data method in Rails.


Next, create a new pdftest.rhtml file in the appropriate app/views directory for the controller you just added the pdftest action to.


Lets start coding. Open the pdftest.rhtml in your favorite editor and follow me down the yellow brick road....

<%

# Create the PDF object and reverse the coordinate system. By
# default, PDFs cartesian coordinate system starts with (0,0)
# in the lower left corner. By setting @topdown => true, we flip
# the coordinate system upside to make the upper left (0,0).
# You can also set default margins and page sizes during initialization
p = PDF.new(:topdown => true)

# When working with PDFs, the typical structure is a document 
# with many pages. Calling open begins what PDFlib refers to as
# document scope.
p.open

  # Our PDF only needs one page to display the book cover
  # so we'll open a new page here, and close it at the end
  p.beginpage

    # When working with PDFs, setting a base font/size is required 
    # before writing any text to the page. We wont use this font for
    # this page, but thats OK
    p.font('Helvetica', 10, '#000000')

    # Remember when I said we would tell PDFlib where to find
    # our images? Here ya go. Stick in the path to where you
    # copied rails.gif to.
    p.set_parameter('SearchPath', '/path/to/images')


    # Let the fun begin. We'll start out with the book outline.
    # Just gonna draw a black outline and fill it with white.
    # Using the rect method, this is easy to do. By passing
    # the stroke and fill colors, we tell the method to both
    # stroke and fill the path created.
    # def rect(x, y, w, h, options={})
    p.rect(p.left_margin,
           p.top_margin,
           p.page_width-(p.left_margin+p.right_margin),
           p.page_height-(p.top_margin+p.bottom_margin),
           :fillcolor => '#ffffff',
           :strokecolor => '#000000')
    
    # Next up is the maroon tab at the top of the book with 
    # the text 'The Pragmatic Programmers'. To draw out this
    # odd shape, we'll create a path and pass an multi-dimensional
    # array of points for the path to follow. This time, by only
    # specifiying a fillcolor, we are telling PDFlib not to stroke
    # the path, but only fill it.
    p.path([[102,p.top_margin],
            [312, p.top_margin],
            [300, p.top_margin+63],
            [114, p.top_margin+63]],
            :fillcolor => '#741415')
    
    # Time to add the text in the pretty maroon box we just made.
    # Here, we set the font we want to use ahead of time. Later,
    # I'll show you a different way to do it inline.
    p.font('Times-Roman', 16, '#ffffff')
    p.print 'The', 160, 51
    p.print 'Pragmatic', 151, 66
    p.print 'Programmers', 172, 80
        
    # For the Title of the Book, we demonstrate how we can
    # use pass-through options for native PDFlib functionality
    # not provided for in the wrapper. We are able to adjust
    # the charspacing and horizscaling by passing those options
    # as Hash elements and the wrapper library sends them onto
    # the native PDFlib method. This also demonstrates how
    # to set the font/fontsize inline on a single call to print
    p.font('Times-Roman', 60, '#000000')
    p.print 'Agile', 112, 230 
    p.print 'Web', 254, 230, :charspacing => -2
    p.print 'Development', 162, 278, :horizscaling => 105
    p.print 'with', 248, 308, :fontsize => 38
    p.print 'Rails', 322, 324, :horizscaling => 110
    
    # Working with images in PDFs is easy as you can see below.
    # Pass the name and location and walla, an image in your PDF.
    # Images can be used as templates for forms as well. If you have
    # complex line layouts, its easier to save an image version of the
    # raw template, then insert it as a background layer and write on
    # top of it.
    p.image 'rails.gif', 140, 330
    
    # In these print calls, we give the :boxsize of the textfield 
    # and specify the :position to obtain right aligned text.
    p.font('Courier-BoldOblique', 14)
    p.print 'Dave Thomas', 300, 600, :boxsize => '{205 20}', :position => '{right bottom}'
    p.print 'David Heinemeier Hansson', 300, 618, :boxsize => '{205 20}', :position => '{right bottom}'
    
    # Just another rectangle here for the footer of the cover.
    p.rect(p.left_margin, 
           p.page_height-p.bottom_margin-35,
           p.page_width-p.left_margin-p.right_margin,
           35,
           :fillcolor => '#741415')
    
    # Here we right align the text, set the fillcolor for the font,
    # and set the font/fontsize inline on the print call
    p.print 'The Facets of Ruby Series', 260, 754, :boxsize => '{310 20}', :position => '{right center}', :fillcolor => '#ffffff', :font => 'Times-Roman', :fontsize => 24
    
  p.endpage
p.close

# This next line actually sends the in-memory PDF back to the 
# controller as a string so that it can be sent to the browser.
%>

<%= p.read -%>

If you PDF doesn't look like this, then you didn't follow me very well. As you can see, generating PDF's doesn't have to be difficult, but it can be time consuming as you get into more complex layouts. I'm done with my PDF work on my latest application, so this will conclude this series on Generating PDFs in Rails. Have fun!

ActiveRecord Calculations 1

Posted by Bob Silva Sat, 22 Apr 2006 14:59:00 GMT

Rick Olson's Calculations Plugin (which is now part of core) is great as long as you only need to perform a calculation on one column in your model. I had a need to sum two columns in a result set and after talking with Rick on IRC, started to modify his Calculations Plugin to accept a hash of {:calc => :column} pairs. Time was of the essence though so I found a different way to do it using AR. The examples below don't really have any wow factor, but they may be helpful to someone.


In the example below, it inner joins table (ModelB) and groups by a column (group_field) from that table, just to show how it might be done.

The magic is the :select option. It allows you to define what goes into the SQL statement (SELECT :select FROM ...). The :readonly attribute on the find call, is to prevent you from trying to modify the record since it is not a fully loaded AR record set.

@model_a = ModelA.find(:all,
  :select => 'sum(column_a) as column_a, sum(column_b) as column_b, model_b.group_field', 
  :joins => 'inner join model_b on model_a.id = model_b.model_a_id', 
  :group => 'model_b.group_field', 
  :conditions => ['column_a=?', column_a_value],
  :readonly => true)


Now that you have your recordset, you can use your calculated columns like any other AR attribute. In this case, @model_a.column_a. If you build more advaned reporting or charts into your applications, you will find yourself using this method a lot.

User Friendly Time Entry

Posted by Bob Silva Sat, 22 Apr 2006 08:49:00 GMT

Have a need to track time spent on something? Here's an easy way to allow your users to enter their time in a smart way (anyway they want). This example accepts fractional hours, overflowing minutes and converts and displays them as the user would expect. They are stored in your database as minutes (integer) and displayed as hours/minutes (regardless of how they were input).

Model Code (model.rb):

def set_travel_time(hours, minutes)
  self.travel_time = ((hours.to_f * 60) + minutes.to_i).to_i
end

def get_travel_time
  travel_time.to_i.divmod(60)
end


Controller Code (models_controller.rb):

def create
  @model.new(...)
  ...
  @model.set_travel_time(params[:hours], params[:minutes])
  ...
  if @model.save
  ...
end

def edit
  @model = Model.find(...)
  ...
  @hours, @minutes = @model.get_travel_time
  ...
end


View Code (_form.rhtml):

<%= text_field_tag 'hours', @hours -%> hours 
<%= text_field_tag 'minutes', @minutes -%> minutes 

Older posts: 1 2 3 4 5