Tag Archives: programming

Rails 3: How to Simulate Paperclip Attachments With FactoryGirl

In developing the next phase of markstocks.com, I needed to simulate a file upload attribute in my FactoryGirl factories. A quick Google revealed some promising code, but everything out there was based on Rails 2.

There’s been a lot of changes in Rails 3, so using what I found, I tweaked the code to work in my Rails 3 factories. I’ve also posted this code as a gist forked from the original Rails 2 version on Github.

# spec/spec_helper.rb
...
# Support for Paperclip factories (add this before you load your factory definitions)
include ActionDispatch::TestProcess
...
# spec/support/factory_attachment.rb
Factory.class_eval do
  def attachment(name, path, content_type = "image/jpg")
    path_with_rails_root = "#{Rails.root}/#{path}"
    uploaded_file = fixture_file_upload(path_with_rails_root, content_type)
 
    add_attribute name, uploaded_file
  end
end
# spec/factories/photos.rb
Factory.define :photo do |p|
  # Given a Photo model with has_attached_file :image
  p.attachment :image, "spec/support/sample_photo.jpg"
end

References

  1. Original Gist
  2. APIDock.com

Lightweight Web Apps: Getting Started With Sinatra

For many reasons, I’m a huge fan of Rails for building web software, and by implication, coding in Ruby. When you’ve spent a little time working with Ruby, it’s difficult to go back to more traditional languages such as PHP.

For less intense website or small applications, though, Rails can feel a bit heavy-handed. Whilst Rails 3 goes a long way to improving this, I’ve recently been trying out the lightweight ruby framework, Sinatra.

Sinatra is a barebones framework for getting web applications up and running quickly. The idea is that Sinatra gives you a base into which you pull together the things you need, effectively building your own mini-framework. The process is enhanced by the vast array of Ruby Gems that are available.

In this post, I’ll show how to build a simple Sinatra application configured with Bundler and running on Rack that lets you quickly start building lightweight web applications.

Creating Your Sinatra Project

Unlike Rails, Sinatra doesn’t come with generators, so you’ll need to create the project layout yourself. Whilst you can use your own folder layout, there are a few conventions for which Sinatra is configured. Something like this should be good to get started:

mkdir -p myproject myproject/views myproject/public myproject/public/javascript myproject/public/css myproject/public/images
touch myproject/app.rb myproject/config.ru myproject/Gemfile

Running these commands generates the following folder structure:

myproject/
  public/
    public/css
    public/images
    public/javascript
  views/
  tmp/
  app.rb
  Gemfile
  config.ru

If you’ve used Rails 3, or worked with the Bundler gem and Rack, most of this should look familar: Gemfile is used by Bundler to declare rubygems the project relies on, whilst config.ru is used by Rack to configure and run the application.

Bundling Gems

Next, edit the Gemfile to load Sinatra and any dependencies. My markup of choice for HAML for layout (HTML) and SASS for CSS stylesheets. Sinatra makes using HAML (or any other renderer, such as ERB) very simple:

# Gemfile
source :rubygems
 
gem "sinatra"
gem "haml"

To install the bundle, just run bundle install from within your project folder:

cd myproject
bundle install

Configure Sinatra to run on Rack

My development environment is setup to run Ruby projects on Rack using the Passenger gem. To configure Sinatra to run on Rack, our project just needs a config.ru file. This file tells Rack to load the any required gems and star your Sinatra application:

# Gemfile
require "rubygems"
require "bundler/setup"
require "sinatra"
require "haml"
require "app"
 
set :run, false
set :raise_errors, true
 
run Sinatra::Application

Build Your App

With the environment configured, it’s time to build a small app to test everything. Start by adding a root path to app.rb and a corresponding index.haml file under views/:

# app.rb
set :haml, :format => :html5
 
get "/" do
  haml :index
end
# views/index.haml
%html
  %head
    %title My Sinatra App
 
  %body
    %h1 Hello World
    %p Your app is up and running!

