Search posterous

Search all posts and users. Type a name, type a favorite song title, whatever! See what comes up.
  

More posterous blogs











More recommended blogs »

Here are posterous posts filed under ruby...

Since discovering Twitter a few years ago, we have been massive fans of the Ruby on Rails framework. It's clean, flexible, scalable, and extremely easy to use. We've watched as other agencies have built some fantastic apps which are being used all over the world. In that time, I personally have bought book after book with no real time to learn from them. Time has now finally been set aside each day to tackle the great subject. This will hopefully enable us to offer a back-end development service within the agency.

Coming from a non programmer background it has been hard to grasp aspects of programming, the shear size of the task has been off-putting. In the past I have tackled Asp, then Asp.Net with neither sinking in. Ruby & Rails on the other hand is different. In the short time i've been dabbling with the idea of learning i've been able to understand the Rails framework, MVC architecture, the DRY & Convention over Configuration terms so knew this was a language and framework I could get on with. Rails just makes sense.

What is clear though, in order to get the most from Rails, not only understanding what is happening but also to know how to alter code nested deep within the framework, I will need to know Ruby. Pretty obvious really, Rails is written in Ruby, when you write Rails code you are in effect writing Ruby code. So putting my impatience aside I intend to start with Ruby and work towards Rails.

The first book from the agency library, Ruby for Rails. This book looks like the perfect starting point to work from Ruby to Rails with that goal in mind. Along the way I intend to put the coding examples into practice by creating one or more small web apps. I haven't decided what yet though. If anyone has done a similar thing and wants to suggest a small app or two, i'd welcome the suggestion.

Finally, I have just decided where I can I will write an article or two as I go through the put, trying to document my understanding of the chapter, code example, Ruby or Rails term.

Filed under: Ruby

Shayne says...

Threw this together real quick. I think someone could expand on this by creating playlists, on the fly (GrooveShark, Lala) or even track popularity. Anyways, just a few minutes of fun...

Filed under: ruby

timocratic says...

So my buddy Tammer's recent post about the Gang of Four's Template Pattern reminded me of some code I saw recently. A start-up's greenfield project had it's authorization done in a pretty clean way using the template pattern. Basically every object determined what could be done to it, something like this:

After continuing this approach to fully cover CRUD you make a straight-forward set of accessors that can be used to easily enforce permissions in the controller in a programmatic way (this project was using on of the inherited resourceful-controller plugins, so that was a big plus). The developer who implemented this commented that the trade-off for this simplicity was having to look in each individual model file to figure out what a user can do overall.

I figured I liked everything about this scheme except that trade-off, and since ruby is so dynamic, why settle for almost. Why not just reopen each class in the authorization file and add the methods. You still get the simplicity and encapsulation of having the model able to determine it's own permissions, based on it's state and methods, and there is still one place to look to review/change the permissions for the whole project:

Thoughts?

Filed under: ruby

bry4n says...

R A I N


What it does?

It can fetch a copy of file, project, application, framework, gem, tarball, zipball via git or downloadable URLs.  Lazy way to get them! It can be pretty handy for your productivity, development, etc ...


How does it handle platforms?

It is using two tools called "git" and "curl". These tools are required to install in order to run RAIN properly.

 

How to install them on Ubuntu? apt-get is installed by default in any debian based distros

sudo apt-get install git-core curl

 

What about OSX? macport is required to install. Grab it at http://www.macports.org/install.php (please follow the macports' instruction how to install it properly)

sudo port install git-core curl

 


How to use it?

 

To display the help screen

rain help


To add application with a source URL (specify the name and actual URL address)

rain add mustache -s git://github.com/defunkt/mustache.git

rain add yard-gem -s http://rubyforge.org/frs/download.php/67247/yard-0.4.0.gem

rain add pystache-tarball -s http://github.com/defunkt/psytache/tarball/master

rain add rails-rf -s http://rubyforge.org/frs/download.php/60599/rails-2.3.3.tgz


You can create a bundle name with multiple names or multiple URLs by seperating them with a comma without space and gap


