Discussion: Lecture 12

November 23rd, 2009 Leave a comment Go to comments

Add comments here with questions and notes regarding Lecture 12.

Here’s the complete REST client; I’m still working on cleaning up the server, but this is the key bit:

# Quick REST client demo
# To clear out old data:
#   rake db:drop db:migrate
#
require 'rubygems'
require 'activeresource'

class Publication < ActiveResource::Base
  self.site = 'http://localhost:3000'
  self.user = 'john@7fff.com'
  self.password = 'aaaa'
end

class Annotation < ActiveResource::Base
  self.site = 'http://localhost:3000'
  self.user = 'john@7fff.com'
  self.password = 'aaaa'
end

def dump_publications
  Publication.find(:all).each_with_index { |p, i| puts "  #{i}. #{p.title}" }
end

puts "Publications at start:"
dump_publications

c_book_title = 'The C Programming Language'
p = Publication.new(:title => c_book_title)
p.save

puts "Publications after adding one:"
dump_publications

if Publication.find(:first, :params => { :title => c_book_title})
  puts "There is a book named #{c_book_title}"
end

annotations = Annotation.find(:all, :from => '/publications/1/annotations.xml')
annotations.each_with_index { |a, i| puts "  #{i}. #{a.title}" }

And here is the monkeypath to get Clearance to use basic auth for REST requests; put this in your config/initializers directory under any name; I used resful_clearance.rb. This is “the simplest thing that could actually work”; we don’t do anything special to produce a “nice” error for the client that fails to authenticate.

module Clearance
  module Authentication
    module InstanceMethods
      def authenticate_with_rest
        if params[:format] == 'xml'
          authenticate_or_request_with_http_basic do |email, password|
            if current_user = ::User.authenticate(email, password)
              return
            end
          end
        end
        authenticate_without_rest
      end
      alias_method_chain :authenticate, :rest
    end
  end
end
  1. Ron Newman
    December 10th, 2009 at 15:20 | #1

    What am I doing wrong here?

     irb
    irb(main):001:0> require 'activeresource'
    => true
    irb(main):002:0> class Publication < ActiveResource::Base
    irb(main):003:1> self.site = "http://publications.plugh.org"
    irb(main):004:1> end
    => "http://publications.plugh.org"
    irb(main):005:0> Publication.find(:all)
    NoMethodError: undefined method `use_ssl' for #<Net::HTTP publications.plugh.org:80 open=false>
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/connection.rb:191:in `http'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/connection.rb:149:in `block in request'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activesupport-2.3.3/lib/active_support/core_ext/benchmark.rb:17:in `block in ms'
    	from /Users/ronnewman/.ruby_versions/ruby-1.9.1-p243/lib/ruby/1.9.1/benchmark.rb:309:in `realtime'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activesupport-2.3.3/lib/active_support/core_ext/benchmark.rb:17:in `ms'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/connection.rb:149:in `request'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/connection.rb:116:in `get'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/base.rb:576:in `find_every'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/base.rb:519:in `find'
    	from (irb):5
    	from /Users/ronnewman/.ruby_versions/ruby-1.9.1-p243/bin/irb:12:in `<main>'
    
  2. December 10th, 2009 at 16:41 | #2

    @Ron Newman

    From your Mac?

    Um . . . I know that on Linux it is possible to get your Net::HTTP screwed up, but I haven't seen this on a Mac. I would resort to the Google . . .

  3. December 10th, 2009 at 16:51 | #3

    @Ron Newman

    Haven't tried it from irb, but this works on my Mac as a separate program:

    require 'rubygems'
    require 'activeresource'
    class Publication < ActiveResource::Base
      self.site = "http://publications.plugh.org"
      self.user = 'e168f09'
      self.password = 'zzzzzzzzzz' # put in the pw
    end
    p Publication.find(:all)
    
  4. Ron Newman
    December 10th, 2009 at 17:00 | #4

    I get the exact same error if I run that program (whether or not I change the password to the correct one).

    Oddly, it works fine if I switch to Ruby 1.8.7.

  5. December 10th, 2009 at 17:06 | #5

    @Ron Newman

    Works for me under 1.8.6, 1.9.1.

  6. Ron Newman
  7. December 10th, 2009 at 17:58 | #7

    @Ron Newman

    No idea, but that should be a very easy monkeypatch . . .

  8. Ron Newman
    December 16th, 2009 at 22:00 | #8

    Apparently it's a very bad idea to specify :skip_types =>true when calling .to_xml on an array of ActiveRecord model objects. Doing so causes the ActiveResource client to complain cryptically:

    /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/base.rb:599:in `instantiate_collection': undefined method `collect!' for #<Hash:0x1202be8> (NoMethodError)
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/base.rb:576:in `find_every'
    	from /Users/ronnewman/.gem/ruby/1.9.1/gems/activeresource-2.3.3/lib/active_resource/base.rb:519:in `find'
    	from ./courses_client.rb:20:in `<main>'
    
  9. December 16th, 2009 at 22:28 | #9

    @Ron Newman

    Wow.

    If you want to get info from a resource in a "typeless" fashion, you should check out HttParty.

  10. Ron Newman
    December 16th, 2009 at 22:45 | #10

    By the way, here's the monkeypatch for the use_ssl problem. Still don't understand why I needed it and you didn't ....

    # See https://rails.lighthouseapp.com/projects/8994/tickets/1272-ruby19-incompatibility-activeresourceconnectionhttp-use_ssl
    class Net::HTTP
      unless instance_methods.include?('use_ssl')
        alias use_ssl use_ssl?
      end
    end
    
  1. No trackbacks yet.