The get block routes any HTTP GET requests for the site’s root path (example.com/) and renders views/index.haml using the HAML parser.

Running Your Application

To see your application running, start Rack by calling rackup from your project directory.

cd myproject
rackup

Now navigate to localhost:9292 to see your Sinatra app working! All being well, you should be greeted with the following:

Summary

Initially I had trouble seeing how Sinatra would be useful given the existence of full-stack frameworks like Rails. However, as I’ve taken the time to learn Sinatra, I can see the benefits of such a lightweight framework when used for certain tasks.

Whilst it shouldn’t be thought of as a replacement for frameworks like Rails, Sinatra is another tool available to Ruby developers looking to quickly build and deploy small websites and applications.

When Should You Use Sinatra?

When you should use Sinatra over a larger framework like Rails is entirely dependent on the requirements of your site. Sinatra is capable of connecting with databases using gems like ActiveRecord or DataMapper in the same way Rails is. It’s feasible, then, to build large-scale web applications with Sinatra – but my personal preference would be to stick with Rails.

The rule of thumb I’m using at the moment is that if my app requires a database, I’ll build it in Rails, otherwise I’ll try Sinatra.

With that in mind, I’m now using Sinatra to build and run lightweight websites such as the recently launched portfolio of Mark Stocks. Mark’s site only requires simple server-side processing for handling contact forms – a full-blown Rails build seemed a be too much! Sinatra provided just the right base on which to build Mark’s site, whilst retaining the flexibility that comes with the Ruby ecosystem.

Next Steps

In the next tutorial, I’ll extend the basic framework we’ve started here to include of a number of useful Ruby gems built for Sinatra, and show how to use your own custom helper code. When it’s a little more polished, I’ll also publish my working Sinatra base application on github.

References

  1. The Sinatra Website
  2. The Official Sinatra Book
  3. Bare Sinatra App For Deploying To Passenger

Android: Double Taps on a MapView with Overlays

Download the source code for this post PushPin.tar.gz, PushPin.zip.

For the past few days, I’ve been struggling with the Android SDK to detect double-taps on a MapView with overlays. I’m working on Plymouth Software’s first Android app, which makes use of Google’s MapView class. The requirements are:

  • The map can have several pushpin markers overlaid onto it.
  • When the user double-taps an empty part of the map, a new pushpin is added at the tapped location.
  • When the user taps on an existing pushpin, they see a popup (or similar); no new marker is added.

Despite scouring the SDK and web for tutorials, I could only find examples of either detecting double taps (using primitive timers) or adding a list of markers which could be tapped. After several hours, I finally managed to get somewhere. Check out the call for help at the end of the post though!

Creating the Maps Activity

After creating a new Android project in the SDK, switch it to extend MapActivity and add a MapView to the layout. I’ve also setup the MapView with things like built-in zoom controls in the initialiseMapView() method:

<!-- /AndroidManifest.xml -->
 
  <!-- Required to use the Google Maps library -->
  <application>
    <!-- ... -->  
    <uses-library android:name="com.google.android.maps" />
  </application>
 
  <!-- Request permissions to access location and the internet -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.INTERNET" />
/* /src/com/example/PushPinActivity.java */
package com.example;
 
import android.graphics.drawable.Drawable;
import android.os.Bundle;
 
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
 
class PushPinActivity extends MapActivity {
  private MapView mapView;
  private MapController mapController;
 
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
 
    initialiseMapView();
  }
 
  @Override
  public boolean isRouteDisplayed() {
    return false;
  }
 
  private void initialiseMapView() {
    mapView = (MapView) findViewById(R.id.mapView);
    mapController = mapView.getController();
 
    mapView.setBuiltInZoomControls(true);
    mapView.setSatellite(false);
 
    GeoPoint startPoint = new GeoPoint((int)(40.7575 * 1E6), (int)(-73.9785 * 1E6));
    mapController.setCenter(startPoint);
 
    mapController.setZoom(8);
  }
}
<!-- /res/layout/main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <com.google.android.maps.MapView
    android:id="@+id/mapView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:clickable="true"
    android:apiKey="YOUR_MAPS_API_KEY" />
