Logo

Who is talking?

Archive

RSpec::Core::Configuration::MustBeConfiguredBeforeExampleGroupsError

almost 6 years ago | Amit Kumar: toamitkumar's Code Blog

Came across this weird error: This had happened because I had RSpec 1 way of including spec_helper (in old files):require File.expand_path(File.dirname(__FILE__) + ‘/../spec_helper’)And the other way (in my new files):require ‘spec_helper’Synching them fixed it :))

Agile Product Manager - Are you there?

almost 6 years ago | Bhuwan Lodha: What Not to Build

And I am back to my blog. Not that I had disowned Agilecat, but just that I have a little more time these days compared to the last three years, as I gear up to transition into a new product at a new organization.This comeback blog is dedicated to all product managers who have renovated themselves to become ‘product owners’. I realize that there has been a lot of deliberation and analysis on this topic, but in today’s post, I am going to touch upon just that one aspect which is crucial to both the roles - ‘physical presence’. Yes, you got to be there. At the right time with the right people! A nice PM stays in constant contact with his ‘customers’, and to be a nice PO, he must and always be present with the scrum team. This is one large aspect of variation between the descriptions of duties between these two titles.The Product Manager, by definition, is the voice of market. He is coached to stay out, experience the souk, observe the users, study the customers and so on. The agile Product Owner role characterization lays a lot of emphasis on conducting planning meetings, giving first hand feedback to scrum teams, participating in review sessions and so on. So from a distance, this looks pretty clear – PM stays out of the office, while PO sits alongside the team. Two roles, pretty distinct, right? If you look closely, these roles may appear to have dissimilar portrayals, but share a common goal - that of connecting the dots between the market and the team. Yes, it is fundamental for a good PO to understand his customers and market, and equally imperative for the PM to identify with his team dynamics. If there is one person playing both these roles, he’s got to master that sweet balance of staying home with the team, and also out their in the field!Time management and self prioritization become crucial for such an agile PM/PO person. His typical calendar week best describes the role he plays, and nothing else.Agile methods encourage frequent release iterations, and call for stake holders, sponsors etc. to be significantly involved in product development. This helps in reducing risks, and at the same time makes it easy for the PM/PO to engage users and sponsors by making sure that his product stays in touch with them, while he stays in touch with the product.Exploiting social media tools to engage, listen and gauge the market sentiments is not new anymore, and is more and more becoming mainstream in product management techniques. While it clearly does not obviate that need for physical presence, it surely helps the PM/PO to better prioritize his ‘facetime’. Some argue that being a product manager and an agile PO at the same time results in overburdening of one person, and that is true, mostly because with that oath of “product owning” comes a never ending endeavor to help build great agile teams, along with winning products. Another way to look at this is to treat the agile team as another ‘product’ in the making, and PO playing chief architect on that project.

Analytics using R: Most active in my Twitter list

almost 6 years ago | Lalatendu Das: Interpretations of technorealism

I follow some 80 odd people/ news sources on my twitter account. For a while I wondered which of these sources are most active on twitter. I picked a simple metric '# of status messages posted to twitter' as the measure of activity. Using R I quickly wrote a program to generate my top 10 most active twitter sources.Here is the bar plot of the result  As expected news sources dominate the list. Among individuals "Michael Hyatt" and "Jurgen Appelo" are most active. If you are interested in 'R', here is the code to extract this report:## Prerequisite: Install twitteR package 'install.packages(twitteR)## load twitteR packagelibrary(twitteR)##get handle to a twitteR user object (in this case for user d_lalittuser ##get list of friends of d_lalittfriends ##create an array to store the name and number of status messages for each friendfriendsCount friendsName friendsMsgCount for (i in 1:friendsCount) { friendsName[i] friendsMsgCount[i] }## prepare a sortedlist and extract top 10 values from the listsortedlist top10friendsName top10friendsMsgCount for (i in 1:10) { top10friendsName[i] top10friendsMsgCount[i] }## plot the chartbarplot(top10friendsMsgCount, width = 0.25, names.arg = top10friendsName, horiz=FALSE, main="Twitter friends by activity count", ylab="Number of status messages", xlab="twitter friends", space=0.2, density=50, angle=45, cex.names=0.7)    I realize the code is not optimally written. Any suggestions refine the code will be appreciated.Update: 11/29/2011In the latest version of twitteR package, the method userFriends() has been deprecated. You may replace line#9 in the above code as with the code given below:tfriends

