Checkbox Lists in Ruby on Rails

Posted by Mike on October 21, 2009

I will briefly cover creating a list of check boxes on a website that will allow data to be saved to the database. This can be done using a standard form and post or using Ajax. This article will cover the form/post method.

For this example I will have a feature model and a client model. There is a many to many relationship between these two models using a subscription model.

We’ll start with a view template that just lists all available features:

<ul>
  <% for feature in @features %>
    <li><%= feature.name %></li>
  <% end %>
</ul>

 

Now let’s put it inside a form, and checkbox to each list item, and put an update button on it:

<% form_tag "/path/to/post/to", :method => :put do %>
  <ul>
    <% for feature in @features %>
      <li>
        <%= check_box_tag 'feature_ids[]', feature.id, subscribed_to?(feature) %>
        <%= feature.name %></li>
    <% end %>
  </ul>
  <p>
  <%= submit_tag 'Update' %>
  </p>
<% end %>

OK, there are a couple things here that I will explain.  Notice the use of the square brackets in the check_box_tag name.  This allows there to be a list of items with the same name and have them passed as an array in the params.  Also notice that instead of stating true or false as the third element of the check_box_tag, I’ve used a helper method.  This allows me to say that the check box is checked if the client is subscribed to that feature.  That code could look something like:

def subscribed_to?(feature)
  @client.features.include?(feature)
end

We also need a little code in our controller to populate things:

def subscriptions
  @client = Client.find(params[:id])
  @features = Feature.all
end

The action used by the “/path/to/post/to” should now have everything it needs to update the database.  There is an array of feature_ids that can be passed to a model to update the database.  Then you might want to do something like set a flash message to let the user know what happened and redirect to an appropriate page.


def set_subscriptions
  do_something_with_this_array(params[:feature_ids])

  flash[:notice] = ‘Subscriptions Updated’

  redirect_to ‘/someplace/relevant’
end

This is not a complete tutorial by any means.  Hopefully it helps point you in the right direction.  Railscast #52 covers this same topic and may also be a helpful resource.

Setup locate command on Mac OS X

Posted by Mike on February 28, 2009

One of the commands that I immediately missed when I started using OS X for my development environment was the locate command. It is very helpful to be at a command prompt and type:

locate mysql

and have it return a list of every file and directory with mysql in them. It is very fast and is great for chaining with other shell commands. In order for it to work it needs a local file database and it needs to update the database periodically to keep up with the changes made on the system. So my goal with these instructions is a quick way to get locate to work and have it update once a day to keep up with everything.

1. Open a Terminal
2. type: sudo /usr/libexec/locate.updatedb

Once it’s finished running, the locate command will work. That same command needs to be run anytime you want the file database updated. I schedule this to run daily with cron.

1. type: sudo crontab -e
2. add this line to the file, save, and exit

30 20 * * * /usr/libexec/locate.updatedb

What this says is run this command everyday at 8:30 pm. You can adjust this time to what ever is most convenient. It’s best if this is a time when you expect the machine to be on but not in heavy use, as it will make it slow for a few minutes while it runs.

Now the locate command should be working and automatically updating itself for file changes everyday. If you decide to change the time that it runs, just follow the second set of steps again and it will overwrite the existing settings. If you’d like to dig deeper into the crontab file for more advanced scheduling options type:

man 5 crontab

Moving On

Posted by Mike on February 08, 2009

I have accepted a position at UCLICK as a software engineer. They are a digital content provider and syndication company that specializes in both the online and mobile device spaces. They are a Linux and Open Source shop that has been transitioning to Ruby over the last couple years moving from Apache/mod_perl to Ruby on Rails. I will be working with some very smart people that are passionate about technology and the work that they do.

Anyone who knows me will know that this is as much about coming back as it is moving on. I was one of the founding members of the company back in 1999 as we tried to establish ourselves during the dotcom boom. I designed and built much of the infrastructure that allowed the company to grow it’s online traffic. My roll has changed and I will be focused more on development rather than the network and systems. I’m excited to be working in an Open Source shop again and I’m looking forward to helping the company grow and enhance it’s product line.

Query Soap Service Using Ruby

Posted by Mike on September 29, 2008

OK, to get this out of the way.  I know, SOAP is lame and REST is cool.  However, there may still be times when you need to query data from a SOAP web service.  This article is an attempt to document the process of retrieving and working with that data.