</LinearLayout>

Adding Overlays

Next, I’ll add an array of Overlay markers to the map. I couldn’t find much high-level documentation on overlays, but from what I could figure out, the ItemizedOverlay class allows you to store a List of OverlayItems. Each OverlayItem is a marker on the map.

For this example, I’ve just used the default Android application icon as a marker. Let’s add a few Overlays in the initialiseOverlays() method, which is called from onStart() (not onCreate()). Note that I’ve also declared a property, placesItemizedOverlay which is a sub-class of ItemizedOverlay. The GeoPoint locations are from another tutorial I found during my research!

/* /src/com/example/PushPinActivity.java */
class PushPinActivity extends MapActivity {
  private PlacesItemizedOverlay placesItemizedOverlay;
 
  // ...
 
  @Override
  public void onStart() {
    super.onStart();
    initialiseOverlays();
  }
 
  private void initialiseOverlays() {
    // Create an ItemizedOverlay to display a list of markers
    Drawable defaultMarker = getResources().getDrawable(R.drawable.icon);
    placesItemizedOverlay = new PlacesItemizedOverlay(this, defaultMarker);
 
    placesItemizedOverlay.addOverlayItem(new OverlayItem(new GeoPoint((int) (40.748963847316034 * 1E6),
            (int) (-73.96807193756104 * 1E6)), "UN", "United Nations"));
    placesItemizedOverlay.addOverlayItem(new OverlayItem(new GeoPoint(
        (int) (40.76866299974387 * 1E6), (int) (-73.98268461227417 * 1E6)), "Lincoln Center",
        "Home of Jazz at Lincoln Center"));
    placesItemizedOverlay.addOverlayItem(new OverlayItem(new GeoPoint(
        (int) (40.765136435316755 * 1E6), (int) (-73.97989511489868 * 1E6)), "Carnegie Hall",
        "Where you go with practice, practice, practice"));
    placesItemizedOverlay.addOverlayItem(new OverlayItem(new GeoPoint(
        (int) (40.70686417491799 * 1E6), (int) (-74.01572942733765 * 1E6)), "The Downtown Club",
        "Original home of the Heisman Trophy"));
 
    // Add the overlays to the map
    mapView.getOverlays().add(placesItemizedOverlay);
  }
}
/* /src/com/example/PlacesItemizedOverlay.java */
package com.example;
 
import java.util.ArrayList;
 
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
 
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;
 
public class PlacesItemizedOverlay extends ItemizedOverlay {
  private Context context;
  private ArrayList items = new ArrayList();
 
  public PlacesItemizedOverlay(Context aContext, Drawable marker) {
    super(boundCenterBottom(marker));
    context = aContext;
  }
 
    public void addOverlayItem(OverlayItem item) {
        items.add(item);
        populate();
    }
 
    @Override
    protected OverlayItem createItem(int i) {
        return items.get(i);
    }
 
    @Override
    public int size() {
        return items.size();
    }
 
    @Override
    protected boolean onTap(int index) {
      OverlayItem item = items.get(index);
      AlertDialog.Builder dialog = new AlertDialog.Builder(context);
      dialog.setTitle(item.getTitle());
      dialog.setMessage(item.getSnippet());
      dialog.show();
 
      return true;
    }
}

If you save and run the code now, you’ll see a map centred on Manhattan with several Android-esque markers scattered around. Tapping on one of the markers will popup an AlertDialog with the marker’s title and description. This is nothing more advanced than the standard Google reference documentation:

Android Markers

Detecting Double Taps

For my app, I needed to detect a double-tap anywhere else on the MapView, except where a Marker was displayed. To do this, I started to look at the GestureDetector class, and set about extending MapView to detect double-taps.

/* /src/com/example/PushPinMapView.java */
package com.example;
 
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.OnGestureListener;
 
