On The Desired Complexity of Rails

Posted by Brian in Rails (August 21st, 2011)

I attended Madison Ruby this weekend and got a healthy dose of knowledge from some very talented presenters. Some of the talks focused heavily on improving our practices, especially in Rails applications.

Jeff Casimir talked about making views nicer by introducing decorators. These are relatively simple to implement in a language like Ruby, but Jeff created a nice gem to make it even easier, called Draper.

Several talks mentioned using decent_exposure, a gem by Stephen Caudill, to keep instance variables out of views, as Rails does a somewhat nasty hack to get instance variables from controllers.

Then today, I saw another article talking about how Rails code could be made even more easy to maintain by leveraging Dependency Injection, a well-known, and very very useful technique.

On a few applications, I could have used a couple of these techniques to make the code easier to maintain later. And on one I did use a proxy instead of helpers in a complex view. But in the last six years of working on projects for clients, other consultancies, and even when I’ve mentored others, using these patterns would have been a huge jump in complexity for the majority of the projects.

When I decided to use Rails, it was because it was a productivity boost. When compared to Struts, Spring MVC, or other similar frameworks, Rails cuts a lot of corners in exchange for this productivity.

But seeing a number of respected thought leaders looking to bring this complexity to Rails makes me wonder…. is Rails (the community) growing up? Are we out of the “teenage kid that knows it all” phase? Are we done telling Java and C# programmers that they’re not “with it”?

Since it came on the scene, Rails, through decisions made by developers and the core committers, has evolved from something a PHP developer or Java developer would find easy to pick up to something that is much, much more complex. It’s no longer a framework for beginners, but rather a solid foundation and collection of “best practices” to build modern web applications. Rails is now being used to build bigger and more complex applications, and that complexity calls on us to revisit concepts like decorators, proxies, service objects, and dependency injection, the very “high ceremony” things that Rails developers were proud to avoid a few years ago.

While I don’t expect these kinds of things to make it into Rails itself, I do expect these concepts to gain traction. But I hope they only gain traction for the 5% of the situations where they’re needed, rather than for the sake of “well, so-and-so said it was good, so I’m doing it.” Using these tools to mediate complexity in applications adds a different kind of complexity, and that’s worth some thought, especially since, as I was told several times this weekend, there’s apparently a shortage of talented Rails developers these days.

Proper use of these object-oriented concepts in the right place will make our projects better. But it’s vital that we truly understand when we should apply these patterns so we can decide when the additional complexity is warranted, and where it’s overkill. As I was reminded this weekend, there is no “golden path” in Rails.

I encourage you to explore these things. And read Design Patterns in Ruby
while you’re at it, especially if these concepts are new to you.

Installing Oracle Client on Ubuntu.

Posted by Brian in Rails, tips (May 31st, 2011)

Ubuntu isn’t one of the supported operating systems from Oracle, so we have do to some manual work to get things set up.

First, we need to create a home for the files we’ll be downloading.


sudo mkdir -p /opt/oracle/11_2
sudo apt-get install libaio1

Then we need to visit Oracle’s download page and grab these three files for the Instant Client for Linux:

Instant Client Basic-Lite
Instant Client SDK
Instant Client SQLPlus*

We’ll want the ZIP files, not the RPM files, for each one. You will need an Oracle account to download these files.

Then, once we get those zip files over to our Ubuntu server, we need to unzip them all. We should end up with a folder called

instantclient_11_2

Now let’s move that folder into the /opt/oracle/11_2 structure we made.

mv instantclient_11_2 /opt/oracle/11_2/instantclient

Next, we need to open /etc/environment and add this line:


LD_LIBRARY_PATH=/opt/oracle/11_2/instantclient

The LD_LIBRARY_PATH is a variable used by lots of programs that talk to Oracle.

At this point, you will want to estart your terminal session so the environment variable will be available. You could set it manually, but this is a good place to test to make sure that the variable is actually loading into the environment.

Next, we’ll fire up sqlplus to make sure that the Oracle stuff is installed properly.

sqlplus

If it comes up without any errors, we’re good to go. We can exit with CTRL+C.

Next, let’s install the Ruby Oracle adapter. We’ll need to symlink a file since we’re using the InstantClient.


cd /opt/oracle/11_2/instantclient
ln -s libclntsh.so.11.1 libclntsh.so

