santiago.pastorino

Rails for API applications (rails-api) released 9

Posted by santiago.pastorino
on Saturday, April 21

rails-api is a plugin developed by Yehuda Katz, José Valim, Carlos Antonio da Silva and me (Santiago Pastorino) which modifies Rails applications trimming down usually unneeded Rails functionalities for API applications. Do you remember we added support for this on core and it was reverted?. This plugin enables that again.

What is an API app?

Traditionally, when people said that they used Rails as an "API", they meant providing a programmatically accessible API alongside their web application. For example, GitHub provides an API that you can use from your own API clients.

Why using this instead of Rails?

Because you don't need the entire Rails middleware stack. Specifically you won't need middleware that are meant for browser applications. For example you probably won't need cookies support, but you can add that back if you want. You don't need most of the functionality provided by ActionController::Base like template generation for instance. And you won't need generated views, helpers and assets. The plugin also skips the asset pipelining.

Configuration

For existing Rails applications you need …

  1. To add gem 'rails-api' to your Gemfile
  2. Make ApplicationController inherit from ActionController::API instead of ActionController::Base. As with middleware, this will leave out any ActionController module that provides functionality primarily used by browser applications.
  3. Remove respond_to from your controllers and just use render :json instead.

For new apps

Install the gem if you haven't already:

gem install rails-api

Then generate a new Rails API application:

rails-api new my_api

And that's it, when you use the generators by default controllers will respond to json only.

Middlewares

An api application comes with the following middlewares by default.

  • Rack::Cache: Caches responses with public Cache-Control headers using HTTP caching semantics.
  • Rack::Sendfile: Uses a front-end server's file serving support from your Rails application.
  • Rack::Lock: If your application is not marked as threadsafe (config.threadsafe!), this middleware will add a mutex around your requests.
  • ActionDispatch::RequestId
  • Rails::Rack::Logger
  • Rack::Runtime: Adds a header to the response listing the total runtime of the request.
  • ActionDispatch::ShowExceptions: Rescue exceptions and re-dispatch them to an exception handling application.
  • ActionDispatch::DebugExceptions: Log exceptions.
  • ActionDispatch::RemoteIp: Protect against IP spoofing attacks.
  • ActionDispatch::Reloader: In development mode, support code reloading.
  • ActionDispatch::ParamsParser: Parse XML, YAML and JSON parameters when the request's Content-Type is one of those.
  • ActionDispatch::Head: Dispatch HEAD requests as GET requests, and return only the status code and headers.
  • Rack::ConditionalGet: Supports the stale? feature in Rails controllers.
  • Rack::ETag: Automatically set an ETag on all string responses. This means that if the same response is returned from a controller for the same URL, the server will return a 304 Not Modified, even if no additional caching steps are taken. This is primarily a client-side optimization; it reduces bandwidth costs but not server processing time.

Other plugins, including ActiveRecord, may add additional middlewares. In general, these middlewares are agnostic to the type of app you are building, and make sense in an API-only Rails application.

You can get a list of all middlewares in your application via:

rake middleware

Other Middlewares

Rails ships with a number of other middlewares that you might want to use in an API app, especially if one of your API clients is the browser:

  • Rack::MethodOverride: Allows the use of the _method hack to route POST requests to other verbs.
  • ActionDispatch::Cookies: Supports the cookie method in ActionController, including support for signed and encrypted cookies.
  • ActionDispatch::Flash: Supports the flash mechanism in ActionController.
  • ActionDispatch::BestStandards: Tells Internet Explorer to use the most standards-compliant available renderer. In production mode, if ChromeFrame is available, use ChromeFrame.
  • Session Management: If a config.session_store is supplied, this middleware makes the session available as the session method in ActionController.

Any of these middlewares can be added via:

config.middleware.use Rack::MethodOverride

Removing Middlewares

If you don't want to use a middleware that is included by default in the api middleware set, you can remove it using config.middleware.delete:

config.middleware.delete ::Rack::Sendfile

Keep in mind that removing these features may remove support for certain features in ActionController.

Choosing Controller Modules

An api application (using ActionController::API) comes with the following controller modules by default:

  • ActionController::UrlFor: Makes url_for and friends available
  • ActionController::Redirecting: Support for redirect_to
  • ActionController::Rendering: Basic support for rendering
  • ActionController::Renderers::All: Support for render :json and friends
  • ActionController::ConditionalGet: Support for stale?
  • ActionController::ForceSSL: Support for force_ssl
  • ActionController::RackDelegation: Support for the request and response methods returning ActionDispatch::Request and ActionDispatch::Response objects.
  • ActionController::DataStreaming: Support for send_file and send_data
  • AbstractController::Callbacks: Support for before_filter and friends
  • ActionController::Instrumentation: Support for the instrumentation hooks defined by ActionController (see the source for more).
  • ActionController::Rescue: Support for rescue_from.