import com.google.android.maps.MapView;
 
public class PushPinMapView extends MapView {
  private Context context;
  private GestureDetector gestureDetector;
 
  public PushPinMapView(Context aContext, AttributeSet attrs) {
    super(aContext, attrs);
    context = aContext;
 
    gestureDetector = new GestureDetector((OnGestureListener)context);
    gestureDetector.setOnDoubleTapListener((OnDoubleTapListener) context);
  }
 
  // Override the onTouchEvent() method to intercept events and pass them
  // to the GestureDetector. If the GestureDetector doesn't handle the event,
  // propagate it up to the MapView.
  public boolean onTouchEvent(MotionEvent ev) {
    if(this.gestureDetector.onTouchEvent(ev))
       return true;
    else
      return super.onTouchEvent(ev);
  }
}
/* /src/com/example/PushPinActivity.java */
 
// ...
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.OnDoubleTapListener;
 
class PushPinActivity extends MapActivity implements OnGestureListener, OnDoubleTapListener {
  // ...
 
  /**
   * Methods required by OnDoubleTapListener
   **/
  @Override
  public boolean onDoubleTap(MotionEvent e) {
    GeoPoint p = mapView.getProjection().fromPixels((int)e.getX(), (int)e.getY());
 
    AlertDialog.Builder dialog = new AlertDialog.Builder(this);
    dialog.setTitle("Double Tap");
    dialog.setMessage("Location: " + p.getLatitudeE6() + ", " + p.getLongitudeE6());
    dialog.show();
 
    return true;
  }
 
  @Override
  public boolean onDoubleTapEvent(MotionEvent e) {
    return false;
  }
 
  @Override
  public boolean onSingleTapConfirmed(MotionEvent e) {
    return false;
  }
 
  /**
   * Methods required by OnGestureListener
   **/
  @Override
  public boolean onDown(MotionEvent e) {
    return false;
  }
 
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    return false;
  }
 
  @Override
  public void onLongPress(MotionEvent e) {
  }
 
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    return false;
  }
 
  @Override
  public void onShowPress(MotionEvent e) {
  }
 
  @Override
  public boolean onSingleTapUp(MotionEvent e) {
    return false;
  }
}

Finally, make sure you change your main.xml layout file to use the com.example.PushPinMapView instead of the original Google version. This one caught me out whilst writing this post!

<!-- /res/layout/main.xml -->
  <!-- ....Change com.google.android.maps.MapView to use your custom MapView-->
  <com.example.PushPinMapView
    android:id="@+id/mapView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:clickable="true"
    android:apiKey="YOUR_MAPS_API_KEY" />
  <!-- .... -->

What’s going on?

The custom PushPinMapView creates an instance of GestureDetector and dispatches any touch events (onTouchEvent()) to the designated OnGestureListener. In this code, that is the context instance of PushPinActivity.

If the listener handles the gesture (it’s a double-tap), it shouldn’t not propagate any further (see below). For any gestures that aren’t handled, the GestureDetector propagates the gesture up to other listeners. In this case, it would be handled by the parent MapView gesture handling, which means we don’t have to override things like dragging the map.

Also be sure that your OnGestureListener class imports from the android.view.GestureDetector package.

Call for help…

Whilst functional, the code is still not quite perfect. According to the documentation I’ve found on OnGestureListener, if a method returns true, then the event should not be propagated to any other listeners. However, despite onDoubleTap() returning true in the code above, you’ll find that if you double-tap on one of the OverlayItem markers, both the double-tap dialog and the marker’s dialog are displayed. It seems the MapView is detecting both a single and double-tap.

If you figure out how to stop double-taps on an OverlayItem from triggering a single tap event, please leave a comment and I’ll update the code in the post…Thanks!

Building apps with Rails 3, RSpec, FactoryGirl and Mocha.

Clone the source code from github.

It’s no secret that Rails 3 has been released in beta for a little while now. Like most Rails developers, I was keen to try out some of the new functionality, not least the redesigned Active Record API.

