The HTTParty has just begun
After releasing the new RubyURL API, I decided that it was time to look around at libraries to interact with it. I came across a new Ruby gem from John Nunemaker named, HTTParty, which aims to make it easy to talk to XML and JSON-based web services. Be sure to read John’s announcement of HTTParty.
So, I decided it might be fun to introduce more people to the gem by showing you all how to use it to talk to the new RubyURL API.
Install HTTParty
Before we get started, you’ll need to install the HTTParty gem with the following command:
~ : sudo gem install httparty
Password:
When you HTTParty, you must party hard!
Successfully installed httparty-0.1.6
1 gem installed
Installing ri documentation for httparty-0.1.6...
Installing RDoc documentation for httparty-0.1.6...
Great! Now that we’re ready to party hard, let’s build something.
Talking to the RubyURL API
The RubyURL API currently supports both XML and JSON, which are each supported by HTTParty. The great thing about HTTParty is that all you need to do is include it in a class and you’re able to quickly talk to remote services.
In this following example, we’re going to create a new class called Rubyurl
.
class Rubyurl
end
What we’ll want to do now is include the HTTParty library. (note: you’ll need to require both rubygems and httparty gems and I’ll skip those lines in following code samples)
class Rubyurl
include HTTParty
end
The HTTParty provides a few class methods, which we can use to configure our library. We’ll go ahead and specify the base_uri
, which we’ll set to rubyurl.com
.
class Rubyurl
include HTTParty
base_uri 'rubyurl.com'
end
Now that our class is setup to talk to the Rubyurl.com site, we’ll want to add a new method which we can use to communicate with the RubyURL API. We’ll call this shorten
as we’re using RubyURL to shorten long URLs… right?
class Rubyurl
include HTTParty
base_uri 'localhost:3000'
def self.shorten( website_url )
end
end
Our new shorten
method will expect us to provide it with a website url, which we’ll want RubyURL to return a shortened URL for. The PATH for the API that we’ll want to talk to is: /api/links
, which we’re expected to pass XML or JSON to.
Here are two examples of using the RubyURL API with HTTParty.
RubyURL via JSON w/HTTParty
We’re going to use the post
method that is provided with HTTParty to send a request to /api/links.json
. As you can see, we’re providing the original website url to the web service.
class Rubyurl
include HTTParty
base_uri 'rubyurl.com'
def self.shorten( website_url )
post( '/api/links.json', :query => { :link => { :website_url => website_url } } )
end
end
When ran, it’ll produce the following:
>> Rubyurl.shorten( 'http://github.com/jnunemaker/httparty/tree/master/lib/httparty.rb' ).inspect
=> {"link"=>{"permalink"=>"http://rubyurl.com/uJVu", "website_url"=>"http://github.com/jnunemaker/httparty/tree/master/lib/httparty.rb"}}
Pretty simple, eh?
RubyURL via XML w/HTTParty
The great thing about HTTParty is that you can use XML without changing much.
class Rubyurl
include HTTParty
base_uri 'rubyurl.com'
def self.shorten( website_url )
post( '/api/links.xml', :query => { :link => { :website_url => website_url } } )
end
end
Produces the following
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<link>
<website_url>http://github.com/jnunemaker/httparty/tree/master/lib/httparty.rb</website_url>
<permalink>http://rubyurl.com/uJVu</permalink>
</link>
Closing thoughts
So… there you have it. HTTParty makes it extremely easy to interact with various web services that work over HTTP. I’d encourage you all to take a few minutes to experiment with it and see what crazy ideas that come to mind during the process. :-)
Lesson Learned: Git Ref Naming
Our team has been working our way into the Git world. One of our big client projects is now 100% git while the other is still on Subversion for another month or so. (I’m getting by with git-svn, the gateway drug on that). We’ve had pretty much nothing but success with Git for quite some time, but recently this repository started to get chaotic, which has eaten up time… which isn’t conducive to productivity.
So, I wanted to share a quick lesson that we learned today after scratching our head for a while. It’s important that you avoid having a branch on a remote repository that shares the name of a tag in your local and/or remote repository.
I REPEAT.
It’s bad mojo to have a tag and branch share the same name. Things that you’d expect to just work... don’t. This was causing us to see warnings and errors like the following, which we weren’t really sure what to make of it.
“warning: refname ‘staging’ is ambiguous.
“error: src refspec staging matches more than one.”
This started about two weeks ago when we started a few new remote branches: staging and design. It seemed to be going okay but we managed to muck up things when we merged those two together and some of us were having success fetching/pulling/pushing to staging and others were having to specify :heads/staging
and couldn’t have a local branch named staging. Needless to say, it was causing some problems and slowing us down.
This afternoon, we finally noticed in the GitHub interface that there was a tag named staging
. Hmm… interesting. We verified this by using git show-ref
.
git:(master): git show-ref | grep staging
6a18119ca9.... refs/heads/staging
82caa5f121.... refs/remotes/origin/staging
6a18119ca9.... refs/tags/staging
Notice the tag reference at the end? After asking in #git, we were able to remove the tag with the following:
git tag -d staging
Then we needed to remove the reference of staging
on Github with git push origin :staging
. (we got rid of the remote branch temporarily as well so that we could clean this up).
The next step was to push our local branch back out to the remote branch git push origin staging:staging
.... and now we’re back in business with a simple:
git checkout --track -b staging origin/staging
Anyhow, if you end up having those warnings/errors above, you might take a look at git-show-ref to see what is in your local repository as this could be causing you some unnecessary headaches.
Kudos to Allison for taking the time to really read and digest the git documentation, which helped us figure this shit out. :-)
Since we’re still learning to get around through things like this, if you have any more insight into this issue, feel free to help educate us a bit by sharing your wisdom in response to this post. :-)
RSpec: It Should Behave Like
I was going through an older project of ours and cleaning up some specs and noticed how often we were doing the same thing in several places. When we started the project, we didn’t get the benefits of shared groups. Now that we have some time to go through and update some of our older specs, I’ve been trying to take advantage of the features currently available in RSpec. One feature that I haven’t seen a lot of mention of by people is shared groups, so I thought I’d take a few minutes to write up a quick intro to using it.
To pick some low-hanging fruit, let’s take an all-too-familiar method, which you might be familiar with… login_required
. Sound familiar? Have you found yourself stubbing login_required
over and over throughout your specs?
describe Admin::DohickiesController, 'index' do
before( :each ) do
controller.stub!( :login_required )
Dohicky.should_receive( :paginate ).and_return( Array.new )
get :index
end
...
end
If you’re requiring that a user should be logged in when interacting with most of the application (as in the case of an administration section/namespace), you might want to consolidate some of your work into one shared specification group. The basic premise behind this is that you can write a typical describe
block and load it into any other spec groups that you need. For example, in our case, we’ll need to stub login_required
in several places. We can set this up in one shared group and reference it wherever necessary.
For example, here is what we’ll start off with.
describe "an admin user is signed in" do
before( :each ) do
controller.stub!( :login_required )
end
end
describe Admin::DohickiesController, 'index' do
...
However, the new describe block isn’t accessible from the block at the bottom of the example… yet. To do this, we just need to pass the option: :shared => true
as you’ll see in the following example.
describe "an admin user is signed in", :shared => true do
before( :each ) do
controller.stub!( :login_required )
end
end
Great, now we can reference it by referring to it with: it_should_behave_like SharedGroupName
. In our example above, this would look like:
describe "an admin user is signed in" do
before( :each ) do
controller.stub!( :login_required )
end
end
describe Admin::DohickiesController, 'index' do
it_should_behave_like "an admin user is signed in"
before( :each ) do
Dohicky.should_receive( :paginate ).and_return( Array.new )
get :index
end
...
end
describe Admin::DohickiesController, 'new' do
it_should_behave_like "an admin user is signed in"
before( :each ) do
@dohicky = mock_model( Dohicky )
Dohicky.should_receive( :new ).and_return( @dohicky )
get :new
end
...
That’s it! Pretty simple, eh? We can now reference this shared group in any describe blocks that we want to. A benefit to this approach is that we can make change the authentication system (say, we decide to switch it entirely and/or even just change method names, set any other prerequisites necessary when an admin is signed in), we’ll have a single place to change in our specs. (tip: you can put these in your spec_helper
file)
You can learn more about it_should_behave_like
and other helpful features on the RSpec documentation site.
If you have any suggestions on better ways of handling things like this, please follow up and share your solutions. I’m always looking to sharpen my tools. :-)
Update
In response, Bryan Helmkamp suggests that a better solution is to define a method in our specs like, for example: build_mock_user_and_login
. then calling it in our before(:each)
. So, maybe the approach above isn’t the most ideal method but I did wantt o draw some attention to it_should_behave_like
. I suppose that I need a better example.. another post, perhaps? :-)
Also, Ed Spencer has posted an article titled, DRYing up your CRUD controller RSpecs, which will introduce you mor to it_should_behave_like
.
Thanks for feedback people!
Related Posts
Learning Git without getting your SVN feet wet
Our team has been migrating towards using Git as our primary SCM. We have way too many Subversion-based projects and repositories to just do a clean switch over and not everybody on the team has had time to start playing with it. Baby-steps…
So, for those of us who want to use it day-to-day, we’re using git-svn.
Andy Delcambre has posted the first in a series of blog articles to help you pick up on using Git on Subversion-based projects. Check out his article, Git SVN workflow to get up to speed.
Also, if you’re on OSX and using Git… check out Justin Palmer’s new project, GitNub, which describes itself as, “a Gitk-like application written in RubyCocoa that looks like it belongs on a Mac.” This looks promising. :-)
Get to Know a Gem: Rak
A few months ago, I posted about an article that showed you how to colorize your grep search results. Since then, I’ve heard people talking about ack, which describes itself as…
“a tool like grep, aimed at programmers with large trees of heterogeneous source code.”
It’s written in Perl, which is fine and dandy… but before I installed it, I heard that there was a Ruby version named rak, which describes itself as…
“a grep replacement in pure Ruby. It accepts Ruby syntax regular expressions and automatically recurses directories, skipping .svn/, .cvs/, pkg/ and more things you don’t care about. “
Sounds great. Let’s see what this thing can do.
Installing rak
Daniel Lucraft, the author of rak, was kind enough to package it up as a Rubygem. So, all we have to do is install it via gem install rak
.
> sudo gem install rak
Password:
Bulk updating Gem source index for: http://gems.rubyforge.org
Successfully installed rak-0.8.0
Installing ri documentation for rak-0.8.0...
Installing RDoc documentation for rak-0.8.0...
~ >
Great, let’s move on.
Using rak
Now that it’s installed, we can use Rak by typing rak
from the command line. You’d typically want to run this from within the root of your application.
For example, basic usage would look like the following.
$ rak search-pattern
In my first test, I ran rak README
.
Immediately, I see a greater advantage to rak
over using grep
and that’s because it’s giving me line numbers for free, which takes remembering a few extra options with grep.
Like grep
, we can specify a specific path to search with. For example, we use a view helper named link_to_unimplemented
to help us track actions that aren’t implemented yet. Looking at a current project, I can run rak link_to_unimplemented app/views
and produce the following results.
I’m going to keep playing with it, but wanted to help get the word out. If you have any tips on using it, please share them in the comments. :-)
Multiple Database Connections in Ruby on Rails
We have a client that already has some database replication going on in their deployment and needed to have most of their Ruby on Rails application pull from slave servers, but the few writes would go to the master, which would then end up in their slaves.
So, I was able to quickly extend ActiveRecord with just two methods to achieve this. Anyhow, earlier today, someone in #caboose asked if there was any solutions to this and it prompted me to finally package this up into a quick and dirty Rails plugin.
Introducing… Active Delegate!
To install, do the following:
cd vendor/plugins;
piston import http://svn.planetargon.org/rails/plugins/active_delegate
Next, you’ll need to create another database entry in your database.yml
.
login: &login
adapter: postgresql
host: localhost
port: 5432
development:
database: rubyurl_development
<<: *login
test:
database: rubyurl_test
<<: *login
production:
database: rubyurl_servant
<<: *login
# NOTICE THE NEXT ENTRY/KEY
master_database:
database: rubyurl_master
<<: *login
At this point, your Rails application won’t talk to the master_database
, because nothing is being told to connect to it. So, the current solution with Active Delegate is to create an ActiveRecord model that will act as a connection handler.
# app/models/master_database.rb
class MasterDatabase < ActiveRecord::Base
handles_connection_for :master_database # <-- this matches the key from our database.yml
end
Now, in the model(s) that we’ll want to have talk to this database, we’ll do add the following.
# app/models/animal.rb
class Animal < ActiveRecord::Base
delegates_connection_to :master_database, :on => [:create, :save, :destroy]
end
Now, when your application performs a create
, save
, or destroy
, it’ll talk to the master database and your find
calls will retrieve data from your servant database.
It’s late on a Friday afternoon and I felt compelled to toss this up for everyone. I think that this could be improved quite a bit, but it’s working great for the original problem that needed to be solved.
If you have feedback and/or bugs, please send us tickets.