Examples:

 

To create a bundle name with multiple application names from the list

rain add rails-bundle -s mustache,yard-gem,rails-rf

 

To create a bundle name with multiple URLs

rain add rb-urls -s git://github.com/defunkt/mustache.git,http://rubyforge.org/frs/download.php/67247/yard-0.4.0.gem


Check the list of names and URLs you added

rain list


Screenshot of "rain list"


Install gem

sudo gem install rain


More features, examples, wiki pages can be found at http://wiki.github.com/bry4n/rain/

Gemcutter page: http://bit.ly/rain-gem

Github page: http://bit.ly/rain-git


Rain is an open source. You can fork it and contribute it. Suggestion/Recommendation is acceptable. I might apply your changes/requests. Just let me know.

 

 

 

Filed under: ruby

kevinvaldek says...

Filed under: ruby

rorviswa says...

Class methods are methods that are called on a class and Instance methods are methods that are called on an instance of a class.

Below is the Example describing it.

class Language
   def self.name
       puts "Hi Ruby this is a class method"
   end

   def program
       puts "Hi Ruby this is a instance method"
   end
end

Language.name     # => "Hi Ruby this is a class method"
Language.program # => "undefined method `program' for Language:Class (NoMethodError)"

Language.new.program  # => "Hi Ruby this is a instance method"
Language.new.name      # => "undefined method `name' for #<Language:0xb7d7aa0c> (NoMethodError)"

What is the difference in the above code?

"name" is the class method so calling name on the Language class works fine. "program" is an instance method so calling program on Language class raises Nomethod Error. Similarly the next set of code we called the methods on the instance of a class.

We can represent the class methods in three ways.They are described below

1)   class Language
         def self.name
            puts "Ruby"
         end
      end

      Language.name # => "Ruby"

2)   class Language
         class << self
            def name
               puts "Ruby"
            end
         end
      end

      Language.name # => "Ruby"

3)   class Language        
      end

      def Language.name
            puts "Ruby"
      end

      Language.name # => "Ruby"

We can also represent the instance method in three ways. They are described below

1)   class Language
         def name
             puts "Ruby"
         end
      end

      Language.new.name # => "Ruby"

2)   class Language
         attr_accessor :name                    
      end
 

      language = Language.new
      language.name = "Ruby"
      language.name # => "Ruby"

3)   class Language        
      end

      language = Language.new

      def language.name
            puts "Ruby"
      end

      Language.new.name # => "Ruby"

Filed under: Ruby

choonsiong says...

Okay, it is pretty straight forward to update your gem.

  1. Download the latest gem package (rubygems-update-1.3.5.gem) here.
  2. Issue the following commands:
    # gem install rubygems-update-1.3.5.gem
    # update_rubygems
  3. And verify:
    # gem -v
    1.3.5
  4. Cool!
And you don't know what gem is? Read it here.

Filed under: Ruby

bry4n says...

You will know why I am smiling... :-)

Filed under: ruby

kishyr says...

Filed under: ruby

Nash says...

I must say that Ruby Best Practices is the best book I've had the pleasure of reading when it comes to Ruby. It's aimed at intermediate to advanced developers.

One of the best features of this book is that it reaffirms things that you sorta know, but you're not so sure about. It materializes techniques and concepts so when they come up again, you will solve them with confidence knowing that it's the Ruby way.

Chapter One, Driving Code Through Tests, is a lite overview of TDD. It covers many nice concepts that come up during testing.


Designing for Testability

Many times, when I'm writing tests, I get to some point where I have to change my code in order to make the test easier or cleaner. I always had a huge gut resistance to doing so. Why should I have to change my code so my tests are easier or better. It should be the other way around! Needless to say, this has created some really nasty tests and kept my code as it is.

Well, I was doing it wrong. It's perfectly OK to make your code easy to test. In fact, it makes your code better. As Gregory refactors the Questioner class, it becomes obvious that by designing for testability the final iteration of the code is much more readable and also extensible. You can now interchange input and output with anything that quacks like a stream.