! No such app as radiant-cloud-8241. (Heruko)

almost 6 years ago | Amit Kumar: RubyizednRailified

While pushing my rails application on heroku I stumbled across a weird error.Here are the steps:To look into details of the error, lets dig deep. Below are the steps I followed to resolve the issue.

! No such app as radiant-cloud-8241. (Heruko)

almost 6 years ago | Amit Kumar: toamitkumar's Code Blog

While pushing my rails application on heroku I stumbled across a weird error.Here are the steps:To look into details of the error, lets dig deep. Below are the steps I followed to resolve the issue.

Inverted Waterfall chart with Highcharts

almost 6 years ago | Niranjan Sarade: InLoveWithNature

Pushed inverted waterfall chart implementation with Highcharts to Github @inverted-waterfall-charte.g. Zero Gap, i.e. Planned Savings = Actual SavingsPositive Gap, i.e. Actual Savings > Planned SavingsNegative Gap, i.e. Actual Savings < Planned Savings

Meet YaF - Part Two

almost 6 years ago | Eduard Moldovan: eduardmoldovan.com - tech

In the first part I showed you just a few things about YaF, mostly introductory. In this article I am going write a bit about routing, bootstrap and the view layer.

UX as a discipline

almost 6 years ago | Amit Anand: UXcorner

In this post I try to answer, why and where UX as a discipline stands (or sits). Well I know it might be late for a post such as this ; But each day as I come across reasons to give away reasoning for such displacements, I felt might as well take opportunity to give […]

UX as a discipline

almost 6 years ago | Amit Anand: UXcorner

In this post I try to answer, why and where UX as a discipline stands (or sits). Well I know it might be late for a post such as this ; But each day as I come across reasons to give away reasoning for such displacements, I felt might as well take opportunity to give […]

Things that annoy me in Chrome #1

almost 6 years ago | Ben Gilles: Ben Gillies

Every time I type out a fraction of a URI into the address bar, Chrome auto-completes it: Chrome URI auto-complete If I then hit enter immediately, Chrome takes me to a different page: Chrome incorrect destination This is really annoying (obviously). Dear Chrome Devs: if you auto-complete with one URI, take me to that URI. Don’t take me to a different one.

Testing IP Whitelisting in your Specs and Features

almost 6 years ago | Alex Rothenberg: Alex Rothenberg