Other plugins may add additional modules. You can get a list of all modules included into ActionController::API in the rails console:

ActionController::API.ancestors - ActionController::Metal.ancestors

Adding Other Modules

All Action Controller modules know about their dependent modules, so you can feel free to include any modules into your controllers, and all dependencies will be included and set up as well.

Some common modules you might want to add:

  • AbstractController::Translation: Support for the l and t localization and translation methods. These delegate to I18n.translate and I18n.localize.
  • ActionController::HTTPAuthentication::Basic (or Digest or Token): Support for basic, digest or token HTTP authentication.
  • AbstractController::Layouts: Support for layouts when rendering.
  • ActionController::MimeResponds: Support for content negotiation (respond_to, respond_with).
  • ActionController::Cookies: Support for cookies, which includes support for signed and encrypted cookies. This requires the cookie middleware.

The best place to add a module is in your ApplicationController. You can also add modules to individual controllers.

How can I help?

Go to the project url https://github.com/spastorino/rails-api and report issues, test it in real apps and provide bug fixes. We have been measuring the plugin against some applications and we will post more about the results later. Meanwhile, if you can test it and share the improvements you found in your apps, would be awesome. To be able to add this functionality to core we need the plugin to show significant performance improvements for real API applications, so it's important to let us know about your results.

<3 <3 <3 Find me at RailsConf. Tenderlove and I are giving out hugs for free!

Update #1: Wycats who after working with us (South American rubyists) is known as wygatos (figure our why :P), is adhering to the campaign of giving hugs for free.

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

sebastian.martinez

My OS X Rails installation using Homebrew and rbenv, step by step 4

Posted by sebastian.martinez
on Friday, April 13

In this opportunity I’ll explain (as the title suggests) how to go from a brand new mac os x to running Rails tests.

Step 0, is to make sure that locale returns

LANG="en_US.UTF-8" 
LC_COLLATE="en_US.UTF-8" 
LC_CTYPE="en_US.UTF-8" 
LC_MESSAGES="en_US.UTF-8" 
LC_MONETARY="en_US.UTF-8" 
LC_NUMERIC="en_US.UTF-8" 
LC_TIME="en_US.UTF-8" 
LC_ALL=

(you’ll get some unexpected errors later on if not). To do so, you can either set the Language to one that Mac OS X sets UTF-8 by default, like United States from the System Preferences panel. Or, you can run

$ export LC_ALL=en_US.UTF-8
$ export LANG=en_US.UTF-8
to achieve that.

Step 1, install Xcode.

Step 2, install osx-gcc-installer from https://github.com/kennethreitz/osx-gcc-installer

Step 3, So now you’re ready to install Homebrew, by doing:

$ /usr/bin/ruby -e "$(/usr/bin/curl -fksSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)" 

Now this is how to install some common libraries

Step 4, We need to first have git in order run the brew doctor, so

$ brew install git

You can make sure that everything is ok by running

$ brew doctor
at any time. It should return ‘Your system is raring to brew’ when in optimal conditions.

Step 5, now to install the rest of the libraries

$ brew install memcached mysql postgresql

Step 6, initializing the mysql and postgres databases must be done by doing

$ initdb /usr/local/var/postgres
$ mysql_install_db --verbose --user=`whoami` --basedir="$(brew
--prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp

Step 7, I like having some aliases to load/unload mysql, postgres and memcached. To do so, you should add the following lines to your ~/.zshrc

alias memcached_load="launchctl load -w /usr/local/Cellar/memcached/1.4.13/homebrew.mxcl.memcached.plist" 
alias memcached_unload="launchctl unload -w /usr/local/Cellar/memcached/1.4.13/homebrew.mxcl.memcached.plist" 
alias mysql_load="launchctl load -w /usr/local/Cellar/mysql/5.5.20/homebrew.mxcl.mysql.plist" 
alias mysql_unload="launchctl unload -w /usr/local/Cellar/mysql/5.5.20/homebrew.mxcl.mysql.plist" 
alias postgres_load="launchctl load -w /usr/local/Cellar/postgresql/9.1.3/homebrew.mxcl.postgresql.plist" 
alias postgres_unload="launchctl unload -w /usr/local/Cellar/postgresql/9.1.3/homebrew.mxcl.postgresql.plist" 

Step 8, Now you’re good to go. Next we’ll install rbenv to easily switch between multiple versions of Ruby. You can also choose to use RVM or roll your own.

