Pricing Experiment Follow Up

Thanks so much to those of you who helped me with my pricing experiment. I feel it was a success, with a lot of great feedback.

Before I launched the survey I had a price in mind, but I wanted to see what the prevailing opinion would be on what the price should be without being influenced by that info. I was pleasantly surprised to find that many of those who responded were willing to pay more than the amount I had in mind, which makes me feel good about the value of the products I offer via Rails Kits.

The OAuth Kit has now been priced and released, but I’ll leave the survey open a little longer to let a few more folks get the coupon. 🙂

Pricing Experiment Follow Up

Thanks so much to those of you who helped me with my pricing experiment. I feel it was a success, with a lot of great feedback.

Before I launched the survey I had a price in mind, but I wanted to see what the prevailing opinion would be on what the price should be without being influenced by that info. I was pleasantly surprised to find that many of those who responded were willing to pay more than the amount I had in mind, which makes me feel good about the value of the products I offer via Rails Kits.

The OAuth Kit has now been priced and released, but I’ll leave the survey open a little longer to let a few more folks get the coupon. 🙂

Pricing Experiment Follow Up

Thanks so much to those of you who helped me with my pricing experiment. I feel it was a success, with a lot of great feedback.

Before I launched the survey I had a price in mind, but I wanted to see what the prevailing opinion would be on what the price should be without being influenced by that info. I was pleasantly surprised to find that many of those who responded were willing to pay more than the amount I had in mind, which makes me feel good about the value of the products I offer via Rails Kits.

The OAuth Kit has now been priced and released, but I’ll leave the survey open a little longer to let a few more folks get the coupon. 🙂

A Pricing Experiment

Today I read about determining pricing by surveying your customers, and it just so happens that I have a new product ready for pricing, so I thought I’d try it out.I am ready to release the OAuth Rails Kit, which gives you a good example of how to integrate Twitter, Facebook, and LinkedIn into your Rails app. If you’re like me, you’ve probably been asked to pull data in from LinkedIn, or push out updates to a user’s Facebook stream. This Kit shows you step by step exactly how to that. The only thing I need now to start selling the Kit is a price. 🙂

That’s where you come in. After you check out the product page, head over to this one-page, seven-question survey that seeks your input on what I should charge for the OAuth Kit. In exchange for your time, you’ll get a 25%-off coupon code that you can use towards a purchase of the OAuth Kit.

Thanks for your help — I’m looking forward to seeing how this turns out!

Update

The Kit has now been priced and launched. Please see the results of the pricing experiment, or go ahead and buy the Kit to easily integrate Facebook, Twitter, and LinkedIn APIs in your Rails app. 🙂

A Pricing Experiment

Today I read about determining pricing by surveying your customers, and it just so happens that I have a new product ready for pricing, so I thought I’d try it out.

Continue reading “A Pricing Experiment”

Defaulting to Ruby 1.9.2

Heroku is fully behind Ruby 1.9.2 as the new gold standard for production Ruby apps. Over the past few months, we’ve seen more and more developers move to the Bamboo 1.9.2 stack. It’s fast, stable, and increasingly sees excellent support throughout the community.

In February, we said that we’d be reviewing the state of 1.9.2 support with the eventual goal of switching the default for new Ruby apps on Heroku from 1.8.7 to 1.9.2. Today, we’re announcing the date of that switchover.

As of June 1st, 2011, all new Ruby applications on Heroku will be run on Ruby 1.9.2 by default. (Existing applications won’t be affected, and you can always create a new application on 1.8.7 by running heroku create --stack bamboo-ree-1.8.7.)

But there’s no need to wait till June – get started with a Ruby 1.9.2 app on Heroku today with the following command:

$ heroku create --stack bamboo-mri-1.9.2

Unboxing Sifteo cubes

A good friend in Switzerland wanted the sifteo cubs, so I order a started kit for him which I just received. He told me I should check them out, now I want to keep them 🙂
They come with a bunch of games but they can also be used as controls for your computer. I’m looking forward to see what new interaction people create with these. I would love to control my home automation with these cubes.

For the very curious (and patient) out there, here is the Uboxing video and the initial setup walk through:

For something more exiting here is David Merrill demo at Ted:

http://www.ted.com/talks/david_merrill_demos_siftables_the_smart_blocks.html

Check out their Websites www.sifteo.com

Unboxing Sifteo cubes

A good friend in Switzerland wanted the sifteo cubs, so I order a started kit for him which I just received. He told me I should check them out, now I want to keep them 🙂
They come with a bunch of games but they can also be used as controls for your computer. I’m looking forward to see what new interaction people create with these. I would love to control my home automation with these cubes.

For the very curious (and patient) out there, here is the Uboxing video and the initial setup walk through:

For something more exiting here is David Merrill demo at Ted:

http://www.ted.com/talks/david_merrill_demos_siftables_the_smart_blocks.html

Check out their Websites www.sifteo.com

Unboxing Sifteo cubes

A good friend in Switzerland wanted the sifteo cubs, so I order a started kit for him which I just received. He told me I should check them out, now I want to keep them 🙂
They come with a bunch of games but they can also be used as controls for your computer. I’m looking forward to see what new interaction people create with these. I would love to control my home automation with these cubes.

For the very curious (and patient) out there, here is the Uboxing video and the initial setup walk through:

For something more exiting here is David Merrill demo at Ted:

http://www.ted.com/talks/david_merrill_demos_siftables_the_smart_blocks.html

Check out their Websites www.sifteo.com

Ruby Programming 24th Batch: An Intensive, Online Course For Beginners

Introducing an intensive, online course for beginners that helps you get started with Ruby programming.

What’s Ruby?

Ruby

According to http://www.ruby-lang.org/en/ – “Ruby is a dynamic, open source programming language with a focus on simplicity and productivity. Ruby’s elegant syntax is natural to read and easy to write.”

Yukihiro Matsumoto, the creator of Ruby, in an interview says –

I believe people want to express themselves when they program. They don’t want to fight with the language. Programming languages must feel natural to programmers. I tried to make people enjoy programming and concentrate on the fun and creative part of programming when they use Ruby.

What Will I Learn?

In the Ruby programming course, you will learn the essential features of Ruby that you will end up using every day.

Depending on participation levels, we throw a Ruby coding challenge in the mix, appropriate for the level we are at. We have been known to give out a prize or two for the ‘best’ solution.

Who’s It For?

An absolute beginner but with some experience in some other programming language.

You can read what past participants have to say about the course. Click here.

Mentors

Satish Talim, Michael Kohl, Satoshi Asakawa, Victor Goff III and others from the RubyLearning team.

Dates

The course starts on Saturday, 21st May 2011 and runs for seven weeks.

RubyLearning’s IRC Channel