Some heavy duty googling turned up little information on how to get an app started and configured with all the associated goodies we’ve come to expect: rspec, mocha and factory_girl.

This is probably because most of these plugins are in a state of development to bring full compatability with Rails 3. So until that happens, I thought I’d document how I’ve got a skeleton app up and running on Ubuntu using the current development branches.

You can find the latest versions of the code behind on my github. I’ll continue to revise this template as I figure out more about Rails 3, and the plugins.

Installing Rails 3

There’s plenty of posts detailing how to get Rails 3 on your machine. Favouring gems, I followed the official advice:

$ gem install tzinfo builder memcache-client rack rack-test rack-mount
$ gem install erubis mail text-format thor bundler i18n
$ gem install rails --pre
$ rails -v
Rails 3.0.0.beta

With everything set, we can spin a new app using:

$ rails myapp
# Lots of output
$ cd myapp

Bundling Gems

Rails 3 uses the Bundler gem to configure its environment. Bundler brings a lot of benefits, including dependency resolution and ensures that an app’s gem requirements are met.

Your app’s required gems are declared in a Gemfile in your project root. A default Gemfile is provided to load Rails 3 and SQLite. For our project, we’ll update it to require some additional gems:

# Gemfile
source 'http://gemcutter.org'
 
gem "rails", "3.0.0.beta"
gem "sqlite3-ruby", :require => "sqlite3"
 
# Require the haml gem for rendering HAML templates and SASS stylesheets
gem "haml"
 
# FactoryGirl and Shoulda Rails 3 development branches from github
group :thoughtbot do
  # I've included shoulda here in case you use TestUnit. Shoulda macros for RSpec 2 don't
  # work yet though.
  gem "shoulda", :git => "git://github.com/sinefunc/shoulda.git",
                 :branch => "rails3"
 
  gem 'factory_girl', :git => 'git://github.com/thoughtbot/factory_girl.git',
                      :branch => 'rails3',
                      :require => "factory_girl"
end
 
group :test do
  # Install development release of rspec (includes rspec-rails)
  gem "rspec-rails", ">= 2.0.0.a9"
  gem "webrat"
  gem "mocha"
end

Now you can install the bundled gems with:

$ bundle install

Configuring RSpec and FactoryGirl

One of the first tools I felt lost without in Rails 3 was RSpec. Although I tried going back TestUnit, I missed the clarity of RSpec. With RSpec 2 installed by Bundler, the app can be prepared for specs with:

$ rails generate rspec:install

This creates the appropriate spec folder and configuration files. I configured RSpec to use FactoryGirl and Mocha. Notice that in the Gemfile above, Shoulda and FactoryGirl are declared in a group :thoughtbot. Bundler loads the default gems before Rails has initialised environment constants such as Rails.root. By declaring these gems within a group, they can be defered until Rails has setup the environment (Reference).

For RSpec to use FactoryGirl, we ask Bundler to load the :thoughtbot gems in spec_helper.rb:

# specs/spec_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
require 'rspec/rails'
 
# Load in RSpec and Shoulda
# Shoulda macros don't seem to work with RSpec 2. When they do, this is where to require them.
# require 'shoulda'
# require 'shoulda/rspec'
 
require 'factory_girl'
 
# Autoloading of Factories seems to be broken, so manually require the <tt>factories.rb</tt> file
require File.dirname(__FILE__) + "/../spec/factories.rb"
 
# Requires supporting files with custom matchers and macros, etc,
# in ./support/ and its subdirectories.
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}

For now I’ve left shoulda out of the configuration as the Shoulda macros don’t yet work with RSpec 2. I also manually required spec/factories.rb as FactoryGirl’s autoloader also seemed not to be working yet. Before running a spec, you’ll need to declare your factories in spec/factories.rb:

$ touch spec/factories.rb

Finally, switch RSpec to use mocha for mocking objects:

# spec/spec_helper.rb
# == Mock Framework
config.mock_with :mocha

Writing specs

