Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting rails 2 generators to rails 3?

How difficult is it to convert rails 2 generators to rails 3? I keep finding useful plugins but then finding that the generators are only for rails 2. I realize some of it is just a convenience, but if migrating the generator to rails 3 is as simple as tweaking a few lines in the generator code, I would be down to just do that (and commit the work to github for future users as well).

Here's one such generator I've been thinking about using, for example (from feedback)

require File.expand_path(File.dirname(__FILE__) + "/lib/insert_routes.rb")

class FeedbackFormGenerator < Rails::Generator::Base

  attr_accessor :name, 
    :model_class_name,
    :controller_class_name,
    :helper_class_name,
    :mailer_class_name


  def initialize(runtime_args, runtime_options = {})
    super
    @name = (runtime_args[0] || "feedback").downcase
    @model_class_name = name.classify
    @mailer_class_name = "#{@model_class_name}Mailer"
    @controller_class_name = "#{@model_class_name.pluralize}Controller"
    @helper_class_name = "#{@model_class_name.pluralize}Helper"
    #@js_framework = (runtime_options[''])

  end

  def manifest
    record do |m|

      puts "hello"
      add_model(m)
      add_mailer(m)
      add_controller(m)
      add_helper(m)
      add_views(m)
      add_routes(m)
      add_unit_test(m)
      add_functional_test(m)
      add_stylesheet(m)
      add_javascript(m)
      add_images(m)
    end
  end


  def add_stylesheet(m)
    m.directory 'public/stylesheets'
    m.file 'feedback.css', 'public/stylesheets/feedback.css'

  end

  def add_javascript(m)
    m.directory 'public/javascripts'
    file_name = options[:jquery] ? 'jquery.feedback.js' : 'prototype.feedback.js'
    m.file file_name, "public/javascripts/#{file_name}"
  end

  def add_images(m)
    m.directory 'public/images/feedback'
    m.file "images/feedback_tab.png", "public/images/feedback/feedback_tab.png"
    m.file "images/feedback_tab_h.png", "public/images/feedback/feedback_tab_h.png"
    m.file "images/closelabel.gif", "public/images/feedback/closelabel.gif"
    m.file "images/loading.gif", "public/images/feedback/loading.gif"
  end

  def add_model(m)
    m.template 'feedback_model.rb.erb', "app/models/#{name}.rb"
  end

  def add_mailer(m)
    m.template 'feedback_mailer.rb.erb', "app/models/#{name}_mailer.rb"
    m.directory "app/views/#{name}_mailer"
    m.file 'views/feedback_mailer/feedback.html.erb', "app/views/#{name}_mailer/feedback.html.erb"

  end

  def add_controller(m)
    m.template 'feedbacks_controller.rb.erb', "app/controllers/#{name.pluralize}_controller.rb"
  end

  def add_helper(m)
    template_name = options[:jquery] ? 'feedbacks_helper.rb.jquery.erb' : 'feedbacks_helper.rb.prototype.erb'
    m.template template_name, "app/helpers/#{name.pluralize}_helper.rb"
  end

  def add_views(m)
    m.directory "app/views/#{name.pluralize}"
    m.file 'views/feedbacks/new.html.erb', "app/views/#{name.pluralize}/new.html.erb"
  end

  def add_routes(m)
    m.route_name "new_feedback", "feedbacks/new", {:controller => name.pluralize, :action => "new"}
    m.route_name "feedback", "feedbacks", {:controller => name.pluralize, :action => "create"}
  end

  def add_unit_test(m)
    m.template 'feedback_test.rb.erb', "test/unit/#{name}_test.rb"
    m.template 'feedback_mailer_test.rb.erb', "test/unit/#{name}_mailer_test.rb"
  end

  def add_functional_test(m)
    m.template 'feedbacks_controller_test.rb.erb', "test/functional/#{name.pluralize}_controller_test.rb"    
  end

  protected 

  def add_options!(opt)
    opt.separator ''
    opt.separator 'Options:'
    opt.on("--jquery",
      "Use jquery Javascript framework, default is Prototyp")           { |v| options[:jquery] = true }
  end
end
like image 327
unsorted Avatar asked Oct 14 '22 17:10

unsorted


1 Answers

It really depends on the sort of generator it is. A lot of the internals of Rails have changed a lot between 2 and 3. Let me show you my recent experience in converting a very simple migration generator which I have in one of my apps from 2 to 3.

Here's the 2 code:

class LegacyMigrationGenerator < MigrationGenerator
  def manifest
    record do |m|
      m.migration_template 'legacy_migration.rb', 'db/migrate'
    end
  end
end

And here's the 3 code:

require 'rails/generators/active_record'

class LegacyMigrationGenerator < ActiveRecord::Generators::Base
  source_root File.expand_path('../templates', __FILE__)
  def create_migration_file
    migration_template "legacy_migration.rb", "db/migrate/#{file_name}.rb"
  end
end

So, as you can see - totally different method to override, had to inherit from a generator now, had to call this source_root now (used to be automatic), and no longer calling the migration_template in a block.

This small conversion took me about three hours to hunt down all the pieces through the source. The best part was that I didn't have to change my template at all (and I believe that will be true for most generators).

All that being said, I think migration generation is probably the least well documented, looking at the generator guide it really doesn't seem too challenging to recreate generators in Rails3. Definitely worth taking a crack at in my opinion.

Also, I know that one of the authors of that guide has a book coming out soon with a chapter all about generators - so it's definitely something which will be getting more attention.

like image 112
smathy Avatar answered Oct 30 '22 13:10

smathy