Missing host to link to!

So I was outputting URL from a rails model with

Rails.application.routes.url_helpers.something_url(id)

but my specs were complaining with

Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true

after some googling and trial and errors I found that this line would did the trick. Put it in your test_helper or spec_helper

Rails.application.routes.default_url_options[:host] = 'localhost:3000'

cheers :D

Rails 3, unit test, and autotest

This is just a reminder for myself, I finally can run autotest with this setup on my mac:

Gemfile content:

snip ...
group :development, :test do
  gem 'webrat'
  gem 'mocha'
  gem 'ZenTest'
  gem 'autotest-rails'
  gem 'autotest-growl'
  gem 'autotest-fsevent'
end

RAILS_ROOT/.autotest (create one if it doesn’t exist) content:

require "ZenTest"
require "autotest/rails"
require "autotest/growl"
require "autotest/fsevent"
Autotest.add_hook :initialize do |autotest|
  %w{.git .svn .hg .DS_Store ._* vendor tmp log doc config .rvmrc Gemfile .autotest README Rakefile}.each do |exception|
    autotest.add_exception(exception)
  end
end

then go to your RAILS_ROOT directory, run bundle exec autotest, and watch those nice green growl pops up :D

RailsInstaller with ruby 1.9.2

UPDATE: RailsInstaller 2 has been released. It include ruby 1.9.2 and rails 3.1, read it here and download it here.

Railsinstaller from railsinstaller.org ships with ruby 1.8.7 by default, but if you want to use ruby 1.9.2, these steps might help you out.

  1. Download and install railsinstaller (default to C:\RailsInstaller, lets call this ROOT_DIR)
  2. Download and install Ruby 1.9.2 from rubyinstaller.org (railsinstaller only compatible with ruby from rubyinstaller.org) to ROOT_DIR\ruby192
  3. Edit file setup_environment.bat on ROOT_DIR\ruby1.8.7 (you can use notepad or notepad++)
  4. On line 12 in setup_environment.bat, change it to: SET RUBY_DIR=C:\RailsInstaller\Ruby192
  5. On line 27 change the line to: SET PATH=%RUBY_DIR%\bin;%RUBY_DIR%lib\ruby\gems\1.9.1\bin;%ROOT_DIR%\DevKit\bin;%ROOT_DIR%\Git\cmd;%PATH%
  6. Save the file
  7. Open railsinstaller console from Start menu and make sure the loaded ruby version is 1.9.2 by running ‘ruby -v’ command on the console
  8. Still on the console, go to devkit folder on ROOT_DIR\DevKit by running ‘cd C:\RailsInstaller\DevKit’ command
  9. Inside the devkit folder run ‘ruby dk.rb init’
  10. Still inside the devkit folder, run the ‘ruby dk.rb install –force’ command (note the 2 dash before force)
  11. If nothing went wrong then you should be able to install the various ruby gems that’s available out there (Ex. gem install rails).
  12. You need to install rails gem again (and any gems that you want to use) because the default rails gem that come with railsinstaller is on the ruby 1.8.7 folder while now you’ll be using the gems in the ruby192 folder.

And that’s it, now you can enjoy railsinstaller with ruby 1.9.2 :D

Problem with paperclip 2.3.4

I just upgrade my rails application to rails 2.3.10 because of this post, my application is using paperclip and by that time it was using paperclip 2.3.4, and on rails 2.3.9 everything is going well. But as soon as I upgraded to rails 2.3.10 when I run ./script/server I got this error:

=> Booting Mongrel
=> Rails 2.3.10 application starting on http://0.0.0.0:3001
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.10/lib/active_support/dependencies.rb:466:in `load_missing_constant': 
uninitialized constant Paperclip::Glue (NameError)

After googling a while, none of the results was involving rails 2.3.10, but most of the answers suggesting to install paperclip version 2.3.1.1, so I think I’ll give it a try. So I change the line in my Gemfile to gem ‘paperclip’, ‘~> 2.3.1.1’, and then I run bundle install, after that I try to run ./script/server, and it run!

Missing the Rails 2.3.8 gem after bundle install, solved

Ok, basically I have just clone this rails 2.3.8 app which use bundler, and it told me to do “bundle install”, so I did, and it run without any problem, so far so good. After ‘bundle install’ finished successfully I try to run ‘rake db:create’ and it throws this error message :

Missing the Rails 2.3.8 gem. Please `gem install -v=2.3.8 rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.

I said, WTF? I do have rails 2.3.8 installed, in fact I’ve been using it for a while without any problem, so why is this new app cannot find it? google to the rescue! I found this post from heroku that explain the problem, and one of the solution is to add the Rails 2.3.8 gem to your gem manifest or Gemfile, so I did. Put this in your Gemfile just after the line that says ‘source :rubygems’

source :rubygems
gem 'rails', '2.3.8'

After that I try to run ‘rake db:create’ again, and it works! that’s another trick in my rails arsenal :)

Tudulis with Ruby on Rails

Tudulis which originally written with PHP and CakePHP is now have its clone. Meet rtudulis, just like tudulis it’s a web-based, free, todo list and tasks management application and most importantly it is written with Ruby on Rails instead, how cool is that? :D

