diff --git a/lib/generators/addon/USAGE b/lib/generators/addon/USAGE new file mode 100644 index 000000000..a1e49aa05 --- /dev/null +++ b/lib/generators/addon/USAGE @@ -0,0 +1,6 @@ +------------------------- +This generator creates a new sciNote addon inside /addons folder. + +The NAME parameter should be a fully namespaced addon name, containing +any potential modules (e.g. Scinote::MyOrganization::MyAddon). +------------------------- \ No newline at end of file diff --git a/lib/generators/addon/addon_generator.rb b/lib/generators/addon/addon_generator.rb new file mode 100644 index 000000000..3decd5e77 --- /dev/null +++ b/lib/generators/addon/addon_generator.rb @@ -0,0 +1,217 @@ +class AddonGenerator < Rails::Generators::NamedBase + source_root File.expand_path('../templates', __FILE__) + argument :name, type: :string + + def initialize_vars + @modules = name.split('::') + @folders = @modules.map(&:underscore) + @full_underscore_name = @folders.join('_') + @folders_path = @folders.join('/') + @addon_name = @folders[-1] + end + + def create_app + # app/assets + create_file( + "addons/#{@addon_name}/app/assets/images/#{@folders_path}/.keep" + ) + create_file( + "addons/#{@addon_name}/app/assets/" \ + "javascripts/#{@folders_path}/application.js" + ) + copy_file( + 'application.scss', + "addons/#{@addon_name}/app/assets/" \ + "stylesheets/#{@folders_path}/application.scss" + ) + + # app/controllers + create_file( + "addons/#{@addon_name}/app/controllers/" \ + "#{@folders_path}/application_controller.rb" + ) do + embed_into_modules do + "class ApplicationController < ::ApplicationController\nend\n" + end + end + + # app/decorators + create_file("addons/#{@addon_name}/app/decorators/controllers/.keep") + create_file("addons/#{@addon_name}/app/decorators/models/.keep") + + # app/helpers + create_file( + "addons/#{@addon_name}/app/helpers/" \ + "#{@folders_path}/application_helper.rb" + ) do + embed_into_modules do + "module ApplicationHelper\nend\n" + end + end + + # app/models + create_file("addons/#{@addon_name}/app/models/#{@folders_path}/.keep") + + # app/overrides + create_file("addons/#{@addon_name}/app/overrides/.keep") + + # app/views + create_file( + "addons/#{@addon_name}/app/views/layouts/#{@folders_path}/.keep" + ) + create_file( + "addons/#{@addon_name}/app/views/#{@folders_path}/overrides/.keep" + ) + end + + def create_bin + file_path = "addons/#{@addon_name}/bin/rails" + copy_file('rails', file_path) + gsub_file(file_path, '${FOLDERS_PATH}', @folders_path) + end + + def create_config + # config/initializers + create_file( + "addons/#{@addon_name}/config/initializers/" \ + "#{@folders_path}/constants.rb" + ) do + embed_into_modules do + "class Constants\nend\n" + end + end + + # config/locales + create_file( + "addons/#{@addon_name}/config/locales/en.yml" + ) do + "en:\n" + end + + # config/routes.rb + create_file( + "addons/#{@addon_name}/config/routes.rb" + ) do + "#{name}::Engine.routes.draw do\nend\n" + end + end + + def create_db + create_file("addons/#{@addon_name}/db/migrate/.keep") + end + + def create_lib + # lib/.../engine.rb + file_path = "addons/#{@addon_name}/lib/#{@folders_path}/engine.rb" + create_file( + file_path + ) do + embed_into_modules { File.read("#{@source_paths[0]}/engine.rb") } + end + gsub_file(file_path, '${FULL_UNDERSCORE_NAME}', @full_underscore_name) + gsub_file(file_path, '${NAME}', name) + gsub_file(file_path, '${FOLDERS_PATH}', @folders_path) + gsub_file(file_path, '${ADDON_NAME}', @addon_name) + + # lib/.../version.rb + create_file( + "addons/#{@addon_name}/lib/" \ + "#{@folders_path}/version.rb" + ) do + embed_into_modules do + "VERSION = '0.0.1'.freeze\n" + end + end + + # lib/.../.rb + folders_path_2 = @folders[0..-2].join('/') + file_name = @folders[-1] + create_file( + "addons/#{@addon_name}/lib/" \ + "#{folders_path_2}/#{file_name}.rb" + ) do + embed_into_modules { '' } + end + + # lib/tasks + create_file("addons/#{@addon_name}/lib/tasks/#{@folders_path}/.keep") + + # lib/engine.rb + create_file( + "addons/#{@addon_name}/lib/#{@full_underscore_name}.rb" + ) do + "require '#{@folders_path}'\n" \ + "require '#{@folders_path}/engine'\n" + end + end + + def create_test + # test/fixtures + create_file("addons/#{@addon_name}/test/fixtures/#{@folders_path}/.keep") + + # test/integrations + create_file("addons/#{@addon_name}/test/integrations/.keep") + + # test/models + create_file("addons/#{@addon_name}/test/models/#{@folders_path}/.keep") + + # test/engine_test + create_file( + "addons/#{@addon_name}/test/" \ + "#{@folders_path}/#{@addon_name}_test.rb" + ) do + "require 'test_helper'\n\n" \ + "class #{name}::Test < ActiveSupport::TestCase\n" \ + " test 'truth' do\n" \ + " assert_kind_of Module, #{name}\n" \ + " end\n" \ + "end\n" + end + + # test/test_helper.rb + copy_file('test_helper.rb', "addons/#{@addon_name}/test/test_helper.rb") + end + + def create_root + copy_file('.gitignore', "addons/#{@addon_name}/.gitignore") + copy_file('Gemfile', "addons/#{@addon_name}/Gemfile") + copy_file('LICENSE.txt', "addons/#{@addon_name}/LICENSE.txt") + copy_file('README.md', "addons/#{@addon_name}/README.md") + + # Rakefile + file_path = "addons/#{@addon_name}/Rakefile" + copy_file('Rakefile', file_path) + gsub_file(file_path, '${NAME}', name) + + # .gemspec + file_path = "addons/#{@addon_name}/#{@full_underscore_name}.gemspec" + copy_file('.gemspec', file_path) + gsub_file(file_path, '${FOLDERS_PATH}', @folders_path) + gsub_file(file_path, '${FULL_UNDERSCORE_NAME}', @full_underscore_name) + gsub_file(file_path, '${NAME}', name) + end + + private + + def embed_into_modules + res = '' + @modules.each_with_index do |mod, i| + res << ' ' * i + res << "module #{mod}\n" + end + block_res = yield + block_res.each_line do |line| + if line == "\n" + res << "\n" + else + res << ' ' * @modules.count + res << line + end + end + @modules.each_with_index do |_, i| + res << ' ' * (@modules.count - 1 - i) + res << "end\n" + end + res + end +end diff --git a/lib/generators/addon/templates/.gemspec b/lib/generators/addon/templates/.gemspec new file mode 100644 index 000000000..019ef400b --- /dev/null +++ b/lib/generators/addon/templates/.gemspec @@ -0,0 +1,25 @@ +$:.push File.expand_path('../lib', __FILE__) + +# Maintain your gem's version: +require '${FOLDERS_PATH}/version' + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = '${FULL_UNDERSCORE_NAME}' + s.version = ${NAME}::VERSION + s.authors = [''] + s.email = [''] + s.homepage = '' + s.summary = '' + s.description = '' + s.license = '' + + s.files = Dir['{app,config,db,lib}/**/*', + 'LICENSE.txt', + 'Rakefile', + 'README.rdoc'] + s.test_files = Dir['test/**/*'] + + s.add_dependency 'rails', '~> 4.2.5' + s.add_dependency 'deface', '~> 1.0' +end diff --git a/lib/generators/addon/templates/.gitignore b/lib/generators/addon/templates/.gitignore new file mode 100644 index 000000000..48a18d72a --- /dev/null +++ b/lib/generators/addon/templates/.gitignore @@ -0,0 +1,3 @@ +.bundle/ +log/*.log +pkg/ \ No newline at end of file diff --git a/lib/generators/addon/templates/Gemfile b/lib/generators/addon/templates/Gemfile new file mode 100644 index 000000000..ad86f99fd --- /dev/null +++ b/lib/generators/addon/templates/Gemfile @@ -0,0 +1,14 @@ +source 'https://rubygems.org' + +# Declare your gem's dependencies in gamification.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use a debugger +# gem 'byebug', group: [:development, :test] diff --git a/lib/generators/addon/templates/LICENSE.txt b/lib/generators/addon/templates/LICENSE.txt new file mode 100644 index 000000000..1333ed77b --- /dev/null +++ b/lib/generators/addon/templates/LICENSE.txt @@ -0,0 +1 @@ +TODO diff --git a/lib/generators/addon/templates/README.md b/lib/generators/addon/templates/README.md new file mode 100644 index 000000000..f87f5c14c --- /dev/null +++ b/lib/generators/addon/templates/README.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/lib/generators/addon/templates/Rakefile b/lib/generators/addon/templates/Rakefile new file mode 100644 index 000000000..814db9a85 --- /dev/null +++ b/lib/generators/addon/templates/Rakefile @@ -0,0 +1,19 @@ +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rdoc/task' + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = '${NAME}' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('lib/**/**/*.rb') +end + +Bundler::GemHelper.install_tasks + +task default: :test diff --git a/lib/generators/addon/templates/application.scss b/lib/generators/addon/templates/application.scss new file mode 100644 index 000000000..0cdd2788d --- /dev/null +++ b/lib/generators/addon/templates/application.scss @@ -0,0 +1,14 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/lib/generators/addon/templates/engine.rb b/lib/generators/addon/templates/engine.rb new file mode 100644 index 000000000..dd3aad207 --- /dev/null +++ b/lib/generators/addon/templates/engine.rb @@ -0,0 +1,52 @@ +class Engine < ::Rails::Engine + engine_name '${FULL_UNDERSCORE_NAME}' + isolate_namespace ${NAME} + paths['app/views'] = 'app/views/${FOLDERS_PATH}' + + # Precompile engine-specific assets + initializer '${ADDON_NAME}.assets.precompile' do |app| + app.config.assets.precompile += %w( + ) + end + + # Include static assets + initializer :static_assets do |app| + app.middleware.insert_before( + ::ActionDispatch::Static, + ::ActionDispatch::Static, + "#{root}/public" + ) + end + + # Merge localization files from engine + initializer :load_localization do |app| + app.config.i18n.load_path += Dir[ + Rails.root.join( + 'addons', + '${ADDON_NAME}', + 'config', + 'locales', + '*.{rb,yml}' + ) + ] + end + + # Initialize migrations + initializer :append_migrations do |app| + unless app.root.to_s.match(root.to_s) + config.paths['db/migrate'].expanded.each do |p| + app.config.paths['db/migrate'] << p + end + end + end + + # Initialize decorators + config.to_prepare do + Dir.glob(Engine.root.join('app', + 'decorators', + '**', + '*_decorator*.rb')) do |c| + Rails.configuration.cache_classes ? require(c) : load(c) + end + end +end diff --git a/lib/generators/addon/templates/rails b/lib/generators/addon/templates/rails new file mode 100644 index 000000000..1eb3848ab --- /dev/null +++ b/lib/generators/addon/templates/rails @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 4 +# gems installed from the root of your application. + +ENGINE_ROOT = File.expand_path('../..', __FILE__) +ENGINE_PATH = File.expand_path('../../lib/${FOLDERS_PATH}/engine', + __FILE__) + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +require 'rails/all' +require 'rails/engine/commands' diff --git a/lib/generators/addon/templates/test_helper.rb b/lib/generators/addon/templates/test_helper.rb new file mode 100644 index 000000000..368f9426d --- /dev/null +++ b/lib/generators/addon/templates/test_helper.rb @@ -0,0 +1,24 @@ +# Configure Rails Environment +ENV['RAILS_ENV'] = 'test' + +require File.expand_path('../..//config/environment.rb', __FILE__) +ActiveRecord::Migrator.migrations_paths = [ + File.expand_path('../..//db/migrate', __FILE__) +] +require 'rails/test_help' + +# Filter out Minitest backtrace while allowing backtrace from other libraries +# to be shown. +Minitest.backtrace_filter = Minitest::BacktraceFilter.new + +# Load support files +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } + +# Load fixtures from the engine +if ActiveSupport::TestCase.respond_to?(:fixture_path=) + ActiveSupport::TestCase.fixture_path = + File.expand_path('../fixtures', __FILE__) + ActiveSupport::TestCase.file_fixture_path = + ActiveSupport::TestCase.fixture_path + 'files' + ActiveSupport::TestCase.fixtures :all +end