Most of the mentors and students hang out at RubyLearning’s IRC (irc.freenode.net) channel (#rubylearning.org) for both technical and non-technical discussions. Everyone benefits with the active discussions on Ruby with the mentors.

How do I register and pay the course fees?

  • The course is based on the The Ultimate Guide to Ruby Programming eBook. This book is normally priced at US$ 19.95 and we are discounting it US$ 10.00 by combining it in the Course+eBook option below.
  • You can pay either by Paypal or send cash via Western Union Money Transfer or by bank transfer (if you are in India). The fees collected helps RubyLearning maintain the site, this Ruby course, the Ruby eBook, and provide quality content to you.
  • Once you pay the fees below, register on the RubyLearning.org site and send us your name and registered email id while creating an account at RubyLearning.org to satish [at] rubylearning [dot] com
  • We will enroll you into the course. If you have purchased the eBook at the time of registration, we will personally email you the eBook within 24 hours.

You can pay the Course Fees by selecting your option from the menu below (please select your option).

Register

At the end of this course you should have all the knowledge to explore the wonderful world of Ruby on your own.

Join for free: If you are based in Africa, register at rubylearning.org and send me your registered email id. I shall enroll you into this batch, for free.

Here are some details on how the course works:

Important:

Once the course starts, you can login and start with the lessons any day and time and post your queries in the forum under the relevant lessons. Someone shall always be there to answer them. Just to set the expectations correctly, there is no real-time ‘webcasting’.

Methodology:

  • The Mentors shall give you URL’s of pages and sometimes some extra notes; you need to read through. Read the pre-class reading material at a convenient time of your choice – the dates mentioned are just for your guideline. While reading, please make a note of all your doubts, queries, questions, clarifications, comments about the lesson and after you have completed all the pages, post these on the forum under the relevant lesson. There could be some questions that relate to something that has not been mentioned or discussed by the mentors thus far; you could post the same too. Please remember that with every post, do mention the operating system of your computer.
  • The mentor shall highlight the important points that you need to remember for that day’s session.
  • There could be exercises every day. Please do them.
  • Participate in the forum for asking and answering questions or starting discussions. Share knowledge, and exchange ideas among yourselves during the course period. Participants are strongly encouraged to post technical questions, interesting articles, tools, sample programs or anything that is relevant to the class / lesson. Please do not post a simple "Thank you" note or "Hello" message to the forum. Please be aware that these messages are considered noises by people subscribed to the forum.

Outline of Work Expectations:

  1. Most of the days, you will have exercises to solve. These are there to help you assimilate whatever you have learned till then.
  2. Some days may have some extra assignments / food for thought articles / programs
  3. Above all, do take part in the relevant forums. Past participants will confirm that they learned the best by active participation.

Some Commonly Asked Questions

  • Qs. Is there any specific time when I need to be online?
    Ans. No. You need not be online at a specific time of the day.
  • Qs. Is it important for me to take part in the course forums?
    Ans. YES. You must Participate in the forum(s) for asking and answering questions or starting discussions. Share knowledge, and exchange ideas among yourselves (participants) during the course period. Participants are strongly encouraged to post technical questions, interesting articles, tools, sample programs or anything that is relevant to the class / lesson. Past participants will confirm that they learned the best by active participation.
  • Qs. How much time do I need to spend online for a course, in a day?
    Ans. This will vary from person to person. All depends upon your comfort level and the amount of time you want to spend on a particular lesson or task.
  • Qs. Is there any specific set time for feedback (e.g., any mentor responds to me within 24 hours?)
    Ans. Normally somebody should answer your query / question within 24 hours.
  • Qs. What happens if nobody answers my questions / queries?
    Ans. Normally, that will not happen. In case you feel that your question / query is not answered, then please post the same in the thread – “Any UnAnswered Questions / Queries”.
  • Qs. What happens to the class (or forums) after a course is over? Can you keep it open for a few more days so that students can complete and discuss too?
    Ans. The course and its forum is open for a month after the last day of the course.

Remember, the idea is to have fun learning Ruby.

Technorati Tags: , , ,

Post-mortem on April 21 Outage

On April 21st 2011, Heroku experienced a widespread application outage. We have posted a full post-mortem detailing the causes and steps we are taking to prevent similar outages from happening in the future.

Heroku status always contains our current status. You can follow @herokustatus to follow status updates via twitter.

jQuery, CoffeeScript, Rails 3.1 and more

In this episode, Peter and Jason go over the latest Ruby and Rails news and cover jQuery and CoffeeScript in Rails 3.1, and more.

RedDirt RubyConf

I was fortunate to spend this Thursday and Friday at RedDirt RubyConf in Oklahoma City. Here’s a quick conference report, and random thoughts about single-track conferences in general.

This is my second try at writing this post, excuse me if it’s a little disjointed (the first one was eaten by my writing tool — the dark side of continually trying out new writing app, but more on that later…)

I want to make sure I say up front that James and the rest of the organizers did an outstanding job with the logistics of the conference. I’ll talk more about the format later, but there was power and WiFi, they were able to keep the speakers on time, the mix of speakers and attendees was overall great, with a nice range of experience levels and expertise represented. There was plenty of time built in to meet the other attendees — even I, who am by nature not great at this stuff, managed to meet lots of people.

It got me to thinking about what kind of talk works in a single track environment when you are speaking to an audience that is essentially captive, and also has that wide range of interests and experience. For example, the best talk of the day, by general acclimation, was Jeff Casimir and his talk about fat models and Rails code design. Not only was it strong from a presentation or performance perspective — there’s something to be said for “shut up and listen to me” swagger — but it also had something for everybody. The novices could be inspired by Jeff’s examples, and learn something about good practice. The experts could nod sagely, pretend they do all those practices consistently and pick nits.

In contrast, you have talks like, to pick an example at random, mine. Now, I like my talk. I really like the tool I presented, I was happy to be able to introduce a tool at the conference, and I think the talk was a clear introduction. It was also only immediately relevant to a small percentage of the audience, based on show of hands. I’m not complaining, mind you, I think it’s great for people to be exposed to ideas outside their immediate needs. Part of the genius of the RRDC format is that if you weren’t interested in a particular topic, there was only a short wait until the next speaker.

Anyway, it was fun, and I’m glad I got a chance to go.

Filed under: Uncategorized

#263 Client Side Validations

Showing validation errors inline as the user is filling out the form can lead to a better use experience. Learn how to do this using the Client Side Validations gem.

#263 Client Side Validations

Showing validation errors inline as the user is filling out the form can lead to a better use experience. Learn how to do this using the Client Side Validations gem.

Summer Breeze Makes Me Feel Fine Blowing Through The Jasmine In My Mind

I just gave my RedDirt RubyConf talk introducing a new gem for JavaScript testing from a Rails app called Summer Breeze. It makes you feel fine, blowing through the Jasmine in your mind.

More specifically, Summer Breeze is a tool for generating fixture DOM output for Jasmine JavaScript tests directly from your Rails Views with a simple DSL for specifying fixtures

Summer Breeze is based on work by JB Steadman and Jonathan Barnes that can be found at http://pivotallabs.com/users/jb/blog/articles/1152-javascripttests-bind-reality-

Please note that Summer Breeze is an early release, with limitations, and will likely change over time.

Why Use Summer Breeze?

Jasmine is a great tool for BDD testing of JavaScript. When testing the JavaScript front end of a Rails project, often the JavaScript functionality will depend on a specific DOM structure being present on the page. Ideally, your Jasmine tests would be written in such a way that if the page view changed, the JavaScript test would fail.

So, Summer Breeze provides an easy way to have your Rails views be generated on the fly and used as input to Jasmine tests

Installing Summer Breeze

Summer Breeze requires Rails 3 and Ruby 1.9. (1.8 support is a future possibility, Rails 2 is less likely.) Jasmine must be installed, and right now there’s a dependency on Devise for authentication.

To install include in your gem file

    gem summer_breeze

After the bundle is installed, use

    rails generate summer_breeze:install

This creates two files, spec/javascripts/helpers/summer_breeze.js which contains JavaScript utilities, and spec/javascripts/support/summer_breeze.rb, which is where you put your Summer Breeze fixture definitions.

Defining Fixtures Summer Breeze

Summer Breeze fixtures are defined in the summer_breeze.rb file. The easiest way is with the fixture command

    fixture "PostsController##index.body_container"

The syntax is the controller name, followed by a ##, followed by the controller action, followed by an optional DOM element. If the element is specified, then only markup inside (and including) that element is saved in the fixture. This allows you to limit your fixture to only the part of the page you care about. If there is no DOM element (delimited by either a ‘.’ or a ‘#’), then the entire body of the page is saved. In any case, at the moment, any markup inside a DOM element called #third-party-scripts is automatically discarded.

Additional options to the fixture can go in an optional block

    fixture "PostsController##index.body_container" do
      params(:id => 1)
    end

These options can take a simple value, evaluated when the Summer Breeze file is loaded, or a block, evaluated when the fixture is run

These options include:

  • action — The controller action, overrides anything that might come from parsing the string argument to fixture.
  • controller_class — The controller class, also overriding anything that might come from parsing the string.
  • filename — the name to save the fixture to, otherwise defaults to the action and DOM id
  • flash — a hash of values in the flash, as in a controller test
  • limit_to_selector — the DOM element to limit output, overriding the parsing of the argument string
  • method — HTTP method of the action to take
  • params — A hash of parameters sent to the controller
  • session — A hash of session values sent to the controller, as in a controller test

You often need to do some setup, such as creating a logged-in user, before running the fixture. These setups can be defined with initialize blocks

    initializer :create_user do
      @user = User.new
      controller.sign_in(@user)
    end

    fixture "PostsController##index.body_container" do
      initializer :create_user
    end

The argument to initializer within the fixture block is either a symbol referring to an already defined initializer block, or a block or lambda in it’s own right.

Fixture files are stored in Rails.root/tmp/summer_breeze

Using Summer Breeze in Jasmine tests

Summer Breeze provides a few methods for loading the fixture file:

    sb.loadFixture(fixture_name)
    sb.findSelector(fixture_name, selector)
    sb.readFixture(fixture_name)

The loadFixture method reads the matching fixture file and adds it to the Jasmine DOM for further use. The findSelector method does the same, but also returns the the matching selector as a jQuery object. Finally, readFixture returns the HTML text of the fixture without adding it to the Jasmine DOM.

A sample test might look like this. Note that the jasmine-jquery extensions are very helpful in writing these tests

    it("hides text when asked", function() {
      $form_container = sb.findSelector('login', '.form_container');
      toggle_handlers.init();
      $hide_link = $form_container.find(".toggle_link");
      expect($hide_link).not.toHaveClass("hidden");
      $hide_link.click();
      expect($hide_link).toHaveClass("hidden");
    });

Summer Breeze Limitations

There are two limitations to these fixtures based on how they load data. The main one has to do with event handlers. Any handlers that are loaded as part of the header script on the page, such as application.js in a typical Rails application, will not be applied to the fixture markup even if the JavaScript file is loaded as part of Jasmine’s setup. This is because Jasmine loads those files first before the markup fixture is loaded. Any handlers or such like that you want referred to in the test must either be part of the fixture markup, or the handlers must be explicitly loaded as part of the test, as in the above test, where you can imagine that toggle_handlers.init() is defined elsewhere in the code.

Similarly, stylesheets are not attached to the fixture, so any outcome which depends on style elements defined in the stylesheet will not work.

And In Conclusion, I’m not done

I hope you find this kind of useful, I’ve been using it a little bit, and I like the workflow.

Filed under: Uncategorized

Coffeescript

In this episode, Peter and Jason go over the surprising news about Coffeescript and Rails, new releases of app servers, and more.

jQuery: New Default

In Rails 3.1 jQuery is going to be the default JavaScript library. Also, RJS has been extracted out. This post explains what that means for new applications, and what to look for while upgrading existing applications.

New Applications

Starting with Rails 3.1

rails new my_app

generates an application with jQuery.

The -j option of the generator lets you choose Prototype and Scriptaculous instead:

rails new my_app -j prototype

Such an application does not have RJS yet available though. From now on prototype-rails is needed for RJS, see below.

Upgrading Applications Using No RJS

Existing applications using no RJS should remove any references to ActionView::Base.debug_rjs in the project. Typically that means deleting

config.action_view.debug_rjs = true

from config/environments/development.rb. Other than that, upgrading should work out of the box as far as these changes is concerned.

Upgrading Applications Using RJS

Existing application using RJS should work out of the box with prototype-rails.

prototype-rails

RJS has been extracted to prototype-rails.

Applications using RJS have to add this line to their Gemfile while working against Rails master before the 3.1 release:

gem 'prototype-rails', :git => 'git://github.com/rails/prototype-rails.git'

prototype-rails is gonna be a gem when Rails 3.1 is out.

prototype-rails is the one who provides now the RJS template handler; the configuration flag ActionView::Base.debug_rjs; the ability to pass a block to link_to_function and button_to_function; the :update option of render, both in controllers and views; and the modules ActionView::Helpers::PrototypeHelper and ActionView::Helpers::ScriptaculousHelper.

Extraction has taken backwards compatibility into account as much as possible. With that goal in mind, everything is put back where it was before, either by reopening classes or modules, or via alias_method_chain when the refactor involved cutting some part of a method out, as happened with render :update.

There’s an exception: ActionView::Helpers::PrototypeHelper and ActionView::Helpers::ScriptaculousHelper are no longer ancestors of ActionView::Helpers. They are now injected into ActionView::Base and ActionView::TestCase directly.

When you include a module M into a class C, the class stores a proxy to M in its ancestor chain. After inclusion, if you add methods to M instances of C respond to them. But if you include another module N into M, the ancestor chain of C is not updated. Instances of C won’t respond to N‘s methods. Although a complete dynamic method dispatch would treat both ways of augmenting M equal, that’s the way it works as of today.

By the time prototype-rails is loaded ActionView::Helpers has already been included into ActionView::Base and ActionView::TestCase, so we need to inject them directly where they are needed. Standard usage just works, but please take into account that change in case you reopened or used ActionView::Helpers assuming those ancestors.

Before release, prototype-rails is going to provide also a way to bring Prototype and Scriptaculous to any application.

One Last Detail: The xhr Test Helper

The xml_http_request/xhr test helper is a simple convenience method that sets the X_REQUESTED_WITH header to “XMLHttpRequest”. If the test request has no Accept header, a fixed value of

[Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')

serves as default.

The Accept header in Prototype calls corresponds to that value, but in jQuery it depends on the dataType attribute. Also, in other JavaScript libraries the Accept header may behave differently. What to do with the default?

This method has been left as is. In particular, if your application uses jQuery the default Accept header in the test will be different from the Accept header sent by jQuery. That’s some vinegar: Rails encourages you to base interfaces on explicit format parameters. So, for example, best practice is to provide a /users.json endpoint, rather than a /users endpoint with a JSON representation chosen depending on the Accept header.

If you desperately need a matching Accept header in tests you are still able to pass it. And you can also write your own convenience test helpers easily, since a XHR request is just one whose X_REQUESTED_WITH header matches /XMLHttpRequest/i.

Try It Out!

If your application uses RJS it would be really helpful that you test it against master with prototype-rails and report any issues you may find. Thanks!

SSH Tunneling in Ruby

The other day I wanted to do some queries in production, but our servers are pretty locked down to the outside world. I was well aware that I could just make an ssh tunnel to connect to the database server, but I decided I wanted to do it in Ruby.

I am not the brightest of crayons in the box, so it took me a bit. Since I struggled with it for a few, I figured others probably will someday as well and decided to post my solution here.

Obviously, replace the strings with <…> with your own information and change the host port information in the gateway.open call.

require 'net/ssh/gateway'

gateway = Net::SSH::Gateway.new('<myremotehostorip.com>', '<remote_user>')

# Open port 27018 to forward to 127.0.0.1:27017
# on the remote host provided above
gateway.open('127.0.0.1', 27017, 27018)

# Connect to local port set in previous statement
conn = Mongo::Connection.new('127.0.0.1', 27018)

# Just printing out stats to show that it works
puts conn.db('<database_name>').stats.inspect

gateway.shutdown!

With just a few lines of Ruby, I can make scripts that use my local ssh key to talk to production. Thanks go to Jamis Buck for all the heavy lifting of writing net-ssh and company.

SSH Tunneling in Ruby

The other day I wanted to do some queries in production, but our servers are pretty locked down to the outside world. I was well aware that I could just make an ssh tunnel to connect to the database server, but I decided I wanted to do it in Ruby.

I am not the brightest of crayons in the box, so it took me a bit. Since I struggled with it for a few, I figured others probably will someday as well and decided to post my solution here.

Obviously, replace the strings with <…> with your own information and change the host port information in the gateway.open call.

require 'net/ssh/gateway'

gateway = Net::SSH::Gateway.new('<myremotehostorip.com>', '<remote_user>')

# Open port 27018 to forward to 127.0.0.1:27017
# on the remote host provided above
gateway.open('127.0.0.1', 27017, 27018)

# Connect to local port set in previous statement
conn = Mongo::Connection.new('127.0.0.1', 27018)

# Just printing out stats to show that it works
puts conn.db('<database_name>').stats.inspect

gateway.shutdown!

With just a few lines of Ruby, I can make scripts that use my local ssh key to talk to production. Thanks go to Jamis Buck for all the heavy lifting of writing net-ssh and company.