Tuesday 24 December 2013

Google Cloud Storage with Carrierwave/Mongoid (Rails 4.0)

Have just been creating a new Rails 4 app and am looking to use Google Cloud Storage for the first time. Previously I had been using Amazon S3

To upload images I'll be using carrierwave.

GemFile

# for image uploading
gem 'carrierwave'
gem "carrierwave-mongoid", git: "git://github.com/jnicklas/carrierwave-mongoid.git"
gem 'mongoid-grid_fs', github: 'ahoward/mongoid-grid_fs'
gem 'fog'
gem 'rmagick'

config/initializers/carrierwave.rb


require 'fog'
require 'rails'
require 'carrierwave'


CarrierWave.configure do |config|
  
  config.root = Rails.root.join('tmp')
  config.cache_dir = 'carrierwave'
  
  config.fog_credentials = {
    :provider                         => 'Google',
    :google_storage_access_key_id     => 'xxxxxx',
    :google_storage_secret_access_key => 'xxxxxx'
  }
  config.fog_directory = 'bucket_name'

end

Here's how to find the details you need:

app/uploaders/image_uploader.rb

class ImageUploader < CarrierWave::Uploader::Base

  # Include RMagick or MiniMagick support:
  include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  include Sprockets::Rails::Helper

  # Choose what kind of storage to use for this uploader:
  storage :fog

end
Important that you don't forget to include Sprockets::Rails::Helper in Rails 4+. Also, mongodb does not automatically save associated records so be sure to use cascade_callbacks or autosave options in your model depending on the relation - more info.

You should be good to go after this :)

Friday 28 June 2013

Upgrade Rails 3 app to Rails 4.0.0

Rails 4.0.0 stable version has been released recently, so you may want to upgrade an existing app to the new version of Rails.
First you might want to upgrade to the latest Ruby version 2.0.0, which is recommended with Rails 4. If you are using Ruby Version Manager (RVM), you do as follows:
$ rvm list known
NB. The RVM list should contain ruby-2.0.0. If it doesn't, then you may have to update RVM. You can follow the instructions from here
$ rvm install ruby-2.0.0
$ rvm use ruby-2.0.0 
Your rails app will now be using ruby 2.0.
You'll need to run bundle install to load your gems into the new ruby version.
$ bundle install
Now we can upgrade rails.

gemfile.rb

gem 'rails', '4.0.0'
$ bundle install
NB. If bundle install does work first of all, you may have to remove your Gemfile.lock and/or remove versioning from some of your gems so that dependencies are resolved.
I also found that I needed to update the railties gem.

You may also find that you get a Load Error when starting the rails server:

../config/application.rb:7:in `require': cannot load such file -- active_resource/railtie (LoadError)

If that is the case, then you will need to comment out/remove following line from application.rb:

require "active_resource/railtie"

If you do actually need active resource then it can still be added as a gem.

Saturday 22 June 2013

FactoryGirl with polymorphic associations

Polymorphic associations are very common within a Ruby on Rails app and one of the more popular testing libraries people use is FactoryGirl.

Here we look at how to setup FactoryGirl models to be used in a polymorphic situation.

The issue was first raised on StackOverflow here

For our demonstration, here is a common polymorphic model setup:

FactoryGirl.define do
class Image < ActiveRecord::Base
  mount_uploader :photo, ImageUploader
  belongs_to :imageable, :polymorphic => true

end

class Slideshow < ActiveRecord::Base
  has_many :images, :as => :imageable, :dependent => :destroy

end

class Article < ActiveRecord::Base
  has_many :images, :as => :imageable, :dependent => :destroy

end

And this is how you can build your factories in FactoryGirl to deal with the polymorphic association:

FactoryGirl.define do
  factory :slideshow_image, class: "Image" do
    association :imageable, :factory => :slideshow
    # other attributes for slideshow model
  end
  
  factory :article_image, class: "Image" do
    association :imageable, :factory => :article
    # other attributes for article model
  end
end

This will allow you to call the following:

before(:each) do
  @article_image = FactoryGirl.create(:article_image)
  @article = @article_image.article
end

This provides you with the image, along with the associated article for testing :)