Next, we need to copy over all the development header files into the instantclient root folder so RubyGems can find them when it needs to compile the native extensions.


cd /opt/oracle/11_2/instantclient/
cp sdk/include/*.h .

Finally, we can install the gem. If you’re using sudo, then the environment won’t have the variables you need so you’ll need to pass them with the command.

sudo env LD_LIBRARY_PATH=/opt/oracle/11_2/instantclient gem install ruby-oci8

That should be it. If you run into other problems, don’t fight with Oracle – just remove the /opt/oracle/11_2/instantclient folder and start over.

Rails 3, Refactored Code, and Docs

Posted by Brian in Rails (May 10th, 2011)

If you’ve been doing Rails work for a long time, you’re familiar with the difference between delete and destroy in your ActiveRecord models. If you weren’t, you might look at your code and see what class you
inherited from.

  class User < ActiveRecord::Base
   ...
  end

In Rails 2 and below, the delete and destroy methods were both listed in the documentation for ActiveRecord::Base.

In Rails 3, you'll find these under ActiveRecord::Persistence. And the only way you'd know to look there is by looking through the eight delete methods located in the sidebar at the API.

There's not really a good fix, because the refactoring they did makes a lot of sense. But it also makes these automated documentation tools a lot less useful, especially since there's no indication in ActiveRecord model declarations that a Persistence module is loaded. You'd need to dig into the Rails source, or know who to ask for clarification.

And if you're wondering what the difference is, destroy will invoke callbacks and observers, whereas delete just uses raw SQL to remove the record. Both have their place and it's important to know the difference.

Sharing Vim configs with Mac and Windows using Dropbox

Posted by Brian in Howto, Programming, Rails (January 27th, 2011)

I’m back to using VIm again, after a few years of working with TextMate on the Mac. VIm is great because it works the same on many different platforms, and I jump from Mac to Windows a lot these days.

I’ve devised a setup that lets me keep almost all of my configuration for VIm on my Dropbox account so I can have the same configuration synchronized on all of the computers I use. Here’s how you do it:

Inital Setup

Of course, I assume you have Dropbox and VIm installed on your Mac and Windows machines. I’m not covering any of that setup in this article.

You need a few folders in your Dropbox to make this work. I find doing this on my Mac the easiest:

mkdir -p ~/Dropbox/dotfiles/.vim/autoload
mkdir -p ~/Dropbox/dotfiles/.vim/backup
mkdir -p ~/Dropbox/dotfiles/.vim/bundles

Next, we’ll create a master .vimrc file in our Dropbox. If you already have one, move it there.

mv ~/.vimrc  ~/Dropbox/dotfiles/.vimrc_main

If you don’t have a good config file, there’s one at the end of this article you can look at. For now, just create a blank file there:

touch ~/Dropbox/dotfiles/.vimrc_main

Next, let’s set up a way to manage plugins, or extensions to VIm.

Pathogen

We’ll use Pathogen.vim to manage our plugins. Pathogen modifies VIm’s load paths and lets us keep our plugins in folders we can easily update.

Download Pathogen.vim from the official site and place it in your Autoload folder.

mv pathogen.vim ~/Dropbox/dotfiles/.vim/autoload/pathogen.vim

vimrc

Now, create a new .vimrc in your Dropbox folder. This will be our normal .vimrc for our macs.

  vim ~/Dropbox/dotfiles/.vimrc_mac

And put this in the file:

call pathogen#helptags()
call pathogen#runtime_prepend_subdirectories(expand('~/Dropbox/dotfiles/.vim/bundles'))
source ~/Dropbox/dotfiles/.vimrc_main

We’re telling Pathogen to load any installed plugins from our Dropbox, and then we’re loading in our vimrc_main file which will contain all of our platform independent configuration.

Now, symlink that to your home directory so VIm will find it.

ln -s ~/Dropbox/dotfiles/.vimrc_mac ~/.vimrc

And symlink your .vim folder so everything else you put there gets loaded as well:

ln -s ~/Dropbox/dotfiles/.vim ~/.vim

Now we’re ready to set up the Windows side of things.

Windows setup

Since Windows has no symlink support, you’ll need to create a couple of empty stubs. You’ll need a _vimrc file and a _vimfiles folder in your Home directory.

First, from a command prompt, create a _vimfiles folder

   mkdir %HOMEDRIVE%%HOMEPATH%\vimfiles

And an autoload folder

   mkdir %HOMEDRIVE%%HOMEPATH%\vimfiles\autoload

Then copy pathogen.vim into that folder from your dropbox

   cp "%HOMEDRIVE%%HOMEPATH%\My Dropbox\dotfiles\.vim\autoload\pathogen.vim" %HOMEDRIVE%%HOMEPATH%\vimfiles\autoload\pathogen.vim

Create the file %HOMEDRIVE%%HOMEPATH%_vimrc

  vim %HOMEDRIVE%%HOMEPATH%\_vimrc

Add this to the file:

call pathogen#helptags()
call pathogen#runtime_prepend_subdirectories(expand('c:\My Dropbox\dotfiles\.vim\bundles'))
source c:\My Dropbox\dotfiles\.vimrc_main

This is nearly identical to the file on our Mac, but it instead specifies the paths to the vim bundles folder and vimrc_main files in our Dropbox. Change those paths to the ones for your Dropbox installation!

Environment Variables and Path

At this point, you should set a HOME environment variable, as Windows doesn’t yet ship with that variable set by default (although it does have HOMEDRIVE and HOMEPATH variables.) Many VIm plugins use the HOME environment variable, and things might break down if you don’t have one set. You can set the HOME environment variable to %HOMEDRIVE%%HOMEPATH%.

Next, you should ensure that VIm is on your system PATH so you can access it from the commandline.

You typically set both of these environment variables through the Control Panel.

  1. From the desktop, right-click My Computer and click Properties.
  2. In the System Properties window, click on the Advanced tab.
  3. In the Advanced section, click the Environment Variables button.
  4. Finally, in the Environment Variables window, highlight the Path variable in the Systems Variable section and click the Edit button. Add the path to gvim.exe to this list, keeping in mind that each different directory is separated with a semicolon.
  5. Next, create a new environment variable called HOME, and give it the value %HOMEDRIVE%%HOMEPATH%

Plugins

Many of the most awesome plugins for VIm are now maintained in Git repositories stored on Github. If you have Git installed on your Mac, which you can do quickly with the Mac OSX installer, you can clone each plugin’s repository right into your vim/bundles folder and Pathogen will load them right up.

Here’s what I use:

  • Rails.vim gives me support for Rails development
  • The Cucumber and HAML bunldes provide syntax support for their respective languages.
  • The NERDTreee plugin gives me a project tree which is absolutely necessary when working on anything substantial.
  • The closetag plugin lets me close any open HTML tags by pressing CTRL+_, and since I work in HTML and XML a lot, it’s a lifesaver when you’re several levels deep in a hierarchy.
  • I’m using the VividChalk color scheme, which I love.


cd ~/Dropbox/dotfiles/.vim/bundle
git clone git://github.com/tpope/vim-rails.git
git clone git://github.com/tpope/vim-cucumber.git
git clone git://github.com/tpope/vim-haml.git
git clone git://github.com/tpope/vim-endwise.git
git clone git://github.com/scrooloose/nerdtree.git
git clone git://github.com/scrooloose/nerdcommenter.git
git clone git://github.com/tpope/vim-surround.git
git clone git://github.com/vim-scripts/closetag.vim.git

For suggestions on other plugins, see Tammer Saleh’s blog post on the topic, which is very helpful.

A .vimrc_main config file

Remember the .vimrc_main file we created in the Dropbox? You’ll put all of your common configuration in that file. Here’s what’s in mine, if you’d like a starting point. I’ve pulled this from so many sources I can’t even remember where everything came from, but I have found that peeking at other people’s VIm files is really helpful.

A couple of important points about this configuration:

  1. The mapleader key is set to the comma, and I’ve set it so that the NERDtree plugin can then be toggled with ,d when you’re in normal mode.
  2. I’ve set soft tabs to two spaces.

It’s not an amazing configuration by any means, but it does the job for me.

Wrapping Up

There are a ton of steps to this process, but once you’ve gone through it, you can easily work on code on any configuration. And you can install Dropbox on Linux, too, so you could expand this over to that platform as well.

Share your comments and suggestions. I’m always looking for new VIm tips.

Connecting to SQL Server from a Mac (Again)

Posted by Brian in Rails, tips (September 20th, 2010)

Connecting to SQL Server is one task I have to do regularly when I work on Rails applications for clients that use Microsoft technologies. I usually set my machine up and don’t really worry too much about how it all comes together.

Recently I had to do the installation completely from scratch. I followed Ken Collins’ comprehensive walkthrough, but I ran into a problem – I wanted to use RVM. Ken’s tutorial uses MacPorts to install the Ruby ODBC bindings, and I wasn’t using Ruby via MacPorts.

Everything out there wasn’t working for me even when I followed Ken’s article on RVM.

Here’s what ended up working for me.

First, I used MacPorts. Then I installed the ports I needed:

sudo port install unixodbc
sudo port install freetds +odbc

I modified /opt/local/etc/freetds/freetds.conf to look like this:

[my_dev_server]
  host = 192.168.1.58
  port = 1433
  tds version = 8.0

Then I modified /opt/local/odbcinst.ini to point to my FreeTDS configuration:

[FreeTDS]
Decscription = FreeTDS driver for SQLServer
Driver = /opt/local/lib/libtdsodbc.so
Setup = /opt/local/lib/libtdsodbc.so
FileUsage = 1

Finally I modified /opt/local/odbc.ini and created my ODBC DSN.

[my_dev_server_dsn]
Driver=FreeTDS
Description=My Server Connection
Servername=my_dev_server
Server=my_dev_server
Port=1433
Database=killer_app

Note that the servername matches the servername defined in the FreeTDS configuration file.

Then I went and installed the gems I needed for my project

gem install ruby-odbc
gem install dbi  -v=0.4.1
gem install dbd-odbc -v=0.2.4
gem install activerecord-sqlserver-adapter -v=2.3.9

But when I ran my Rails application, attempts to connect to models failed.

ODBC::Error: IM002 (0) [iODBC][Driver Manager]Data source name not found and no default driver specified. Driver could not be loaded

It’s using iODBC which comes with OSX. It wasn’t using UnixODBC at all!

To fix that, I had to reinstall the ruby-odbc gem and instruct it to use the unixodbc path. This is what ultimately fixed things for me:

gem install ruby-odbc -- --with-odbc-dir=/opt/local

After that, everything worked again!

Accessible Rails Applications – Let Cucumber help you test for Accessibility

Posted by Brian in Accessibility, Rails (August 27th, 2010)

Developers working with Rails are constantly looking for ways to use Cucumber to test their JavaScript. One thing I’ve come to love about Cucumber’s default setup is that it does not work with JavaScript at all, which actually helps me ensure that my applications work for uses without JavaScript enabled.

if I write a Cucumber story that tests to see if a delete works, and I’ve used the default “link_to” method for deletes made popular by the Rails scaffolding, my cucumber feature will fail. I’ll be shown the Show page instead of the “successfully deleted” message.

Keep that in mind as you work through your applications – See what stories break when you don’t have JavaScript enabled and reconsider your implementations.

Reordering Records with acts_as_list and Metaprogramming

Posted by Brian in Howto, Metaprogramming, Rails (May 28th, 2010)

Using acts_as_list, you can reorder items by adding a “position” column to your database and then easily sort records.

  class Project < ActiveRecord::Base
     acts_as_list
  end

  class Task < ActiveRecord::Base
     acts_as_list
  end

The acts_as_list plugin also provides you methods to manipulate the position.

  • @project.move_to_top
  • @project.move_to_bottom
  • @project.move_higher
  • @project.move_lower

In a current project, I have multiple items that need reordering, which means I'd be duplicating a lot of controller actions and other code across my controllers and views. I'll show you how I used metaprogramming to significantly reduce that duplication.

The Route To Reordering

First, we need some routes. Add this to your routes.rb file:

  %w{projects tasks}.each do |controller|
    %w{move_higher move_lower move_to_top move_to_bottom}.each do |action|
      instance_eval <<-EOF
        map.#{action}_#{controller.singularize} "#{controller}/:id/#{action}", {:controller => "#{controller}", :action => "#{action}"}
      EOF
    end
  end

We use an array of controllers, then we have another array of the four actions, and we just make the named routes. This generates

    move_higher_project        /projects/:id/move_higher                            {:action=>"move_higher", :controller=>"projects"}
      move_lower_project       /projects/:id/move_lower                             {:action=>"move_lower", :controller=>"projects"}
     move_to_top_project       /projects/:id/move_to_top                            {:action=>"move_to_top", :controller=>"projects"}
  move_to_bottom_project       /projects/:id/move_to_bottom                         {:action=>"move_to_bottom", :controller=>"projects"}

        move_higher_task       /tasks/:id/move_higher                            {:action=>"move_higher", :controller=>"tasks"}
         move_lower_task       /tasks/:id/move_lower                             {:action=>"move_lower", :controller=>"tasks"}
        move_to_top_task       /tasks/:id/move_to_top                            {:action=>"move_to_top", :controller=>"tasks"}
     move_to_bottom_task       /tasks/:id/move_to_bottom                         {:action=>"move_to_bottom", :controller=>"tasks"}

Metaprogramming really cuts down on work when you use it correctly. This turns out to be a pretty nice way of generating route patterns that share common attributes.

Keep The Control Centralized

Now let's step it up a notch. Each controller is going to need the four reordering methods. The logic will be identical except for the object they work on and the URL they redirect to when they're finished.

Let's create a module that adds controller methods to match these routes. We'll add it into our controllers where we need it.

Create the file lib/reorder_controller_actions.rb:

  module ReorderControllerMethods

      %w{move_higher move_lower move_to_top move_to_bottom}.each do |action|
        define_method action do
          klass = self.class.name.split("::").last.gsub("Controller", "").downcase.singularize.camelize.constantize
          item = klass.find(params[:id])
          item.send(action)
          flash[:notice] = "The #{klass.to_s} was reordered."
          redirect_to :action => "index"
        end
      end
  end

That module defines four controller actions and calls the corresponding method on the model, then does a redirect back to the index action. It'll be the same everywhere I use it, so I also gain consistency with metaprogramming.

We need to add this to the bottom of config/environment.rb so that our controllers can make use of it.

  require 'reorder_controller_methods'

Then, in each controller where we need this module, we mix it in with include

class ProjectsController < ApplicationController
  include ReorderControllerMethods
end

class TasksController < ApplicationController
  include ReorderControllerMethods
end

Stop and REST for a second

Is it appropriate for me to do it this way? I'm going to argue that while technically the position of something could be sent to the update action, I want specific redirection and notification to occur when I change the order of elements. The logic was getting too nasty in the update action, so I split each thing apart, so I went with this approach instead.

An Improved View

Next, we need some buttons for our index pages with arrows on them so the user can trigger the ordering. How about a simple helper that can generate all four buttons for us?

  def reorder_buttons(object)
    thing = object.class.name.camelize.downcase
    result = ""
    [
      {:action => "move_higher", :label => "↑"},
      {:action => "move_lower", :label => "↓"},
      {:action => "move_to_top", :label => "↑↑"},
      {:action => "move_to_bottom", :label => "↓↓"}
    ].each do |item|
      result << button_to("#{item[:label]}", send("#{item[:action]}_#{thing}_path", object) )
    end
    result
  end

We use an array hold the buttons. We use hashes within the array to map the action to the label of the button. We then iterate and generate buttons for each one, concatenating to a string that we then return.

Then in our index views, we just need to call this:

  <%=reorder_buttons @project %>

That generates exactly what I need - four buttons, one for each reordering action.

Wrapping Up

This solution easily allowed me to add reordering to a lot of controllers in only a few minutes. Hopefully it will help you do the same. You could improve this by storing the methods in a constant so that you didn't have to duplicate the array all the time, and I'm sure there are other improvements that I could make as well. I'd love to hear from you.

Making “as_string” Attribute Readers for ActiveRecord

Posted by Brian in Howto, Metaprogramming, Rails, tips (March 15th, 2010)

Occasionally, I need to transform boolean model attributes like “active” to display “active” or “inactive” instead of “true” or “false” when making reports or views. A lot of times this means writing some kind of helper method like this:

def active_or_inactive(object, true_message, false_message)
  object.active ? true_message : false_message
end

and calling it like this:

  <%= active_or_inactive(@project, "Active", "Inactive" %>

That’s not a bad approach, and it helps keep the views slightly cleaner by keeping the logic out, but it ends up being more characters than simply using a ternary operator in the view. I’ve used a slightly different approach in some of my more recent projects and I thought I should share it with you.

Move It To The Model

That’s right, I’m advocating pushing that helper into the model itself. I can hear you now, yelling something about “this guy doesn’t know what he’s talking about! How dare he put display logic in his models!” But before you close your browser, allow me to explain.

It just so happens that I need this logic not only in my views, but in my text-based reports that I run outside of the web server. I could mix the module with the helpers in when I needed it, but there’s also something un-object-oriented that bugs me about helpers. They remind me of PHP a bit. I feel like I should be calling object.active_as_string("Active", "Inactive") instead. So that’s what I’m going to do.

First, a unit test, because we’re all good professionals that write tests first. I want to call a method called active_as_string which takes two parameters – the string to print when it’s true and the string to print when it’s
false. Here are my tests:

require 'test_helper'

class ProjectTest < ActiveSupport::TestCase

  test "should display 'Active' if active" do
    p = Project.new(:active => true)
    assert_equal p.active_as_string("Active", "Inactive"), "Active"
  end

  test "should display 'Inactive' if not active" do
    p = Project.new(:active => false)
    assert_equal p.active_as_string("Active", "Inactive"), "Inactive"
  end
end

Tests help me design the method’s use up front. With two failing tests as my guide, I can now take my first stab at making the method work:

class Project < ActiveRecord::Base
   def active_as_string(true_message, false_message)
      self.active ? true_message : false_message
   end
end

With that implemented, my tests pass. However, I also have a "closed" boolean I need to handle, and it would also be nice if I could display "No description" if a project's description was blank. I could write my own _as_string methods like I've done already, but instead, I'll do a little metaprogramming to generate what I need.

Let's add four more test cases - to test the "closed" and the "description" fields.

  test "should display 'Closed' if closed" do
    p = Project.new(:closed => true)
    assert_equal p.closed_as_string("Closed", "Open"), "Closed"
  end

  test "should display 'Open ' if not closed" do
    p = Project.new(:active => false)
    assert_equal p.closed_as_string("Closed", "Open"), "Open"
  end

  test "should display 'No Description' if description is nil" do
    p = Project.new(:description => nil)
    assert_equal p.description_as_string("No Description"), "No Description"
  end

  test "should display the description if it exists" do
    p = Project.new(:description => "Hi there!")
    assert_equal p.description_as_string("No Description"), "Hi there!"
  end

Now, let's build some methods!

ActiveRecord::Base.columns

Every ActiveRecord class has a class method called columns that returns a collection of column objects. The Column object describes each database column and lets you determine its type and its name. We can use that and class_eval to generate a whole bunch of methods at runtime.


class Project < ActiveRecord::Base
  self.columns.each do |column|

    if column.type == :boolean

      class_eval <<-EOF

        def #{column.name}_as_string(t,f)
          value = self.#{column.name}
          value ? t : f
        end

      EOF

    end
  end
end

In this example, we're creating the _as_string method for each boolean column. It takes two parameters and is basically the same code we already used in our original method earlier. Notice how class_eval can do string interpolation using Ruby's #{} syntax. That makes it easy to build up the method names.

We can use that same concept to do the same for any other methods - we'll just cast them to strings and check to see if they are blank.

  class_eval <<-EOF

    def #{column.name}_as_string(default_value)
     value = self.#{column.name}.to_s
     value.blank? ? default_value : value
    end

  EOF

We throw that into the else block and our whole example looks like this:

  class Project < ActiveRecord::Base

    self.columns.each do |column|

      if column.type == :boolean

        class_eval <<-EOF

          def #{column.name}_as_string(t,f)
            value = self.#{column.name}
            value ? t : f
          end

        EOF

      else

      class_eval <<-EOF

          def #{column.name}_as_string(default_value)
           value = self.#{column.name}.to_s
           value.blank? ? default_value : value
          end

        EOF

      end

    end
  end

If you run your tests now, they all pass. But our work isn't done - this isn't very DRY. We may want to use this in another class too.

Modules!

Create a new module and mix the behavior into your models. Create the file lib/active_record/as_string_reader_methods.rb (create the active_recordfolder if it doesn't exist already) and put this code in the file:

  module ActiveRecord
    module AsStringReaderMethods
     def self.included(base)
       create_string_readers(base)
     end

     def self.create_string_readers(base)
      base.columns.each do |column|

         if column.type == :boolean

           class_eval <<-EOF

             def #{column.name}_as_string(t,f)
               value = self.#{column.name}
               value ? t : f
             end

           EOF
         else

           class_eval <<-EOF

             def #{column.name}_as_string(default_value)
               value = self.#{column.name}.to_s
               value.blank? ? default_value : value
             end

           EOF
         end
       end
     end
    end
  end

It's mostly the same code we had before, but in this case we're using the self.included method to trigger the method creation on the model that includes the module.

Now, remove the code from your Project mode and replace it with

include AsStringReaderMethods

Run your tests, and everything should pass. You now have a module you can drop into your projects and you'll have this functionality yourself. Now it's up to you to expand upon this, and use this pattern in your own work if you find it useful.

Good luck!

Rails and SQL Server – “There is no text for object”

Posted by Brian in Howto, Rails, tips (February 23rd, 2010)

I recently moved a Rails application to a new SQL Server 2005 server on a recent project and everything seemed to go smoothly, but when I tried to fire up a connection to the database from my Rails application, I was greeted with

ActiveRecord::StatementInvalid: DBI::DatabaseError: 42000 (15197) [FreeTDS][SQL Server]There is no text for object 'people'.: EXEC sp_helptext people

The “people” table here is actually a view that gets used all over the place in multiple applications. The DBA had moved the databases from an older SQL Server 2000 database previously.

The solution was to ensure that the application’s user account had the “view definition” permission on the view in question as well as the “select” permission. On the view, in the SQL Server Management Studio, right click and choose “Properties”. Then choose Permissions select your user account, and then select the “View definition” permission. Checking the box under the “Grant” column was enough for me to make it work.

Interestingly enough, the production server (which was upgraded months ago from SQL Server 2000 to 2005), does not have the permission set, but still works fine.

Hopefully someone else finds this useful.

Why Rails?

Posted by Brian in News, Rails (February 16th, 2010)

NAPCS was a proud sponsor of the first Chippewa Valley Ruby Camp, a day-long Ruby training camp where 23 students learned how to build and deploy their first Rails application. I taught two of the three sessions and had a great time helping other developers get their hands on what I believe to be the best way to develop scalable, maintainable, and stable web applications today. That’s a pretty bold statement, but I believe in it, and it’s why NAPCS uses Rails on all new client projects. (In fact, every project since 2006 has been a Rails project.)

Rails projects are quick to launch

With Rails, we can build and launch a prototype application in an extremely short time. On average, we can have something simple in front of the client in less than a couple of days, which is much faster than our previous projects where we used ASP or PHP. And that project isn’t usually a throwaway project; we can tweak it and move forward, from prototype to production.

Rails applications are easily testable

Professionals write tests that prove the code works as it should, and since testing is built right in to the Rails framework. testing is an easy natural part of the process. Testing has always been possible regardless of the language used, but with Rails, it’s so easy to produce well-tested code that you’d be foolish not to test. For my customers, that means much better products, and less support calls.

It’s a standard framework

I occasionally pick up projects from other developers, and while I can’t always ensure that the quality of the code will be good, I at least already know my way around the project because, in a Rails application, conventions dictate where things go. This means the learning curve is lower when we transition an application, and the customer doesn’t get billed extra time for me to figure out what’s going on.

The community is incredible

We rely heavily on open-source projects to get stuff done, and Rails has an amazing community that is always pushing the limits of what Rails applications can do. There is a new solution to a new problem almost every day, and that keeps us all on our toes. Plus, we’re very proud to be sponsoring the Rails Mentors project, which helps other developers get better at Rails development. We’re always giving back to open source, too.

It gets out of the way.

This is the most important point of all; Rails lets me deliver features. Instead of spending hours wiring up database tables to web pages, I can do that in five minutes and spend more time focusing on user experience and new features. And since it isn’t difficult to build things incrementally, I don’t get boxed in. I can make changes without feeling that I’ll lose days of work. It allows me to respond flexibly to new feature requests.

Rails gives us a competitive advantage. We cannot always compete on price alone, but we can provide better-quality solutions than others because we embrace an open, agile framework that lets us deliver stable, scalable, well-tested, and maintainable web applications.

Want to learn how you can take advantage of Ruby on Rails?

Contact us for information on customized training and mentoring services. We offer affordable hourly rates for remote mentoring, as well as custom training classes upon request.

Next Page »