Rails has so much support for testing built into itself that its rare I come up with something that’s hard to test but HTTP headers is not easy. Normally you don’t have to worry about HTTP headers as they’re set by the browser and you don’t do much with them. Recently I was working on an application where each user has an IP whitelist and they are only allowed to come from their whitelisted IP addresses. This isn’t as crazy as it sounds since the app is in a corporate environment and the users will all be coming from their corporate networks. Basically this means our authentication method needs 3 pieces of information username password remote ip address What makes this interesting is that the first two are input by the user but the ip address comes from the browser and network. Writing an RSpec unit test or Cucumber scenario to test user parameters (username and password) is something we’ve all done before but today I’m going to talk about how you can also test the IP address in a header. Implementation Before we look at how to test this let’s take a look at the implementation of our SessionController. app/controllers/sessions_controller.rb class SessionsController < ApplicationController def new @session = Session.new end def create remote_ip_address = request.headers['X-Forwarded-For'] || request.headers['REMOTE_ADDR'] @session = Session.create(params[:username], params[:password], remote_ip_address) if @session.valid? session[:current_user] = @session.user redirect_to root_url else flash.now[:error] = 'Unable to authenticate. Please try again' render :new end end def destroy session[:current_user] = nil redirect_to session end end These three actions provide login and logout. new displays the login form with username & password fields create uses the username and password from the form as well as the ip address to create a session (i.e. authenticate). In case the request hops through some proxy servers we use the X-Forwarded-For header to get the source IP and not the proxy’s IP. destroy users need to log out (but we wont talk about that anymore here) This works, but you shouldn’t trust me. We need tests around the create action! Unit Testing the IP Whitelist with RSpec Our Controller Spec needs to pass all 3 pieces of information (username, password & ip address) to the controller. Passing the username and password is pretty standard and something I’m sure you’ve done before. They come from a form so we pass them as a hash in the second argument to post. spec/controllers/sessions_controller_spec.rb post :create, {:username => 'alex', :password => 'secret'} Unfortunately we can’t pass the IP the same way because the post method in ActionController::TestCase doesn’t support passing headers in (but it does take the session or flash - that’s interesting to remember for some other time). actionpack/lib/action_controller/test_case.rb def post(action, parameters = nil, session = nil, flash = nil) process(action, parameters, session, flash, "POST") end If we keep looking around it turns out the ActionDispatch::TestRequest object has a nice convenience method that lets us specify the remote_addr directly. actionpack/lib/action_dispatch/testing/test_request.rb def remote_addr=(addr) @env['REMOTE_ADDR'] = addr end If we add a line to our spec we can handle the case where the IP comes in the REMOTE_ADDR HTTP header. spec/controllers/sessions_controller_spec.rb request.remote_addr = '192.168.1.100' post :create, {:username => 'alex', :password => 'secret'} We still need to deal with the X-Forwarded-For case. While Rails doesn’t give us a convenience method, by looking at the implementation of the remote_addr= method we can see how to set this header ourselves. spec/controllers/sessions_controller_spec.rb request.env['X-Forwarded-For'] = '192.168.1.100' post :create, {:username => 'alex', :password => 'secret'} Putting it all together we end up with a controller spec that looks like this. spec/controllers/sessions_controller_spec.rb require 'spec_helper' describe SessionsController do describe '#create' do describe 'successfully' do let(:alex) { mock } let(:valid_session) { mock(:valid? => true, :user => alex )} before do Session.should_receive(:create).with('alex', 'secret', '192.168.1.100').and_return(valid_session) end describe 'using REMOTE_ADDR' do before do request.remote_addr = '192.168.1.100' post :create, {:username => 'alex', :password => 'secret'} end it { should redirect_to root_path } it { should set_session(:current_user).to(alex)} end describe 'using X-Forwarded-For' do before do request.remote_addr = '172.16.254.1' request.env['X-Forwarded-For'] = '192.168.1.100' post :create, {:username => 'alex', :password => 'secret'} end it { should redirect_to root_path } it { should set_session(:current_user).to(alex)} end end describe 'unsuccessfully' do let(:invalid_session) { mock(:valid? => false) } before do Session.should_receive(:create).with('alex', 'secret', '192.168.1.100').and_return(invalid_session) end describe 'using REMOTE_ADDR' do before do request.remote_addr = '192.168.1.100' post :create, {:username => 'alex', :password => 'secret'} end it { should render_template :new } end describe 'using X-Forwarded-For' do before do request.remote_addr = '172.16.254.1' request.env['X-Forwarded-For'] = '192.168.1.100' post :create, {:username => 'alex', :password => 'secret'} end it { should render_template :new } end end end end To sum up we can pass parameters as a hash in the post method post :create, {:username => 'alex', :password => 'secret'} set the remote_addr on the request with a convenience method request.remote_addr = '192.168.1.100' et the X-Forwarded-For directly on the requests’s environment hash request.env['X-Forwarded-For'] = '192.168.1.100' Integration Testing the IP Whitelist in a Cucumber Feature We face a similar issue when writing our cucumber scenarios - its easy to pass the username and password but harder to pass the IP address. The solution turns out to be similar but not quite exactly the because our Cucumber steps will use Capybara instead of ActionController::TestCase directly. Before we look into how to implement the steps, let’s write the feature we want which will help us define the steps we need. features/authentication.feature Feature: Authentication of a user In order to ensure a really secure application As a user I want my IP address to be validated during login Background: Given the following user exists: | username | password | company | | alex | secret | ip_address: 192.168.1.100 | Scenario: Successful log in Given I am connecting from ip "192.168.1.100" When I log in as "alex" with password "secret" Then I should be on the home page Scenario: Successful log in with X-Forwarded-For header Given I am connecting from ip "192.168.1.100" behind a proxy When I log in as "alex" with password "secret" Then I should be on the home page Scenario: Failed log in from wrong IP Given I am connecting from ip "172.16.254.1" When I log in as "alex" with password "secret" Then authentication should have failed Scenario: Failed log in from wrong IP behind a proxy Given I am connecting from ip "172.16.254.1" behind a proxy When I log in as "alex" with password "secret" Then authentication should have failed We immediately realize we don’t know how to write the first step features/step_definitions/authentication_steps.rb Given /^I am connecting from ip "([^"]*)"$/ do |ip_address| pending # How do we set the IP Address??? end To figure this out we need to dig into how capybara works. We don’t call post in ActionController::TestCase directly instead letting capybara do it for us. To see what capybara is doing we can skip that step and implement the login step features/step_definitions/authentication_steps.rb Given /^I am connecting from ip "([^"]*)"$/ do |ip_address| # do nothing for now end When /^I log in as "([^"]*)" with password "([^"]*)"$/ do |name, password| visit(new_session_path) fill_in('User name', :with => name) fill_in('Password', :with => password) click_button('Log In') end and edit the SessionsController to show us the stack trace. app/controllers/sessions_controller.rb class SessionsController < ApplicationController def create raise caller.inspect end end The stack trace is very big but if we look closely, somewhere in the middle of it we see lines below that show how capybara uses the rack-test gem to submit our form. ~/.rvm/gems/ruby-1.8.7-p334/gems/rack-test-0.6.1/lib/rack/test.rb:66:in `post' ~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/browser.rb:62:in `send' ~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/browser.rb:62:in `process' ~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/browser.rb:27:in `submit' ~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/rack_test/form.rb:64:in `submit' ... more lines omitted... ~/.rvm/gems/ruby-1.8.7-p334/gems/capybara-1.1.2/lib/capybara/node/actions.rb:38:in `click_button' Looking at the Rack::Test#post method we see something similar to what we saw before in ActionController::TestCase but its not quite identical. It takes the env as a parameter so we need to figure out how to inject our header in there. rack-test - lib/rack/test.rb def post(uri, params = {}, env = {}, &block) env = env_for(uri, env.merge(:method => "POST", :params => params)) process_request(uri, env, &block) end Following the stack trace up we see the env passed into Rack::Test::Session.post comes from Capybara::RackTest::Browser and it turns out that env is computed in the Capybara::RackTest::Browser#env method. capybara - lib/capybara/rack_test/browser.rb def options driver.options end def env env = {} begin env["HTTP_REFERER"] = last_request.url rescue Rack::Test::Error # no request yet end env.merge!(options[:headers]) if options[:headers] env end The key is in the line env.merge!(options[:headers]) if options[:headers] and those options are delegated to the driver. Now we know how to inject our IP address onto the driver’s options. features/step_definitions/authentication_steps.rb Given /^I am connecting from ip "([^"]*)"$/ do |ip_address| page.driver.options[:headers] = {'REMOTE_ADDR' => ip_address} end Putting it all together we can write all our steps features/step_definitions/authentication_steps.rb Given /^I am connecting from ip "([^"]*)"$/ do |ip_address| page.driver.options[:headers] = {'REMOTE_ADDR' => ip_address} end Given /^I am connecting from ip "([^"]*)" behind a proxy$/ do |ip_address| page.driver.options[:headers] = {'X-Forwarded-For' => ip_address} end When /^I log in as "([^"]*)" with password "([^"]*)"$/ do |name, password| visit(new_session_path) fill_in('User name', :with => name) fill_in('Password', :with => password) click_button('Log In') end Then /^I should be on the home page$/ do URI.parse(current_url).path.should == root_path end Then /^authentication should have failed$/ do page.text.should include 'Unable to authenticate. Please try again' end Now the scenarios we wrote before all pass. To sum up capybara handles form submission superbly with fill_in('User name', :with => name) click_button('Log In') we can set any HTTP header in capybara with page.driver.options[:headers] = {'REMOTE_ADDR' => ip_address} Testing is good Since we’re testing the IP logic at both the unit level with RSpec and integration level with Cucumber and Capybara we can be pretty sure it’s all going to work correctly.

Programming With Kids

almost 6 years ago | Alex Rothenberg: Alex Rothenberg

I’ve started to teach my kids to program. I figured I build websites professionally and it’d be a fun way for me to share what I do and help supplement their learning. And it was something they expressed interest in not something I was pushing. I suggested we build our own small version of facebook or twitter. Very quickly I learned two truths websites are boring games are fun Okay. I’ve never built a game before after a little digging there are plenty of tools in the open source world and many built on Ruby. We’re currently experimenting with three different tools/technologies. Shoes I first came across Shoes several years ago and was blown away. It was originally written by why and is now maintained by Team Shoes on github. “Shoes is the best little DSL for cross-platform GUI programming there is. It feels like real Ruby, rather than just another C++ library wrapper” Writing a Shoes app feels just like writing a Ruby app (it is Ruby!). The best analogy I can use is that what Rails does for websites, Shoes does for GUI apps. If you want to create a blue rectangle on a page, here’s your app Shoes.app do fill blue rect :top => 25, :left => 50, :height => 75, :width => 150 end A blue rectangle We can make it a bit more interactive and allow the user to move our rectangle around with the arrow keys and display the current coordinates Shoes.app do fill blue @player = rect :top => 25, :left => 50, :height => 75, :width => 150 @current_coordinates = para "(#{@player.left}, #{@player.top})" keypress do |key| @player.left += 10 if key == :right @player.left -= 10 if key == :left @player.top += 10 if key == :down @player.top -= 10 if key == :up @current_coordinates.replace "(#{@player.left}, #{@player.top})" end end The Blue Rectangle Moves We’re not limited to blue rectangles. We can replace it with an image Shoes.app do @player = image 'images/Starfighter.png', :top => 25, :left => 50 @current_coordinates = para "(#{@player.left}, #{@player.top})" keypress do |key| @player.left += 10 if key == :right @player.left -= 10 if key == :left @player.top += 10 if key == :down @player.top -= 10 if key == :up @current_coordinates.replace "(#{@player.left}, #{@player.top})" end end The Player is a Starship We’re writing Ruby in a fairly natural way. Shoes just gives us GUI methods like rect to create a rectangle or para to create a paragraph. Because this is Ruby, as your Shoes app gets more complex you can create classes and methods to organize and keep it manageable just as you would in any other app. There are all sorts of great resources out there including The Shoes Manual which includes a reference for all the elements you may use (like rect or para) why’s tutorial - the original introduction to Shoes sample apps - there are some really good ones here! Teaching Ruby to High School Girls (using Shoes) article by Sarah Mei Gosu Gosu is a gaming library so while Shoes lets us build any sort of GUI apps this is seemed like it might be a better fit since we’re interested in gaming. Luckily there’s a gem that wraps up the Ruby interface (Gosu can be used from C++ or Ruby). gem install gosu If we want to build a similar game to what we did in Shoes with a play we move around via the arrow keys we need to subclass the Gosu::Window class. require 'rubygems' require 'gosu' class Player def initialize(window) @image = Gosu::Image.new(window, "media/Starfighter.png", false) @x, @y = 125, 50 @angle = 0.0 end def draw @image.draw_rot(@x, @y, 0, @angle) end end class GameWindow < Gosu::Window def initialize super(640, 480, false) self.caption = "Gosu Tutorial Game" @player = Player.new(self) end def draw @player.draw end end window = GameWindow.new window.show And we see a window with a player that looks like a starship Starship player Its not too hard to make it move by overriding the update method in our window class require 'rubygems' require 'gosu' class Player attr_accessor :x, :y def initialize(window) @image = Gosu::Image.new(window, "media/Starfighter.bmp", false) @x, @y = 75, 50 @angle = 0.0 end def draw @image.draw_rot(@x, @y, 0, @angle) end end class GameWindow < Gosu::Window def initialize super(400, 300, false) self.caption = "Our Game" @player = Player.new(self) @current_coordinates = Gosu::Font.new(self, Gosu::default_font_name, 20) end def update @player.x -= 10 if button_down? Gosu::KbLeft @player.x += 10 if button_down? Gosu::KbRight @player.y += 10 if button_down? Gosu::KbDown @player.y -= 10 if button_down? Gosu::KbUp end def draw @player.draw @current_coordinates.draw("(#{@player.x}, #{@player.y})", 10, 10, 0, 1.0, 1.0, 0xffffff00) end end window = GameWindow.new window.show Starship player moves This example can be extended into a full Asteroids like like game where your ship has inertia. You should look at the source or an explanation on the gosu site. There are all sorts of great resources out there including Samples from the Gosu Showcase or Falling Blocks or CptnRuby Falling Blocks (tetris)   Captain Ruby Chingu an extension that seems to let us avoid re-writing common tasks Robot Chipmunk a physics library that makes it easy to do things like collision detection, gravity, etc Gravity and Collisions demo Even though we’re still writing Ruby, Gosu feels more like C++ Windows development I used to do long long time ago. I’m not sure if that’s inevitable and need to keep using Gosu to find out. gamesalad The last framework we’ve been working with is pretty different. GameSalad advertises it lets you “Create games for iPhone, iPad, Android, Mac, and HTML5. No coding required.” It follows a model similar to what Adobe Flash uses where you have Scenes containing Actors. You write your programs in a visual editor by dragging and dropping Actors onto Scenes, Rules onto Actors and Behavior onto Rules. For instance if we have a starship actor and we drop these rules onto it Starfighter rules We will get our familiar spaceship that can move left and right Starfighter Moving GameSalad is the least familiar to me but seems to be easiest for my kids to start working on. Not having to write any “code” or “do programming” makes it much easier to get started. It also can create iPhone or iPad games and I would never dream of exposing my kids to Objective-C. What’s next? We’ve started experimenting with all three of these tools and so far are having fun with all three. Hopefully we’ll figure out what works for us and perhaps try to write about it again in a few months. After writing this I came across a recent NY Times article Programming for Children, Minus Cryptic Syntax and Scratch also sounds interesting so I may have to look into that sometime too.

Meet YaF - Part one

almost 6 years ago | Eduard Moldovan: eduardmoldovan.com - tech

PHP YaF, as Yet another Framework, is object oriented PHP framework. But there are a few things about it, that make it a bit different. I have tried it a few days back and decided to write up a few articles about my quest with it.

Twitter is the new RSS Reader

almost 6 years ago | Alex Rothenberg: Alex Rothenberg

In 2008 I thought RSS was an awesome way to stay abreast of what’s going on, but now its 2011 and I find myself using Twitter more often than Google Reader to find new and interesting articles people have written. Readers tweet and retweet articles they find interesting which seems a lower barrier than leaving an “I like this” comment. As an author Twitter also gives you some idea of who is reading your posts and a way to connect with them. Back in 2008 I created a blog aggregator site http://waywework.it to group the all the people I work with and promote others to share their thoughts. I was so excited I even wrote an article about it. Now that its 2011, I’ve been asking myself how could I update http://waywework.it for the twitter world of today? I decide that if we’re going to follow people on twitter that’s what my site should facilitate. When new posts come in it should tweet them letting you see them if you follow @WayWeWorkIT. Enabling API access to twitter Once I had this I added the twitter gem to my application. I have to give a shout out John Nunemaker for writing this fantastic gem which made my task so simple. In the Gemfile gem 'twitter' I created a new twitter account @WayWeWorkIT and registered an application at https://dev.twitter.com/apps so I had my OAuth and access tokens. The only trick was I had to go Application Settings tab and configure it for Read and Write access then regenerate the tokens. Now that I had the keys and tokens from twitter I had to tell my application to use them without hardcoding them in my code. This took two steps. First, configuring the app to read the tokens from the environment in config/initializers/twitter.rb. Yes I am somewhat paranoid about accidentally tweeting from development but that if Rails.env.production? should save me. if Rails.env.production? Twitter.configure do |config| config.consumer_key = ENV['TWITTER_CONSUMER_KEY'] config.consumer_secret = ENV['TWITTER_CONSUMER_SECRET'] config.oauth_token = ENV['TWITTER_OAUTH_TOKEN'] config.oauth_token_secret = ENV['TWITTER_OAUTH_TOKEN_SECRET'] end end Secondly, setting the tokens on the heroku environment (I typed the real tokens instead of the XXXXXXXX’s). $ heroku config:add TWITTER_CONSUMER_KEY=XXXXXXXX $ heroku config:add TWITTER_CONSUMER_SECRET=XXXXXXXX $ heroku config:add TWITTER_OAUTH_TOKEN=XXXXXXXX $ heroku config:add TWITTER_OAUTH_TOKEN_SECRET=XXXXXXXX We can test it out (after deploying with git push heroku) $ heroku console >> Twitter.tweet('http://waywework.it aggregates blog articles') => # some big object returned >> Twitter.user_timeline('wayweworkit').first.text => "http://t.co/FCmUQdc3 aggregates blog articles" Great we just tweeted our first tweet for the world to see. Updating WayWeWork.IT to tweet new posts The app periodically scans the rss feeds it tracks and when it sees a new post it creates it in the app’s database. First we add a twitter_username to each feed we’re tracking class AddTwitterUsernameToFeeds < ActiveRecord::Migration def change add_column :feeds, :twitter_username, :string end end Then, add an after_create callback to tweet each time we create a new post. class Post < ActiveRecord::Base after_create :tweet delegate :twitter_username, :to => :feed def twitter_username_with_at_sign "@#{feed_twitter_username || 'WayWeWorkIT'} end # See https://dev.twitter.com/docs/tco-link-wrapper/faq#Will_t.co-wrapped_links_always_be_the_same_length # We should query instead of hardcoding 20 def short_url_length 20 end def tweet if Rails.env.production? non_title_part_of_tweet = " #{'x'*short_url_length} via #{twitter_username_with_at_sign}" max_title_length = 140 - non_title_part_of_tweet.length tweet = "#{title.truncate(max_title_length)} #{url} via #{twitter_username_with_at_sign}" Twitter.update(tweet) end end end Again with the “if Rails.env.production?” paranoia? You do know that you can never be too paranoid :) With the twitter gem its one line to tweet Twitter.update(tweet). The rest of it is to shorten the title so twitter’s 140 character limit wont cut off the url or the author’s name. Once this is in we’ll start seeing tweets like Using BDD and the email_spec gem to implement Email www.alexrothenberg.com/2011/10/31/usi… via @alexrothenberg Twitter is the new RSS Reader http://www.alexrothenberg.com/2011/11/07/twitter-is-the-new-rss-reader.html via @alexrothenberg Go ahead and follow @WayWeWorkIT on twitter and you’ll start seeing these blog posts.

138 years of popular science by Jer Thorp

almost 6 years ago | James Torio: Designing the experience

Jer Thorp walks through his process of how he created a recent visualization for popular science magazine. Part of his process that I find interesting is he says, “This is a really common approach for me to take – building small tools during the process of a project that help me solve specific problems.” Another interesting point […]