$ brew install rbenv ruby-build

Step 9, Add

export PATH=$HOME/.rbenv/bin:$PATH
eval "$(rbenv init -)" 
to your ~/.zshrc.

Step 10, now do the following to install ruby

$ rbenv install 1.9.3-p125

Step 11, you need to

$ rbenv global 1.9.3-p125
$ rbenv rehash

Step 12, Cool, so now we are good to go and setup Rails.

$ git clone https://github.com/rails/rails.git
$ gem install bundler
$ cd rails
$ bundle

Step 13, now, from the Contributing to Rails Guide, you should

$ mysql_load
$ postgres_load
$ mysql -u root
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost';
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest2.* to 'rails'@'localhost';
exit
$ cd activerecord
$ rake mysql:build_databases
$ rake postgresql:build_databases

And that’s it!, we have Ruby, MySQL, PostgreSQL, Memcached, and everything needed to do some Rails development.

Step 14, we need to load Memcached for its needed for some tests by doing

$ memcached_load 

Step 15, and lastly, you can run Rails tests by doing

$ rake
at the top of the rails directory.

Everything should work just fine, or at least you should get the same results as the Rails CI.

Congratulations!

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

santiago.pastorino

bundle exec rails … executes Bundler.setup 3 times 9

Posted by santiago.pastorino
on Tuesday, December 27

TL;DR: don’t run bundle exec before rails command, rails already checks the presence of Bundler through the Gemfile and sets up everything according to it without the overhead of bundle exec. rails command is the only exception to the rule. Additionally I’ve added a patch to Bundler that avoids calling Bundler.setup which adds unnecessary overhead.

