Close and Go BackBack to Viget

Tools of the Trade

Linux Distributions For Rails Hosting: Viget’s First Annual(?) Shakedown

Mark Cornick
Mark Cornick, Web Developer, July 18, 2008 0

Here at Viget, we’ve done a variety of Rails deployments for our many clients. Nearly all of these have been to dedicated Linux systems, and between those we’ve seen a number of different Linux distributions. Which distribution has what it takes to successfully run your application? This post compares four popular distributions’ support for the basic building blocks of a standard Rails stack, and provides some of our own advice and experience.

Continue reading "Linux Distributions For Rails Hosting: Viget’s First Annual(?) Shakedown"

Helper Testing Independence

Brian Landau
Brian Landau, Web Developer, July 07, 2008 0

Testing helpers is a topic we’ve covered a couple times already here on the Viget Extend blog. I’ve additionally submitted a patch to Rails for adding some helper assertions to ActionView and other helper related testing goodness. But until that gets accepted and committed, I thought I’d hold everyone over with a helper testing plugin.

Independently Testing Helpers

The main tenet here is that helper functionality should be tested outside of another context (i.e. the controller). To achieve that, we need to create helper tests that live independent of our other tests. As Justin pointed out, Rails actually provides a class to assist in this, ActionView::TestCase.

The plugin I’ve created has two generators that help in creating these tests. The first, helper_tests, can be used to generate tests for your existing helpers. It creates a test file for each helper in the test/helpers directory and a test method for each public helper method. You can also pass it a list of helpers you wish to generate tests for and it will skip those that you don’t name.

Usage:

> script/generate helper_tests [SampleHelper Admin::AnotherHelper ...]

The other generator, helper, creates a helper -- and a helper test for the name provided. It will also accept a list of methods for the helper and generate them, as well as tests for each one.

Usage:

> script/generate helper HelperName [methods ...]

All generated helper tests will be run with rake test now along with all the other tests. Also a rake test:helpers task is provided to run just the helper tests.

Bonus Assertions!

That’s right ... I’ve also rolled in assert_tag_in, assert_tag_not_in, assert_select_in, assert_hpricot_in, and assert_hpricot_not_in assertions to the ActionView::TestCase class. These work exactly like their ActionController counterparts, except for the Hpricot ones, of course. These work by simply passing them the HTML string, and either a CSS selector or a XPath selector. The method then looks for an element matching the selector.

In the future, I’d like to spiffy assert_hpricot_in up by making it more like assert_select but it’s still useful to all Hpricot lovers out there as-is.

The Helper Me Test plugin:

The plugin is up on GitHub: http://github.com/vigetlabs/helper_me_test/tree/master

The clone URL to install with: git://github.com/vigetlabs/helper_me_test.git

As always comments, suggestions, or whatever are welcome, as well as forking it and adding your own twist.

Announcing the ActionButton Plugin

Brian Landau
Brian Landau, Web Developer, June 19, 2008 1

When creating web application there’s often a need for single links that have a destructive or “unsafe” effect. In accordance with HTTP specs, GET’s (e.g. links) should not be used for this. The issues that 37signals had with unsafe links prove the importance of this.

This is also important if your application is RESTful. Rails offers a few good solutions, but none of them are ideal. There’s link_to_remote, but this requires the user to have JavaScript enabled and doesn’t allow for progressive enhancement. Then there’s submit_to_remote, which requires you to wrap it in a form tag yourself and also doesn’t allow for progressive enhancement. Last, you have button_to, which is almost ideal, but it uses a submit button that offers less options for styling than a button tag.

And this is where the idea for a button tag helper came in. (See this blog post for a good description of why the button element rocks). Thus, ActionButton was born.

With it, you can create a form with a single button element. The form can be set to point to any url just as you would with a normal form. The button and the form can have different id and class attributes, making them easy to target via JavaScript. But you don’t need to set these; by default it will create classes and ids that are sensible. Of course, all the normal HTML options are available, too.

The plugin will also install a modified version of the lowpro library. The ujs_remote_form helper provided creates a snippet of lowpro JavaScript that can be used to make a form (or set of forms) submit via an AJAX call.

So how would I use this?

Well, if you have a list of blog posts in an admin section and you want to add delete buttons next to each of them and you want them to look the same in every browser, this is how you would do it.

<%= action_button 'delete_post', "#{image_tag('icons/delete.jpg', :alt => 'delete')} Delete", 
post_url(post), {:method => :delete, :number => post.id} %>

Then when you’re ready for some AJAXy goodness, you can either use the Rails built-in helper of the plugin’s lowpro one:

Built-in:

Add this for each post:

<%= observe_form "delete_post#{post.id}-form", :on => 'submit', 
:confim => 'Are you sure you wish to delete this post?' %>

Lowpro:

Add this for the whole page of posts:

<%= ujs_remote_form 'button.delete_post', :confirm => 'Are you sure you wish to delete this post' %>

So where do I get this plugin of button joy?

It’s up on github right now!

If you have any questions, comments or suggestions, send them my way. It’s great to get feedback, but if you really feel I messed something up, just fork it and make the changes you feel it needs.

Announcing spect, a helping library for Test::Unit

Clinton R. Nixon
Clinton R. Nixon, Senior Developer, May 22, 2008 3

We've tried out a lot of test frameworks for Ruby here at the Lab. I have been a big fan of test/spec in the past, and like shoulda's nested contexts. test/spec's wrapped assertions - like user.should.not.be.nil instead of assert_not_nil user - are a particular feature I dig.

I wanted to use these with shoulda, and started to extend shoulda to have its own set of wrapped assertions, but when I looked in the test/spec code, I saw this beauty:

module Test::Spec
  class Should
    ...
    def add_assertion
      $TEST_SPEC_TESTCASE && $TEST_SPEC_TESTCASE.__send__(:add_assertion)
    end
    ...
  end

  class TestCase
  ...
    module InstanceMethods
      def setup                 # :nodoc:
        $TEST_SPEC_TESTCASE = self
        super
        call_methods_including_parents(:setups)
      end
    ...
    end
  ...
  end
end

I don't want to put down a piece of code I've used a lot and enjoyed, and I think this is a practical way for test/spec to handle increasing the assertion count for its wrapped assertions, since they all start with a method on Object. I, however, couldn't bring myself to use a global variable to handle this task. I thought for a while, and after being inspired by JDave, I decided to start with a method on Test::Unit::TestCase.

Announcing spect

I released my test library today as a Ruby gem called spect. It's very simple to use. Once you require spect, you can use the method expect in Test::Unit::TestCase or any derived classes, like a shoulda should block or a test/spec specify block. expect sets up expectations like the following:

expect(user).responds_to admin?
expect(user).is.an.admin
expect(user.name).to.not.match /mr_jenkins/
expect(user).to.be.equal User.find(:first)
expect(user).is.not.not.not.not user
expect(ZeroDivisionError).raised_by do
  user.id / 0
end

Most of the Test::Unit assertions are wrapped, with the following mappings:

  • assert_equal is equal
  • assert_in_delta is close_to
  • assert_match is match
  • assert_nil is nil
  • assert_respond_to is respond_to
  • assert_same is same
  • assert_raise is raised_by
  • assert_throws is thrown_by

In addition, all predicates on an object can be tested for truth by calling them per normal (admin?) or by dropping the question mark (admin.)

There are several methods used solely for grammatical purposes. to, an, and a are no-ops and just return self. is and be are no-ops unless they are passed an argument, in which case they assert equality between the original object and this argument. not reverses assertions, but also can be passed an argument to assert inequality.

I am sure there are a lot of improvements to make. I thought of one writing this blog post (equal_to should be an alias for equal.) I invite you to check out the code at our GitHub repository and submit patches.

From TextMate to ExpressionEngine

Patrick Reagan
Patrick Reagan, Development Director, May 01, 2008 10

Between writing code, documentation, and blog posts, I spend a lot of my time working in TextMate. It's an efficient text editor, but it becomes a bit of a headache when it's time to work on a new blog post. The real problem is my process:

  1. Open TextMate and start collecting my thoughts for a post in some cohesive fashion (optional)
  2. Finalize most of the content and basic formatting
  3. Copy the content into ExpressionEngine, tweak the formatting, add hyperlinks
  4. Preview the post and publish to the site

The reason for all this masochism is my dislike for editing content in a web-based form, WYSIWYG or otherwise. I love my editor enough that I'm willing to jump through some hoops in order to use it for the bulk of my editing work. But, there's a better way to do all this.

Continue reading "From TextMate to ExpressionEngine"

A Development Community for Viget Labs and Beyond

Every team member here at Viget Labs strives to be an innovator. We members of the development team are no different - that's why we're constantly engaging in community discussions and exploring the unknown that is the next generation of open-source web applications.

Viget Is Hiring!

Viget has job openings for Ruby Developers, Interns, and Front-End Developers. Learn More »

Upcoming Events

O’Reilly’s Open Source Convention - July 21 - 25
Clinton R. Nixon, our other Senior Developer, will be speaking on "Extending Rails: Understanding and Building Plugins."

Recent Comments

Smashing! Thanks for outlining what’s needed to be done so precisely :-)