Progressive Tweaking

One thing I hate about writing tests is when I get to a point where I have to rewrite the last few tests because of an interface change. It feels tedious and painful. Especially when I'm about 10 specs into a feature. But I feel that way, because I fail to see the advantage.

What is really happening is that I'm enhancing my code instantaneously instead of doing a big refactor in the future. I'm paying an upfront cost, but in the long run, I'll probably make up for it. Hopefully.


Mocks & Stubs

I've shot myself in the foot with mocks. Their problem is that they create tight coupling with the current state of your code and your tests. So you find yourself changing your tests every time you want to enhance your code without changing it's behavior, interface, or outcome. Which I think is really bad. Gregory actually mentions that when he switches from suing StringIO to mocks in the Questioner class.

I think mocks should be used when the code being tested depends on some external code or some other library which you don't want to include into your isolated tests. In Rails, I only use them when my model expects some other model (not being tested) to be present. Otherwise, I use the actual models themselves.

Another benefit of mocks is when you want to create an interface, but really not sure about how to proceed. They are a good starting point to start coding before replacing them with the real object.


Complex Output

One thing mentioned that I"m guilty of is sticking complex output in my tests as a string, then making sure that that string matches some output from my object. It makes my test look ugly, but it's fast and it gets the job done. That's until you make some tiny change and all tests that depended on that string now fail. It's an annoying problem and Gregory's recommendation is to use a parser that consumes the output. After the output is loaded in the parser you can actually test the individual field values. It makes tons of sense.

For example, I recently wrote a module that allows you to convert a vehicle object into a csv line.

class VehicleListing
  include Zipzoomauto::VehicleCsvFormatter

  formatter :source => :my_source
 
  def my_source
    return SomethingWithAVehicleInterface.new
  end

end



Here's how I test it (tons of code truncated):

module Zipzoomauto::VehicleCsvFormatterHelper
  def default_csv
     "JH4DC4456YS002646,2095,2000,Acura,Integra,LS Coupe,5850.0,83499,Green,Grey,Hatchback,1.8L L4 DOHC 16V,Automatic,Air Condition;Alloy Wheels;Anti-Lock Brakes;Tinted Glass,This is the type of car that you'll be proud to own or give as a gift.  Only 83K Miles!,http://www.myusedcardealer.com/alpha/files/26/24/vehicles/4813/74874/large/100_4979.jpg;http://www.myusedcardealer.com/alpha/files/26/24/vehicles/4813/74874/large/111_4989.jpg\n"
   end
end

describe Zipzoomauto::VehicleCsvFormatter, "converting a vehicle to csv" do
  include Zipzoomauto::VehicleCsvFormatterHelper

  it "should convert a vehicle to csv starting with vin and ending with photo" do
     vehicle_listing = VehicleListing.new
    vehicle_listing.to_csv.should == default_csv
  end

end


but the better way to test it this is like so:

  it "should convert a vehicle to csv starting with vin and ending with photo" do
     vehicle_listing = VehicleListing.new
     row = FasterCSV.parse(vehicle_listing.to_csv).first
    row[0].should == "some expected result"
    row[1].should == "some ohter expcted result" 
   end
 


This gets rid of having an ugly string in the test, but more importantly verifies the expected result.

Conclusion

I would say the first chapter is a very lightweight overview of testing. My favorite part is the Questioner class and how it was completely driven by tests. How when things got ugly, Gregory simply refactored both the code and tesst until he ended up with a far better result. Discover problem, refactor, iterate...


Things I Didn't Know



SomeClass = Class.new(SomeOtherClass)


is actually a shortcut to:

class SomeClass < SomeOtherClass; end;

nice!

StringIO has a rewind function that positions the cursor(?) to the begenning of input so when you call gets after rewind, you could fake user input. For example:



s = StringIO.new
s << "hi\n"
s << "there\n"
s.gets #=> nil
s.rewind #=> 0
s.gets #=> "hi\n"
s.gets #=> "there\n"


Filed under: ruby