Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Version 0.0.1

  • Loading branch information...
commit a73b061cfa52f9ca662ffef68e488ea8da77fd6b 1 parent 7a3f3b0
@eregon authored
View
1  .gitignore
@@ -17,5 +17,6 @@ tmtags
coverage
rdoc
pkg
+.rake_cache
## PROJECT::SPECIFIC
View
55 README.md
@@ -0,0 +1,55 @@
+# app2engine
+
+Convert a Rails 3 app to an Engine.
+
+The structure of a standard Rails application is very similar to what you need for an Engine.
+
+But a few details need to be changed.
+
+This tool intend to do most of them for you.
+
+## Install
+
+ gem install app2engine
+
+## Synopsis
+
+Create an new app to convert it to an Engine (avoid using underscores):
+
+ rails new myengine #
+
+Run `app2engine` in the root directory of this app you want to make an Engine:
+
+ app2engine
+
+Then convert it with Rake:
+
+ rake engine:convert
+
+Follow the instructions: To the main app's Gemfile, add
+
+ gem 'myengine', :path => 'relative/path/to/myengine'
+
+Use extras if you want:
+
+ rake engine:extra
+
+## You are done setting up your engine
+
+If you want a little test:
+
+In your engine's dir:
+
+ rails g controller engine myaction
+
+In your main app's dir:
+
+ rails g controller base myaction
+
+`rails s` and surf on `/engine/myaction` and `/base/myaction` !
+
+(You can also routing is fine with `rake routes`)
+
+## Author
+
+Benoit Daloze
View
17 README.rdoc
@@ -1,17 +0,0 @@
-= app2engine
-
-Description goes here.
-
-== Note on Patches/Pull Requests
-
-* Fork the project.
-* Make your feature addition or bug fix.
-* Add tests for it. This is important so I don't break it in a
- future version unintentionally.
-* Commit, do not mess with rakefile, version, or history.
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
-* Send me a pull request. Bonus points for topic branches.
-
-== Copyright
-
-Copyright (c) 2010 eregon. See LICENSE for details.
View
32 Rakefile
@@ -5,43 +5,19 @@ begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "app2engine"
- gem.summary = %Q{TODO: one-line summary of your gem}
- gem.description = %Q{TODO: longer description of your gem}
+ gem.summary = %Q{Convert a Rails 3 app to an Engine}
+ gem.description = %Q{Ease the convertion of a Rails 3 app in an Engine}
gem.email = "eregontp@gmail.com"
gem.homepage = "http://github.com/eregon/app2engine"
gem.authors = ["eregon"]
- gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+ gem.add_dependency("term-ansicolor")
+ gem.files = Dir['bin/*'] + Dir['lib/**/*']
end
Jeweler::GemcutterTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
end
-require 'rake/testtask'
-Rake::TestTask.new(:test) do |test|
- test.libs << 'lib' << 'test'
- test.pattern = 'test/**/test_*.rb'
- test.verbose = true
-end
-
-begin
- require 'rcov/rcovtask'
- Rcov::RcovTask.new do |test|
- test.libs << 'test'
- test.pattern = 'test/**/test_*.rb'
- test.verbose = true
- end
-rescue LoadError
- task :rcov do
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
- end
-end
-
-task :test => :check_dependencies
-
-task :default => :test
-
require 'rake/rdoctask'
Rake::RDocTask.new do |rdoc|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
View
51 app2engine.gemspec
@@ -0,0 +1,51 @@
+# Generated by jeweler
+# DO NOT EDIT THIS FILE DIRECTLY
+# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{app2engine}
+ s.version = "0.0.1"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["eregon"]
+ s.date = %q{2010-08-04}
+ s.default_executable = %q{app2engine}
+ s.description = %q{Ease the convertion of a Rails 3 app in an Engine}
+ s.email = %q{eregontp@gmail.com}
+ s.executables = ["app2engine"]
+ s.extra_rdoc_files = [
+ "LICENSE",
+ "README.md"
+ ]
+ s.files = [
+ "bin/app2engine",
+ "lib/app2engine.rb",
+ "lib/app2engine/files/__project__.gemspec",
+ "lib/app2engine/files/lib/__project__.rb",
+ "lib/app2engine/files/lib/__project__/engine.rb",
+ "lib/app2engine/files/lib/generators/__project__/migrations/migrations_generator.rb",
+ "lib/app2engine/rake/convert_tasks.rb",
+ "lib/app2engine/rake/extra_tasks.rb",
+ "lib/app2engine/rake/tasks.rb"
+ ]
+ s.homepage = %q{http://github.com/eregon/app2engine}
+ s.rdoc_options = ["--charset=UTF-8"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.3.7}
+ s.summary = %q{Convert a Rails 3 app to an Engine}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+ s.add_runtime_dependency(%q<term-ansicolor>, [">= 0"])
+ else
+ s.add_dependency(%q<term-ansicolor>, [">= 0"])
+ end
+ else
+ s.add_dependency(%q<term-ansicolor>, [">= 0"])
+ end
+end
+
View
10 bin/app2engine
@@ -0,0 +1,10 @@
+#!/usr/bin/env ruby
+$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
+require 'app2engine'
+
+if ARGV.delete("-h") or ARGV.delete("--help")
+ puts "#{File.basename($0)} [dir=.]: install the Rake tasks to the Rakefile (or create it)"
+ puts " The App name is given from the directory. It will also be use in namespaces."
+else
+ App2Engine.install(ARGV.shift || ".")
+end
View
20 lib/app2engine.rb
@@ -0,0 +1,20 @@
+require 'app2engine/rake/tasks'
+
+module App2Engine
+ def install(dir)
+ unless File.directory?(dir) and
+ rakefile = File.join(dir, 'Rakefile') and File.exist?(rakefile) and
+ gemfile = File.join(dir, 'Gemfile') and File.exist?(gemfile)
+ raise "#{dir} is not a rails app"
+ end
+
+ tasks = App2Engine::Rake::Tasks.new
+
+ puts "Appending the App2Engine tasks to the Rakefile"
+ tasks.append_to_file(rakefile, "require 'app2engine/rake/tasks'\nApp2Engine::Rake::Tasks.new")
+
+ puts "Adding app2engine in the Gemfile (necessary for Rake tasks to run)"
+ tasks.append_to_file(gemfile, "gem 'app2engine'")
+ end
+ module_function :install
+end
View
7 lib/app2engine/files/__project__.gemspec
@@ -0,0 +1,7 @@
+Gem::Specification.new do |spec|
+ spec.name = "__DIR__"
+ spec.version = "0.0.1"
+ spec.summary = "__PROJECT__"
+ spec.authors = ["Me"]
+ spec.files = Dir["{app,config,public,lib}/**/*"]
+end
View
3  lib/app2engine/files/lib/__project__.rb
@@ -0,0 +1,3 @@
+module __PROJECT__
+ require '__DIR__/engine' if defined? Rails
+end
View
10 lib/app2engine/files/lib/__project__/engine.rb
@@ -0,0 +1,10 @@
+require "__DIR__" # Require all the real code
+require "rails"
+
+module __PROJECT__
+ class Engine < Rails::Engine
+ initializer "static assets" do |app|
+ app.middleware.use ActionDispatch::Static, "#{root}/public"
+ end
+ end
+end
View
23 lib/app2engine/files/lib/generators/__project__/migrations/migrations_generator.rb
@@ -0,0 +1,23 @@
+require 'rails/generators'
+
+class MigrationsGenerator < Rails::Generators::Base
+ include Rails::Generators::Migration
+
+ def self.source_root
+ @source_root ||= File.expand_path('../../templates', __FILE__)
+ end
+
+ # Implement the required interface for Rails::Generators::Migration.
+ def self.next_migration_number(dirname)
+ if ActiveRecord::Base.timestamped_migrations
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
+ else
+ "%.3d" % (current_migration_number(dirname) + 1)
+ end
+ end
+
+ def create_migration_file
+ # migration_template 'create_posts.rb', 'db/migrate/create_blog_posts.rb'
+ # migration_template '__DIR___create_posts.rb', 'db/migrate/__DIR___create_posts.rb'
+ end
+end
View
56 lib/app2engine/rake/convert_tasks.rb
@@ -0,0 +1,56 @@
+module App2Engine
+ module Rake
+ class Tasks
+ def convert_tasks
+ tasks = %w[gemspec routes hierarchy initializers generators]
+ task :convert => tasks.map { |t| "engine:convert:" << t } do
+ puts
+ puts "Now your app should be ready to be used as an Engine".blue
+ puts "You have to add this to you main app's Gemfile:".red
+ puts "gem '#{@dir}', :path => 'relative/path/to/#{@dir}'"
+ puts "You may want to remove the dependency to app2engine in the Engine's Gemfile".blue
+ end
+ namespace :convert do
+ tasks.each { |t| send(t) }
+ end
+ end
+
+ def gemspec
+ define_task(:gemspec, "add Jeweler to the Rakefile to allow to build a gem which can be referenced from the main app") do
+ add_file('__project__.gemspec')
+ end
+ end
+
+ def routes
+ define_task(:routes, "Change routes to not have a reference to the application, but to the main app") do
+ replace_line('config/routes.rb', "#{@project}::Application.routes.draw do", "Rails.application.routes.draw do")
+ end
+ end
+
+ def hierarchy
+ define_task(:hierarchy, "add the basic hierarchy for the Engine") do
+ add_file('lib/__project__.rb')
+ mkdir("lib/#{@dir}")
+ add_file('lib/__project__/engine.rb')
+
+ mkdir("app/controllers/__project__")
+ mkdir("app/models/__project__")
+ mkdir("app/views/__project__")
+ end
+ end
+
+ def initializers
+ define_task(:initializers, "remove initializers as they would conflict and create NameError") do
+ move_dir('config/initializers', 'config/org_initializers')
@hjblok
hjblok added a note

Instead of renaming the whole directory, you could also change all occurrences of #{@project}::Application to Rails.application (like you did with the config/routes.rb). That won't break your local application, doesn't generate depricate warnings and the apps using it as gem also keep working.

@eregon Owner
eregon added a note

Yes, I did think to that,
but I pulled the idea away because the Engine should not modify the global configuration.

In current setup, if I modify with Rails.application, it will modify the secret_token and the session_store.

I also believe all the initializers of the engine should be in lib/project/engine.rb

But that's not a reason to move the whole directory. I will then just comment these 2 lines.

Don't hesitate to correct me if I am wrong ;)

@eregon Owner
eregon added a note

Done !
(and sorry for this huge commit, I wanted a "all works" or "nothing")

@hjblok
hjblok added a note

Yes that's right: all engine initializers should be in a separate folder. I've tried to separate the Engine config files from the App config files, specifying different paths within the engine.rb:

paths.config              = "lib/project/config"
paths.config.initializers = "lib/project/config/initializers"
paths.config.locales      = "lib/project/config/locales"
paths.config.routes       = "lib/project/config/routes.rb"

But somehow that doesn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ end
+ end
+
+ def generators
+ define_task(:generators, "add the basic code for generators (needed for migrations)") do
+ mkdir('lib/generators/__project__/migrations/templates')
+ add_file('lib/generators/__project__/migrations/migrations_generator.rb')
+ end
+ end
+ end # Tasks
+ end # Rake
+end # App2Engine
View
29 lib/app2engine/rake/extra_tasks.rb
@@ -0,0 +1,29 @@
+module App2Engine
+ module Rake
+ class Tasks
+ SASS = <<SASS
+ initializer "sass" do |app|
+ require 'sass/plugin/rack'
+ template_location = __PROJECT__::Engine.root.join('public/stylesheets/sass').to_s
+ css_location = __PROJECT__::Engine.root.join('public/stylesheets').to_s
+ Sass::Plugin.add_template_location(template_location, css_location)
+ end
+SASS
+
+ def extra_tasks
+ tasks = %w[sass]
+ task :extra => tasks.map { |t| "engine:extra:" << t }
+ namespace :extra do
+ tasks.each { |t| send(t) }
+ end
+ end
+
+ def sass
+ define_task(:sass, "configure the project to be used with Sass") do
+ append_in_class('lib/__project__/engine.rb', SASS)
+ end
+ end
+
+ end # Tasks
+ end # Rake
+end # App2Engine
View
140 lib/app2engine/rake/tasks.rb
@@ -0,0 +1,140 @@
+require 'fileutils'
+
+require 'rake'
+
+require 'app2engine/rake/convert_tasks'
+require 'app2engine/rake/extra_tasks'
+
+require 'term/ansicolor'
+class String
+ [:green, :red, :black, :blue].each { |method|
+ define_method(method) {
+ Term::ANSIColor.send(method, self)
+ }
+ }
+end
+
+module App2Engine
+ module Rake
+ class Tasks
+ FILES_PATH = File.expand_path("../../files", __FILE__)
+
+ def initialize
+ @dir = File.basename(File.expand_path("."))
+ @project = @dir.split(/[^A-Za-z0-9]/).map(&:capitalize).join # Camelize
+
+ namespace :engine do
+ convert_tasks
+ extra_tasks
+ end
+ desc "Alias for engine:convert"
+ task :engine => "engine:convert"
+ end
+
+ def define_task(name, description, &block)
+ desc description
+ task(name) {
+ puts name.to_s.capitalize.blue
+ block.call
+ }
+ end
+
+ # Templates conventions
+ def resolve_contents(contents)
+ contents.gsub("__PROJECT__", @project).gsub("__DIR__", @dir)
+ end
+
+ def resolve_name(name)
+ name.gsub("__project__", @dir)
+ end
+
+ def status status
+ puts " #{status}"
+ end
+
+ def already_done what
+ status "already done (#{what})".black
+ end
+
+ def file_contents file
+ resolve_contents File.read(File.join(FILES_PATH, file))
+ end
+
+ def mkdir dir
+ dir = resolve_name(dir)
+ if File.directory? dir
+ already_done dir
+ else
+ FileUtils.mkdir_p(dir)
+ status "Create #{dir}/".green
+ end
+ end
+
+ def move_dir dir, to
+ if File.directory? to
+ already_done dir
+ else
+ FileUtils.mv(dir, to)
+ status "Move #{dir} to #{to}".green
+ end
+ end
+
+ def add_file file
+ contents = file_contents(file)
+ file = resolve_name(file)
+ if File.exist? file
+ already_done file
+ else
+ File.open(file, 'w') { |fh| fh.write(contents) }
+ status "Create #{file}".green
+ end
+ end
+
+ def append_to_file file, contents
+ file = resolve_name(file)
+ if File.read(file).include?(contents)
+ already_done file
+ else
+ File.open(file, 'a') { |fh|
+ fh.puts
+ fh.puts contents
+ }
+ status "Append #{file}".green
+ end
+ end
+
+ def append_in_class(file, what)
+ file = resolve_name(file)
+ what = resolve_contents(what)
+ if File.read(file).include?(what)
+ already_done file
+ else
+ lines = File.readlines(file)
+ class_indent = lines.find { |line| line =~ /^\s*class .+$/ }.split(//).index('c')
+ class_end = lines.rindex { |line| line =~ /^\s{#{class_indent}}end\s*$/ }
+ what = what.split("\n").map { |line| line.chomp + "\n" }
+ lines = lines[0...class_end] + ["\n"] + what + lines[class_end..-1]
+ File.open(file, 'w') { |fh| fh.write(lines.join) }
+ status "Append #{file}".green
+ end
+ end
+
+ def replace_line(file, line, by)
+ line = line.chomp + "\n"
+ by = by.chomp + "\n"
+ lines = File.readlines(file)
+ if lines.include? by
+ already_done(file)
+ else
+ if i = lines.index(line)
+ lines[i] = by
+ File.open(file, 'w') { |fh| fh.write(lines.join) }
+ status "Edit #{file}".green
+ else
+ status "#{file}: line '#{line}' not found".red
+ end
+ end
+ end
+ end # Tasks
+ end # Rake
+end # App2Engine
View
10 test/helper.rb
@@ -1,10 +0,0 @@
-require 'rubygems'
-require 'test/unit'
-require 'shoulda'
-
-$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
-$LOAD_PATH.unshift(File.dirname(__FILE__))
-require 'app2engine'
-
-class Test::Unit::TestCase
-end
View
7 test/test_app2engine.rb
@@ -1,7 +0,0 @@
-require 'helper'
-
-class TestApp2engine < Test::Unit::TestCase
- should "probably rename this file and start testing for real" do
- flunk "hey buddy, you should probably rename this file and start testing for real"
- end
-end
Please sign in to comment.
Something went wrong with that request. Please try again.