I was researching on a huge Bundler 1.1 performance regression, @masterkain was hitting when running bundle exec rails runner ’’ (you shouldn’t run bundle exec before the rails command, but keep reading for now). I started to profile it using ruby-prof and one of the things I realized was that Bundler.setup (which is a considerable slow method because it calls Bundler::Runtime#setup) was ran 3 times. My first reaction was WTF?? 3 times??. I will write about my other findings in another blog post.

After analyzing the code, I found out that the first call to Bundle.setup is in Bundler::CLI#exec right before shelling out to run rails runner ’’. The second call is on boot.rb as part of the boot process (well actually it’s required from bundle exec through this rubyopt and on boot.rb the require returns false because it’s already required). And the last call starts on config/application.rb which ends up calling Bundler.require to finally call Bundler.setup for the third time. The second and third calls are run on the same process so Bundler.setup caches the result in @setup so there’s no slow down between those 2 calls. But the command passed to bundle exec runs in a different process (remember I said before that we were shelling out to run rails runner ’’) so the resulting execution of the first Bundler.setup won’t be available to the “rails runner process” and doesn’t make any sense. All that bundle exec needs to do is to setup the rubyopts needed to run the command you are passing to bundle exec. I’ve patched Bundler to do the right thing.

So don’t run bundle exec before rails command, this command is already aware of Bundler and sets up everything according to what you have on your Gemfile. If you prepend bundle exec before rails command all you will be adding is overhead of opening another process from Bundler and executing useless code since rails already does the right thing.

You probably already know about that, but I’ve seen a lot of proficient Rails developers doing it.

Read more about the topic in Yehuda’s blog

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

santiago.pastorino

Ruby 1.9.3 and ruby-debug 41

Posted by santiago.pastorino
on Tuesday, November 01

As you probably know Ruby (MRI so brixen doesn’t get mad at me :P) 1.9.3 was released. I’ve been using 1.9.3 for a while now and as part of my RubyConf Uruguay talk I wanted to show ruby-debug. So my first attempt was:

$ gem install ruby-debug19
Fetching: linecache19-0.5.12.gem (100%)
Building native extensions.  This could take a while...
Fetching: ruby-debug-base19-0.11.25.gem (100%)
Building native extensions.  This could take a while...
Fetching: ruby-debug19-0.11.6.gem (100%)
Successfully installed linecache19-0.5.12
Successfully installed ruby-debug-base19-0.11.25
Successfully installed ruby-debug19-0.11.6
3 gems installed

Then require ‘ruby-debug’ and booom!!

$ irb
irb(main):001:0> require 'ruby-debug'
LoadError: dlopen(/Users/santiago/.rbenv/versions/1.9.3/lib/ruby/gems/1.9.1/gems/ruby-debug-base19-0.11.25/lib/ruby_debug.bundle, 9): Symbol not found: _ruby_current_thread
  Referenced from: /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/gems/1.9.1/gems/ruby-debug-base19-0.11.25/lib/ruby_debug.bundle
  Expected in: flat namespace
 in /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/gems/1.9.1/gems/ruby-debug-base19-0.11.25/lib/ruby_debug.bundle - /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/gems/1.9.1/gems/ruby-debug-base19-0.11.25/lib/ruby_debug.bundle
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/gems/1.9.1/gems/ruby-debug-base19-0.11.25/lib/ruby-debug-base.rb:1:in `<top (required)>'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/gems/1.9.1/gems/ruby-debug19-0.11.6/cli/ruby-debug.rb:5:in `<top (required)>'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/1.9.1/rubygems/custom_require.rb:59:in `require'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/1.9.1/rubygems/custom_require.rb:59:in `rescue in require'
    from /Users/santiago/.rbenv/versions/1.9.3/lib/ruby/1.9.1/rubygems/custom_require.rb:35:in `require'
    from (irb):1
    from /Users/santiago/.rbenv/versions/1.9.3/bin/irb:12:in `<main>'

So after some research on the internet I found out that the author of ruby-debug had a fix for it which he considered unstable and didn’t push it to rubygems.org yet. Since I prefer an unstable ruby-debug than a non working one :P, I gave it a try …

First download linecache19-0.5.13.gem and ruby-debug-base19-0.11.26.gem from http://rubyforge.org/frs/?group_id=8883, then …

$ gem install linecache19-0.5.13.gem 
Building native extensions.  This could take a while...
Successfully installed linecache19-0.5.13
1 gem installed
$ gem install ruby-debug-base19-0.11.26.gem -- --with-ruby-include=/Users/santiago/.rbenv/source/ruby-1.9.3-p0  
Building native extensions.  This could take a while...
Successfully installed ruby-debug-base19-0.11.26
1 gem installed
$ irb
irb(main):001:0> require 'ruby-debug'
=> true

and voilá.

So while we wait for an official release, you can enjoy a working ruby-debug.

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

sebastian.martinez

Client - Developer relationships 3

Posted by sebastian.martinez
on Monday, April 11

There is an old joke that illustrates how the relationship between clients and developers is that I’d like to share with you:

A man is flying in a hot air balloon when realizes he is lost. He reduces height and spots a man down below. He lowers the balloon further and shouts: 
- "Excuse me, can you tell me where I am?" 
The man below says: 
- "Yes you're in a hot air balloon, hovering 30 feet above this field." 
- "You must be a software developer," says the balloonist.
- "I am," replies the man. "How did you know?" 
- "Well," says the balloonist, "everything you have told me is technically correct, but it's of no use to anyone." 
The man below says, 
- "You must work in business as a manager." 
- "I do," replies the balloonist, "but how did you know?" 
- "Well," says the man, "you don't know where you are or where you are going, but you expect me to be able to help. You're in the same position you were before we met but now it's my fault." 

Developing successful client relationships are critical to any business. Preserving these relationships is crucial for making the time spent on projects more enjoyable and satisfying, as well as for referrals and future business.

So how can I improve this relationship?

It ain’t the purpose of this post to be a silver bullet, but to share some practices that have given us some good results in the past.

  • Spend some time getting to know your client

    You will likely spend many hours with the client during the project. It is important in order to strengthen the relationship to get to know your client’s interests, try to feel what they feel. After all, we are all human thus have natural highs and lows, and it is important to understand when someone is having a hard day.
  • Educate your client

    Educating clients about web development is crucial to the success of a project. The pace of change on the web is staggering and it is our responsibility to help clients make good decisions regarding their web presence. You need to tell your client that changes are a good thing and should be welcomed.
  • Be willing to say NO

    In many cases, clients ask us to do things that our experience says that doing so will, far from contributing to the project, cause users to run away. You need to take the time to understand why your client is asking you to do this, let them know your reasons against it, and try to find another solution together. This is healthy. Don’t just say “yes” because the client is always right.
  • Be willing to say YES

    Say yes to the jobs that may require you to work harder. The client will be grateful. Specially in those cases when it is important for the client to have this particular feature deployed, as it will represent and lead to a full stack of opportunities. Doing this will make you more valuable in your clients eyes, and also by sharing the stress of the deadline you’ll become closer to the client, so don’t be afraid to embrace these opportunities. Now, this concept should not be taken as the regular way to go, meaning no one can expect us to work every single day giving a 150%. Pushing yourself a little bit every once in a while is ok, but when it becomes normal, then something’s wrong.
  • Keep your distance

    We become more valuable the more we work in an organization, but we need to define and maintain our role clearly. Even as we build the relationships that make us successful, we need to be diligent in keeping our distance so we can continue to provide valued advice and expertise. The idea is to have a respectful relationship, always keeping it professional.
  • Be transparent

    There might be cases when some tasks take longer than you expected. What should you do then? Be transparent. Explain your client the complications you ran into, and that these complications will probably make you work a little bit longer on this task, there’s nothing wrong with that. Anything can get complicated. Complications are part of our job. Being transparent to your client about this is definitely the way to go.
  • Gain your client’s TRUST

    Best way to gain your client’s trust is to stay focused on your deliverables. When we deliver what we say and when we say we will deliver it, we build our credibility and enhance our relationships. The trust the client gives us increases, and will help us when we state “this task will take two days” for example, when they think it’s just a simple tweak and shouldn’t take more than a couple of hours. The most important thing is letting them know that we are part of the team, we are both on the same boat, aiming to the same goals. Once your client understands that their failures are also your failures, and their achievements are your achievements as well and the other way around, then you’ll be a step further in gaining their trust.
  • Work at it

    Recognize that the client relationship is part of the job. Working on the relationship will make you more successful on current projects, enhance your chance for future work, and make the project much more enjoyable.

Hopefully by following this you’ll have a smoother relationship with your clients, and what’s more, make you feel comfortable working with them on the daily basis.

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

jose.costa

RailsConf 2010: Interview with Caike Souza 3

Posted by jose.costa
on Friday, March 25

We’re opening the box of RailsConf 2010 memories! Yep … we suck at journalism, so it turns out we have this almost one year old interview with Caike Souza we never shared before. So sorry Caike!

Caike (@caike) is a passionate agile software craftsman and founder of the Orlando Code Dojo group, where programmers get together to practice coding to improve their skills once a month. He is currently working at Envy Labs.

Thanks for your time and great vibe!

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

santiago.pastorino

Metaprogramming in Ruby slides from my talk at RubyConf Uruguay 1

Posted by santiago.pastorino
on Thursday, November 04
| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

sebastian.martinez

Creating your own generators on Rails 2.3 2

Posted by sebastian.martinez
on Thursday, September 23

Time has come for me to write a Rails generator, and as you’re guessing right now, my first step was taking a look at the Guides. They give you a pretty good idea on what you can do (despite of being for Rails 3.0), but as my friend Santiago always say, there’s no better documentation than the source code itself. So, my second step was to dive into the code. You should definitely read the code, great stuff there.

After some time reading, I decided it was time for me to start playing around with that, so here it comes:

First thing you should know, is that all Rails generators are derived from a class called “Rails::Generator::Base.” But, if we derive our generator class from NamedBase instead of Base, then we’ll get the ability to take a name parameter from the script/generate command line. With that in mind, you can start writing the generator skeleton:

class WidgetGenerator < Rails::Generator::NamedBase
  def manifest
    record do |m|
      # Do something
    end
  end
end

In order to make the generator work on your Rails 2.3 application, you should place this file under ‘lib/generators/widget/widget_generator.rb’

Is on the manifest method where the magic occurs. Depending on what exactly we want our generator to do, is what we’re going to code inside it. In my case, I wanted to behave very similar to the scaffold, so I wanted a controller class, a model, views, migration, etc… You can look at the templates of the scaffold generator, they will give you a very clear idea on how to use them. Then, you should place your templates under ‘lib/generators/widget/templates/’

In most cases, you will want your generator to receive several arguments. Best way is to have an initialize method to take care of that, just like this:


class WidgetGenerator < Rails::Generator::NamedBase
  attr_reader   :controller_class_name,
                :class_name
  attr_accessor :attributes

def initialize(runtime_args, runtime_options = {})
    super
    @name = runtime_args.first
    @controller_class_name = @name.pluralize.capitalize
    @attributes = []

    runtime_args[1..-1].each do |arg|
      if arg.include? ':'
        @attributes << Rails::Generator::GeneratedAttribute.new(*arg.split(":"))
      end
    end
  end

  def manifest
    record do |m|
      # Do something
    end
  end
end

Until now, we’re just initializing the generator, but it’s not doing anything yet. Let’s add some action on our manifest method:

def manifest
    record do |m|
      m.template('controller.rb', "app/controllers/#{name.pluralize}_controller.rb")
      m.template('model.rb', "app/models/#{name}.rb")
      m.migration_template("migration.rb", "db/migrate", :migration_file_name => "create_#{name.underscore.pluralize.camelize}")

      m.directory(File.join('app/views', name.pluralize))
      for action in %w[ new edit show ]
        m.template(
          "view_#{action}.html.erb",
          File.join('app/views', controller_file_name, "#{action}.html.erb")
        )
      end
    end
  end

Cool, now we are generating a controller from our template, a model, a migration, among others…Nice!

You can also add a protected banner method, to display the usage of the generator right on the console:

protected
    def banner
      "Usage: #{$0} widget WidgetName [field:type, field:type]" 
    end

And that’s all !! You can now generate all the widgets you want. The command to run this would be:

$ ./script/generate widget MyWidget title:string viewing:integer

Have fun generating!!

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

jose.costa

RailsConf 2010: Interview with George Guimarães 1

Posted by jose.costa
on Wednesday, July 28

Among the great people we met at the RailsConf was George Guimarães (@georgeguimaraes), by no surprise he was a very cool and funny dude, and he was open to talk and hang around with us.

George is co-founder of Plataforma Tec, that many of us got to know well through their amazing set of gems/plugins and the stunning work José Vailm has been doing as a Rails Core team member. Kind of what I hope it’s happening with the great work Santiago Pastorino is doing with his contributions and how it’s reinforcing WyeWorks reputation.

But still there are a lot of guys behind the scenes that support this great Open Source effort that’s being carried in these companies, probably not so much by direct intervention but with more hard and ‘real’ work as we like to say to joke around and bother the OSS guys. The kind of work that pay the bills :P

Not that George doesn’t do OSS, actually he’s currently involved in the development of Restfulie that got many people pretty excited at the RailsConf this year, and much more stuff.

Hope you enjoy this not so serious take.

Thanks George!

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

jose.costa

RailsConf 2010: Interview with Fabio Akita 4

Posted by jose.costa
on Thursday, July 01

In the last day of the RailsConf 2010 Santiago and I got the pleasure to hang out a few hours with Fabio Akita, a very successful guy in the Ruby and Rails community, but yet so humble and open as many of the great people we met in these past days.

Fabio is well known as a great evangelist of this movement, as a great speaker, for his bundle of plugins for the vim editor but also for carrying interviews with important people of the community on every conference he attends. The thing is that personally I never got to see him as the subject of the interview, and he is a wise guy that has a lot to say. So even though he was very tired, he accepted to do this improvised short interview with me, almost the first time I was holding a camera.

This is the first of a small series of interviews that will be posted soon.

I hope you all enjoy it and share his thoughts on what are the good things that makes this community so special, so that we never loose that spirit.

Thanks Fabio!

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

sebastian.martinez

Making Paperclip work with Sinatra & Datamapper 5

Posted by sebastian.martinez
on Wednesday, February 10

I was working lately on a Sinatra project, and got fascinated on how fast you can get things up and running. Everything was beautiful, until I tried to upload a file using paperclip.

Although Paperclip was originally built for rails Ken Robertson ported it to Datamapper. Let me explain in few steps how you can upload with Paperclip, using Datamapper.

Start declaring your model like this:
class Resource
  include DataMapper::Resource
  include Paperclip::Resource

  property :id,     Serial

  has_attached_file :file,
                    :url => "/system/:attachment/:id/:style/:basename.:extension",
                    :path => "#{APP_ROOT}/public/system/:attachment/:id/:style/:basename.:extension" 
end

You’ll need to specify your :url and :path options as the ones built into dm-paperclip are merb centric which won’t quite work. Also set APP_ROOT to where ever your application root directory with your static Sinatra folder is.

Now your routes should look something like this:
post '/upload' do
  resource = Resource.new(:file => make_paperclip_mash(params[:file]))
  halt "There were some errors processing your request..." unless resource.save
end

And there’s the tricky part, on the make_paperclip_mash method. Paperclip expects the file object loaded from the form to be in a different form than what is created by default. To fix this you should create a Mash (which is just a Hash, unless you’re actually using merb):

def make_paperclip_mash(file_hash)
  mash = Mash.new
  mash['tempfile'] = file_hash[:tempfile]
  mash['filename'] = file_hash[:filename]
  mash['content_type'] = file_hash[:type]
  mash['size'] = file_hash[:tempfile].size
  mash
end

And that’s it, now you can upload files using Paperclip right on your Sinatra app with Datamapper. You can check out the code of this example at: sinatra_paperclip.rb

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

santiago.pastorino

4 Ways to Retrieve a Twitter List Timeline 4

Posted by santiago.pastorino
on Monday, February 01

For past few days we had been working on the new version of the WyeWorks site, so stay tunned. This new version will have a twitter section, where the last 5 tweets of our team will be displayed.

So first thing I had to do was installing the twitter gem:
gem install twitter

In order to achieve this, I’ve found 3 different ways using the twitter gem, plus one not yet implemented on the gem, that I’ve already proposed the patch. The dumbest one would be:

#!/usr/bin/env ruby

require 'rubygems'
require 'twitter'

users = %w(wyeworks spastorino joseicosta smartinez87 nartub)

tweets = users.map { |user_name| Twitter::Search.new.from(user_name) }.
               inject([]) { |tweets, search| tweets + search.fetch(5).results }.
               sort { |t1, t2| Date.parse(t2.created_at) <=> Date.parse(t1.created_at) }[0,5]

tweets.each do |tweet|
  puts tweet.created_at
  puts tweet.from_user
  puts tweet.profile_image_url
  puts tweet.text
end

What this does is retrieve the last 5 tweets of each user and merge them sorted by date. Obviously, best thing to do would be directly retrieving the last 5 tweets from the @wyeworks/team list. Only way to do this using the gem requires authentication, despite the list being public. In order to authenticate, we may take two paths, the first one would be using HTTP Authentication:

#!/usr/bin/env ruby

require 'rubygems'
require 'twitter'

httpauth = Twitter::HTTPAuth.new('wyeworks', 'password')
base = Twitter::Base.new(httpauth)
base.list_timeline('wyeworks', 'team', :page => 1, :per_page => 5).each do |tweet|
  puts tweet.created_at
  puts tweet.user.screen_name
  puts tweet.user.profile_image_url
  puts tweet.text
end

The other and preferred way for authentication is OAuth, since we don’t have to send the user and password through the network. In order to make OAuth work with twitter, we have to create an application at http://twitter.com/apps Once we’ve created the app, twitter provides us with a Consumer Key and a Consumer Secret, needed to authenticate using OAuth

#!/usr/bin/env ruby

require 'rubygems'
require 'twitter'

oauth = Twitter::OAuth.new('consumer token', 'consumer secret')

begin
  oauth.authorize_from_access(oauth.request_token.token, oauth.request_token.secret)

  base = Twitter::Base.new(oauth)
  base.list_timeline('wyeworks', 'team', :page => 1, :per_page => 5).each do |tweet|
    puts tweet.created_at
    puts tweet.user.screen_name
    puts tweet.user.profile_image_url
    puts tweet.text
 end
rescue OAuth::Unauthorized
  puts "> FAIL!" 
end

Either of these ways works just fine, but no one completely satisfied me, since we are working with a public list, so as far as I can see authentication is out the question, even more when anyone can see it directly from the web without authenticating. For this reason, I started looking at the Twitter API searching for a non-authentication way to do it: Here’s what I found. You can test that making a request to http://api.twitter.com/1/wyeworks/lists/team/statuses.json?page=1&per_page=5, obtaining the list as a json, or xml in case you change the .json to .xml

So I’ve came up with this monkey-patch:

module Twitter
  # :per_page = max number of statues to get at once
  # :page = which page of tweets you wish to get
  def self.list_timeline(list_owner_username, slug, query = {})
    response = HTTParty.get("http://api.twitter.com/1/#{list_owner_username}/lists/#{slug}/statuses.json", :query => query, :format => :json)
    response.map{|tweet| Hashie::Mash.new tweet}
  end
end

Being able to get the list without authenticating by:

Twitter.list_timeline('wyeworks', 'team', :page => 1, :per_page => 5).each do |tweet|
   puts tweet.created_at
   puts tweet.user.screen_name
   puts tweet.user.profile_image_url
   puts tweet.text
end

I’ve already contacted the gem’s authors, proposing this patch: http://github.com/spastorino/twitter/commit/aed3a298b613a508bb9caf93afc7f12c50626ad7. Wynn Netherland already told me it’s pretty probable that it will be approved.

Until then, you can make use of this functionality from my fork http://twitter.com/spastorino/twitter

UPDATE #1: My fork was merged into http://github.com/jnunemaker/twitter master branch and twitter 0.8.3 was published through Gemcutter

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

santiago.pastorino

Rails Bugmash an exciting first experience 3

Posted by santiago.pastorino
on Tuesday, January 19

As many of you must know, last weekend a Railsbridge Bugmash was celebrated, and I had the honor to be part of it for the first time. For those who are not aware about what this is, it’s a virtual event that takes place on irc.freenode.net at #railsbridge channel. The general idea of these events is to work on the Rails Core, taking a look at the Rails Issue Tracker. However, given that Rails 3 is about to see the light, this opportunity was intended to deeply test it looking for:

  • Fix a known issue
  • Report a bug
  • Make sure your favorite gem or plugin still works. If not, fork it and make it so.
  • Write a blog post about a certain component
  • Write some documentation
  • Get an app up and running and document what you had to do to upgrade.
  • Create a screencast

Each accepted contribution or patch done by a participant, gives him chances to win one of several prizes, the more contributions the more chances you have to win. For further details check out the Railsbridge Bugmash Guide and the RailsBridge Wiki.

Many bugs were fixed during the event, some plugins and gems were tested, really interesting discussions took place (specially regarding generators) and some other articles were made. To mention some:

And then Jose Valim, motivated by the posts done regarding rails 3 generators, published one himself called Discovering Rails 3 Generators

This was my first participation and it was a bloody great experience. During the event I was specially devoted to search bugs on Rails 3 and try to patch them. I managed myself to find 4 code bugs and 1 documentation bug, proposing a solution for all of them. One of them was not approved though, for there was a bigger problem that required José Valim’s intervention, the 3 other patches were approved.

I would also want to highlight the gigantic work done by the organizers, the core team members, and also to all the participants. I strongly valued the support José Valim, Pratik Naik and Michael Koziarski gave me. They were a hell of a help when trying to find solutions for the bugs. Would also want to thank Ryan Bigg for his cooperation, and specially to Sam Elliott, an incredible 18 year old guy with a great future ahead. Besides working together with Ryan and Sam, we kept a really nice chat during almost the entire bugmash. The awesome will to help at #railsbridge really overwhelmed me, where everybody was willing to help each other, something that makes it so much easier for the ones starting to contribute to Rails.

I would also want to congrat and thank all the participants for trying to make Rails better. So don’t hesitate to join the next time, it’s not as hard as I expected it to be and you would definitely not regret it. Now I’m really motivated to help others so I’m going to join to Rails Mentors on RailsBridge to give back the good things I received during this experience.

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

sebastian.martinez

Modifying Recurring Billing Transactions 3

Posted by sebastian.martinez
on Monday, November 16

Ok, it’s been some time we don’t post something in the blog, past weeks have been crazy at the office but now everything is back to normal, hopefully.

In this post I just want to tell that we added an extra ability to the recurring billing for BeanStream Gateway: Modify an existing transaction.

It’s pretty easy, you just need to do something like this:

  response = gateway.update_recurring(new_amount ,  new_options) 

Remember, same for canceling, as BeanStream uses another API for managing these kind of transactions, we need to use the account_id for identifying the same, so you must include it on the options. Then all same options can be passed.

Check it out here: http://github.com/wyeworks/active_merchant.

That’s all, don’t forget to comment!

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.

sebastian.martinez

Active Merchant Recurring Billing 11

Posted by sebastian.martinez
on Wednesday, October 07

Working on a payment system we had to sort some difficulties when making recurring payments using active merchant. Why? Because we needed to use BeanStream gateway and active merchant does not support recurring billing for this gateway yet. So I just added the functionality to it.

You can check out my fork of Active Merchant that supports recurring billing for this merchant on http://github.com/wyeworks/active_merchant.

Here I leave you an example on how to use it:


require 'rubygems'
require 'active_merchant'

 ActiveMerchant::Billing::Base.mode = :test

  # ActiveMerchant accepts all amounts as Integer values in cents
  # $10.00
  amount = 1000

  # The card verification value is also known as CVV2, CVC2, or CID
  credit_card = ActiveMerchant::Billing::CreditCard.new(
                  :first_name         => 'Bob',
                  :last_name          => 'Bobsen',
                  :number             => '4242424242424242',
                  :month              => '8',
                  :year               => '2012',
                  :verification_value => '123'
                )

  # Validating the card automatically detects the card type
  if credit_card.valid?

    # Create a gateway object for the BeansTream service
    gateway = ActiveMerchant::Billing::BeanstreamGateway.new(
                :login => 'TestMerchant',
                :password => 'password',
                :pass_code => 'pass_code'
              )

    # Make recurring payment for the amount
    response = gateway.recurring(amount, credit_card, {
      :recurring_billing => {
         :end_of_month => '1',
         :tax1 => 0,
         :interval => {
            :unit => :months,
            :length => '1'
          },
          :duration => {
            :start_date => Date.today,
            :occurrences => 5
          }
        })

    if response.success?
      puts "Successfully charged $#{sprintf("%.2f", amount / 100)} to the credit card #{credit_card.display_number}. The Account number is #{response.params['rbAccountId']}" 
    else
      raise StandardError, response.message
    end
  end

And that’s it, you have now created a recurring billing payment.

Now, what if you want to cancel the same? Heres is how to do that:


 gateway.cancel_recurring({ :account_id => account_id })

Pretty easy…the account_id is the number the gateway responses with when making a recurrent payment, and the passcode is the way of authenticating in order to make this kind of transactions, and you can find it at the beanstream administrative console.

So try it out and have fun!

| |

If you have found this material to be useful, you might
consider recommending me on Working With Rails.