The reasons behind why I created rtudulis are mainly to get to know about rails application deployment process (using capistrano). With the creation of this rails app I have to deal with capistrano and its several deployment strategies which I don’t have any experience before. And just like tudulis, the source code for rtudulis is available on my github repository in case anybody want to use it. Currently it doesn’t have all the feature of tudulis (PDF creation and twitter login) since it’s still under development, but if you want to try out the live application, you can go to http://r.tudulis.com and try it out.

Well, that’s all for now, happy forking! :D

Some screenshots :

This slideshow requires JavaScript.

Spanish translation for tudulis.com

In my previous post, I mention that tudulis.com is now support internationalization or i18n, and it’s currently only support English and Indonesian. But thanks to the generosity of Rodrigo Perez, tudulis.com now also support Spanish. Since I can only speak English (beside Indonesian of course), I’ll be very happy if there’s somebody who want to do the translation to other languages :)

To translate to other language, you can copy the eng directory in app/locale directory, change the name to the language code you’re about to translate (like esp for spanish, eng for english, or ind for indonesian), refer to ISO 639-2 for a list of available language code, put it back in the same directory as the eng directory and edit the LC_MESSAGES/default.po file with any application that can edit po files (like poedit), and place the resulting default.mo file in the same directory as the default.po file, and that’s it. After you done all that you can email me if you want your translation to be added to tudulis.com :)

tudulis now support i18n

Just a quick note, tudulis, the free, online, todo list management app is now support internationalization or i18n for short. Currently it only support english and indonesian localization, but you can add your own translation too. Just follow this instruction to add your locale, after you get the source code, or you can fork the source code and send me a pull request. that’s it for now and happy translating :)

PS: some screenshots for the localize interface

Dynamically add and remove input field in rails without javascript

when dealing with nested form field using accepts_nested_attributes_for in ruby on rails, I always tempted to ada feature where the user can dynamically add or remove form field on the form. Usually people achieve this with the help of javascript function. But I want to use plain html for the sake of ‘progressive enhancement’, if that’s works than I can apply some javascript to make it more interactive, it turns out to be pretty simple with ruby on rails.

first, the models

# recipe model
class Recipe < ActiveRecord::Base
  has_many :ingredients
  accepts_nested_attributes_for :ingredients, :allow_destroy => true

  validates_presence_of :name
end

# Ingredient model
class Ingredient < ActiveRecord::Base
  belongs_to :recipe
end

then the controller

class RecipesController < ApplicationController def index @recipes = Recipe.all end def show @recipe = Recipe.find(params[:id]) end def new @recipe = Recipe.new @recipe.ingredients.build # build ingredient attributes, nothing new here end def create @recipe = Recipe.new(params[:recipe]) if params[:add_ingredient] # add empty ingredient associated with @recipe @recipe.ingredients.build elsif params[:remove_ingredient] # nested model that have _destroy attribute = 1 automatically deleted by rails else # save goes like usual if @recipe.save flash[:notice] = "Successfully created recipe." redirect_to @recipe and return end end render :action => 'new' end def edit @recipe = Recipe.find(params[:id]) end def update @recipe = Recipe.find(params[:id]) if params[:add_ingredient] # rebuild the ingredient attributes that doesn't have an id unless params[:recipe][:ingredients_attributes].blank? for attribute in params[:recipe][:ingredients_attributes] @recipe.ingredients.build(attribute.last.except(:_destroy)) unless attribute.last.has_key?(:id) end end # add one more empty ingredient attribute @recipe.ingredients.build elsif params[:remove_ingredient] # collect all marked for delete ingredient ids removed_ingredients = params[:recipe][:ingredients_attributes].collect { |i, att| att[:id] if (att[:id] && att[:_destroy].to_i == 1) } # physically delete the ingredients from database Ingredient.delete(removed_ingredients) flash[:notice] = "Ingredients removed." for attribute in params[:recipe][:ingredients_attributes] # rebuild ingredients attributes that doesn't have an id and its _destroy attribute is not 1 @recipe.ingredients.build(attribute.last.except(:_destroy)) if (!attribute.last.has_key?(:id) && attribute.last[:_destroy].to_i == 0) end else # save goes like usual if @recipe.update_attributes(params[:recipe]) flash[:notice] = "Successfully updated recipe." redirect_to @recipe and return end end render :action => 'edit' end def destroy @recipe = Recipe.find(params[:id]) @recipe.destroy flash[:notice] = "Successfully destroyed recipe." redirect_to recipes_url end end

the views ( form partial )

<% form_for @recipe do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.label :description %><br />
    <%= f.text_area :description, :rows => 4, :cols => 50 %>
  </p>
  <h3>Ingredients</h3>
  <% f.fields_for :ingredients do |ing| %>
    <p>
      <%= ing.label :name %>
      <%= ing.text_field :name, :size => 50 %>
      <%= ing.check_box :_destroy %>
      <%= ing.label :_destroy, 'delete' %>
    </p>
  <% end -%>
  <p>
    <%= f.submit 'Add ingredient', :name => "add_ingredient" %>
    <%= f.submit 'Delete checked ingredients', :name => "remove_ingredient" %>
    <%= f.submit %>
  </p>
<% end %>

and the code in actions…

now that the basic foundation is working, adding some javascript to add an remove nested fields should be fun :)