With everything setup, it’s time to write the first spec. As a simple example, I’ll create a User model and its associated spec. With RSpec installed, the standard rails model generator will automatically create an associated spec file:

$ rails generate model user email_address:string password_hash:string password_salt:string
$ rake db:migrate
==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.0041s
==  CreateUsers: migrated (0.0043s) ===========================================

The spec for the User model can now be written using the familiar RSpec dialect:

# spec/models/user_spec.rb
require 'spec_helper'
 
describe User do
  it "should be valid" do
    @user = Factory.create(:user)
    @user.should be_valid
  end
end

I’ve also used Factory.create to build a user, so as before, you’ll need to declare your user factory in spec/factories.rb:

# spec/factories.rb
Factory.define :user do |u|
  u.email_address 'joe.user@example.com'
  u.password 'secret'
end

Finally, to run your specs, you use rake:

$ rake spec

All being well, RSpec should now load up and run your specs. In this example, the spec fails trying to set User#password. To fix this, we’ll add a virtual attribute, password, to the User model that sets a salted, hashed password:

# app/models/user.rb
require 'digest/sha2'
 
class User < ActiveRecord::Base
  def password=(pass)
    @password =  pass
    return if @password.blank?
 
    self.password_salt = Digest::SHA2.hexdigest(Time.now.to_s + rand(32000).to_s)
    self.password_hash = Digest::SHA2.hexdigest(@password + self.password_salt)
  end
 
protected
  def password
    @password
  end
end

With that, another call to rake should report your passing spec:

$ rake spec
.
Finished in 0.062692 seconds
1 example, 0 failures

With this, you can now start to build your Rails 3 app, complete with specs and factories. I’ll continue to update the code on github as I figure out more, and as more plugins become compatible with Rails 3.

References

Rails: Multiple default scopes for ActiveRecord

Default scopes were introduced in Rails 2.3 to allow a default set of options to be applied to any find methods. The common example is to always order a set of results by a given column, e.g:

class Post < ActiveRecord::Base
  # Any calls to Post.find will automatically have the default :order option merged into them
  # Post.find(:all)
  # => SELECT * FROM "posts" ORDER BY "created_at DESC";
  default_scope :order => "created_at DESC"
end

Unlike named_scopes (which I am finding more and more useful every day), I found that default scopes cannot be combined when I tried to use the acts_as_revisable and is_paranoid plugins together:

class Post < ActiveRecord::Base
  acts_as_revisable
  is_paranoid
end

It seems the default scope declared in is_paranoid overrides that of acts_as_revisable. Post.find(:all) will therefore return every revision of Post rather than just the current revision. You can check this out by reversing the plugin order:

class Post < ActiveRecord::Base
  is_paranoid
  acts_as_revisable
end

Now, Post.find(:all) will return only current revisions, but will include any destroyed posts as the acts_as_revisable default scope overrides is_paranoid!

A Solution

This post and code snippet shows a method for declaring multiple default scopes on a model. I’ve not yet tried out the code, though, as one of the commenter’s was kind enough to forkis_paranoid and modify it to merge any existing default scopes. With this forked plugin, Post can be scoped correctly by both plugins.

The fork is available at http://github.com/grioja/is_paranoid/tree/master.

But… is_paranoid is depracated

I noticed that the original is_paranoid plugin has ceased development, so I’m not sure if I’ll continue to use it, although It’s a neat little plugin, and has several forks.

The underlying problem, though, of ActiveRecord allowing only one default_scope to be declared, is something that I’m bound to come up against in the future, so it’s handy to know there is a workaround at least until Rails includes the functionality.

As an aside, Rich Cavanaugh, the developer of acts_as_revisable, has pointed out that the plugin includes some basic is_paranoid functionality already (see Rich’s reply to my original ramblings):

class Post < ActiveRecord::Base
  acts_as_revisable :on_delete => :revise
end

Do you use default_scope? Do you find the single scope a limitation, or do you rely on named scopes? Feel free to discuss in the comments.