In this example I will describe how to query the WSDL to get a list of methods and parameters, and use that to submit the method call.  I will be calling a web service method called ‘webMethod’ that accepts one parameter called ‘publishDate’.  If you don’t already know this information about the web service you are communicating with, there is a free tool called SoapUI that works pretty well.  It’s written in Java, so you should be able to get it to work on about any platform.

Depending on the version of Ruby you are running, the first thing that may be required is to install soap4r:

gem install soap4r

Next is to set the location of the WSDL file on the web server, set the encoding, and instantiate the driver:

require ’soap/wsdlDriver’
wsdl = ‘http://server/WebService.asmx?WSDL’
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
XSD::Charset.encoding = ‘UTF8′

This next line will create two logs in the directory of the process called devLog_webMethod_response.xml and devLog_webMethod_request.xml that will show the raw request and response each time the process is called.  In place of webMethod will be the actual method name of the web service being called.  This can be commented out when the application is moved to production.

driver.wiredump_file_base = “devLog”

Now it’s time to retrieve the data:

@response = driver.webMethod(:publishDate => ‘2008-09-01‘)

At this point @response contains the XML response from the web service.  In order to retrieve the data we will need to know a little bit about the structure of the XML.  We can find out this information by opening the log file created by the previous step.  Let’s open devLog_webMethod_response.xml:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance xmlns:xsd=”http://www.w3.org/2001/XMLSchema>
<soap:Body>
<WebMethodResponse xmlns=”WebMethod>
<WebMethodResult>
<Article>
<Name>Example 1</Name>
<Headline>Poor Excuse For An Article</Headline>
<Body>Nothing to see here, move along please.</Body>
</Article>
<Article>
<Name>Example 2</Name>
<Headline>Woot!  I Made Headlines</Headline>
<Body>Yeah, OK.  Another poorly written example article.</Body>
</Article>
</WebMethodResult>
</WebMethodResponse>
</soap:Body>
</soap:Envelope>


OK, so here we have two articles that contain the data we are after and they are both inside the WebMethodResult tags.  So to access those bits we might do something like:

@response.webMethodResult.article.each do |article|
puts article["Name"]
puts article["Headline"]
puts article["Body"]
end


That works great as long as there is always more than one article.  If, on the other hand, there is only one article in the result, it is no longer an array and the .each method will fail.  So to get around this we can move our logic to a method and then test the article first to see which way we should handle it.  So the previous code might be rewritten as:

def print_article(article)
puts article["Name"]
puts article["Headline"]
puts article["Body"]

end

if(@response.webMethodResult.article.is_a?(Array))
@response.webMethodResult.article.each do |article|
print_article(article)
end
else
print_article(@response.webMethodResult.article)
end



If you are asked to do some work with SOAP based web services, hopefully this makes it a little easier to get up and running.

IE 7 and Word Wrap

Posted by Mike on September 25, 2008

I guess this is what I get for doing most of my testing in Firefox. I created an aspx page to be opened in a javascript window.open to allow a customer to preview some rendered HTML. I used labels in the aspx page and then populated those with data returned from a database. Everything looked great in Firefox, but when I checked it in Internet Explorer, there was no word wrapping. Each line ran off the page. After some research I found a CSS property called word-wrap. The property is part of the CSS3 draft and is used to force word wrapping. Since this is a simple page that is opened in a pop-up window, I was able to fix the problem by simply adding the following to the CSS style.

body {
  word-wrap: break-word;
}

If I understand the CSS3 draft correctly, this should actually force a word wrap even if it occurs in the middle of a word. However, in testing with both Firefox and IE 7, this is not the case. It breaks at the end of the word.

ruby.exe Unable To Locate Component readline.dll 3

Posted by Mike on August 30, 2008

I just installed ruby 1.8.7 on a Windows machine and when I started IRB:

readlineerror

The fix:

  1. Go to http://gnuwin32.sourceforge.net/packages/readline.htm and download the binaries zip file.
  2. Unzip the file.
  3. Change directory to the new directory created by unzipping the file.
  4. Change directory to the bin directory.
  5. Copy the readline5.dll file.
  6. Change directory to your ruby/bin directory (for me this is C:\ruby\bin).
  7. Paste readline5.dll file there.
  8. Rename file readline.dll.

As long as your ruby\bin directory is set in your PATH environment variable, that should take care of the problem.

Ruby on Rails Development Environment on Ubuntu Linux 8.04.1 1

Posted by Mike on August 13, 2008

I just went through the process of setting up a new Linux desktop for Rails development.  In an effort to keep it short and to the point, I’ve trimmed up some of the info that I found useful from wiki.rubyonrails.org.  This is just a basic development stack.  I plan to write another post on the editors that I’ve tried and what I’ve found to work best for me so far.  Anyway, let’s get started.  I tend to work primarily at a command prompt, so that’s the method I’ve described here.  Open a terminal window and follow along:

sudo apt-get install ruby rdoc libyaml-ruby libzlib-ruby ri libopenssl-ruby ruby1.8-dev build-essential

You don’t want to install the rubygems package from the Ubuntu repository.  It is consistently out of date, so you will need to pull the tarball down from RubyForge:

wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz
tar xvzf rubygems-1.2.0.tgz
cd rubygems-1.2.0
sudo ruby setup.rb

At least with the versions I’ve installed, I had to create a symbolic link to gem1.8:

sudo ln -s /usr/bin/gem1.8 /usr/bin/gem

You should now be able to do a gem update:

sudo gem update --system

And install Rails:

sudo gem install rails

Now it’s time to take care of the database installation:

sudo apt-get install mysql-server libsqlite3-0 libsqlite3-dev
sudo gem install mysql sqlite3-ruby

If you want to install RMagick:

sudo apt-get install imagemagick libmagick9-dev
sudo gem install rmagick

That should do it.  Now go have some fun!

How to change the default editor in Debian and Ubuntu

Posted by Mike on August 10, 2008

I’ve been a fan of Ubuntu Linux since I first started using it a few years ago.  One of the first things I do when building a new Ubuntu machine is set the default editor to Vim.  I have been using Vi for a long time and the keyboard shortcuts are very natural for me, so the first time I typed a command like visudo or crontab -e and got the Nano editor, I was shocked.  With Ubuntu 8.04 it’s really very easy:

Open a terminal window (Applications/Accessories/Terminal)
Type: sudo apt-get install vim-full

That should do it.  By default only the vim.tiny package is installed and installing the vim package (apt-get install vim) only gets you vim.basic.  Both of those will leave the default editor as Nano.  Installing the vim-full package will take care of modifying the default editor for you to be vim.gnome.  If you would like to change the setting to something else, or that didn’t work with the version of Debian or Ubuntu that you have, try:

sudo /usr/sbin/update-alternatives --config editor

Then pick the number that corresponds with your choice.

Grouping in LINQ

Posted by Mike on July 31, 2008

I’ve been using LINQ for my data access piece in .NET for the last few months and I thought I would write a quick post on how I’ve found to do grouping. I’ve seen some examples where a ‘group by new’ is done with a list several fields to group by. I’ve also seen similar examples in SQL, but this is often times not what is wanted. In SQL it generally requires a join to a second query that has the grouping field and any aggregates that are needed. In LINQ, a way that I’ve found to work for me is something like this:

var q = from invoice in context.Invoices
    where invoice.ManifestDate >= startDate && invoice.ManifestDate <= endDate
    group invoice by invoice.PoNumber into g
    select new {
        PoNumber = g.Key,
        g.First().InvoiceNumber,
        g.First().ManifestDate,
        ShippingCharge = g.Sum(p => p.ShippingCharge),
        ProductCharge = g.Sum(p => p.Quantity * p.NetPrice),
        g.First().CreateDate
    }

This allows me to group only by PoNumber in this example and calculate aggregates on ShippingCharge and ProductCharge from the group. In this example this is only going to use the first value found in the group for the value returned, which is an acceptable solution for me in this scenario.

In SQL this might look something like:

SELECT DISTINCT
    inv.PoNumber,
    inv.InvoiceNumber,
    inv.ManifestDate,
    g.ShippingCharge,
    g.ProductCharge,
    inv.CreateDate
FROM Invoice inv
JOIN (
    SELECT
        PoNumber,
        SUM(Quantity * NetPrice) as ProductCharge,
        SUM(ShippingCharge) as ShippingCharge
    FROM Invoice
    GROUP BY PoNumber) g
ON inv.PoNumber = g.PoNumber

Getting Started with IronRuby

Posted by Mike on July 27, 2008

Justin Etheredge has put together an excellent series of tutorials for setting up and getting started with IronRuby on his site.