Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 93c4226a66cc4b24fb0992a55f43090ccf388bde 0 parents
@mkristian authored
Showing with 1,192 additions and 0 deletions.
  1. +3 −0  .gitignore
  2. +20 −0 MIT-LICENSE
  3. +64 −0 README.md
  4. +9 −0 TODO
  5. +6 −0 features/generators.feature
  6. +170 −0 features/step_definitions/ruby_maven.rb
  7. +82 −0 features/step_definitions/simple_steps.rb
  8. +31 −0 ixtlan-generators.gemspec
  9. +1 −0  ixtlan-generators.gemspec.files
  10. +45 −0 lib/generators/ixtlan/base.rb
  11. +12 −0 lib/generators/ixtlan/configuration_model/configuration_model_generator.rb
  12. +12 −0 lib/generators/ixtlan/configuration_scaffold/configuration_scaffold_generator.rb
  13. +38 −0 lib/generators/ixtlan/setup/setup_generator.rb
  14. +17 −0 lib/generators/ixtlan/setup/templates/application_layout.html.erb
  15. +48 −0 lib/generators/ixtlan/setup/templates/database.yml.example
  16. +1 −0  lib/generators/ixtlan/setup/templates/error.html.erb
  17. +1 −0  lib/generators/ixtlan/setup/templates/error_with_session.html.erb
  18. +2 −0  lib/generators/ixtlan/setup/templates/gitignore
  19. +64 −0 lib/generators/ixtlan/setup/templates/initializer.rb
  20. +31 −0 lib/generators/ixtlan/setup/templates/preinitializer.rb
  21. +8 −0 lib/generators/ixtlan/setup/templates/production.yml.example
  22. +2 −0  lib/generators/ixtlan/setup/templates/stale.html.erb
  23. +12 −0 lib/generators/model/model_generator.rb
  24. +40 −0 lib/generators/rails/active_record/active_record_generator.rb
  25. +19 −0 lib/generators/rails/active_record/model/migration.rb
  26. +16 −0 lib/generators/rails/active_record/model/model.rb
  27. +37 −0 lib/generators/rails/erb/erb_generator.rb
  28. +28 −0 lib/generators/rails/erb/scaffold/_form.html.erb
  29. +24 −0 lib/generators/rails/erb/scaffold/edit.html.erb
  30. +49 −0 lib/generators/rails/erb/scaffold/index.html.erb
  31. +11 −0 lib/generators/rails/erb/scaffold/new.html.erb
  32. +30 −0 lib/generators/rails/erb/scaffold/show.html.erb
  33. +129 −0 lib/generators/rails/scaffold_controller/scaffold_controller/controller.rb
  34. +43 −0 lib/generators/rails/scaffold_controller/scaffold_controller/singleton_controller.rb
  35. +35 −0 lib/generators/scaffold/scaffold_generator.rb
  36. +34 −0 lib/generators/scaffold_controller/scaffold_controller_generator.rb
  37. +3 −0  lib/ixtlan-generators.rb
  38. +9 −0 lib/ixtlan/railtie.rb
  39. +6 −0 templates/generators.template
3  .gitignore
@@ -0,0 +1,3 @@
+target
+*.pom
+*~
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Kristian Meier
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64 README.md
@@ -0,0 +1,64 @@
+# Ixtlan #
+
+this gem adds more security related headers to the response for a rails3 application. mainly inspired by
+[google-gets-a-1-for-browser-security](http://www.barracudalabs.com/wordpress/index.php/2011/07/21/google-gets-a-1-for-browser-security-3/)
+and
+[HttpCaching](http://code.google.com/p/doctype/wiki/ArticleHttpCaching).
+and
+[Clickjacking](http://www.owasp.org/index.php/Clickjacking)
+
+the extra headers are
+
+* x-frame headers
+* x-content-type headers
+* x-xss-protection headers
+* caching headers
+
+the main idea is to set the default as strict as possible and the application might relax the setup here and there.
+
+## rails configuration ##
+
+in _config/application.rb_ or in one of the _config/environments/*rb_ files or in an initializer. all three x-headers can be configured here, for example
+
+ config.x_content_type_headers = :nosniff
+
+## controller configuration ##
+
+just add in your controller something like
+
+ x_xss_protection :block
+
+## option for each *render*, *send\_file*, *send\_data* methods
+
+an example for an inline render
+
+ render :inline => 'behappy', :x_frame_headers => :deny
+
+## possible values ##
+
+* x\_frame\_headers : `:deny, :sameorigin, :off` default `:deny`
+
+* x\_content\_type\_headers : `:nosniff, :off` default `:nosniff`
+
+* x\_xss\_protection\_headers : `:block, :disabled, :off` default `:block`
+
+## cache headers
+
+the cache headers needs to have a **current\_user**, i.e. the current\_user method of the controller needs to return a non-nil value. further the the method needs to `:get` and the response status an "ok" status,
+
+then you can use the controller configuration or the options with *render*, *send\_file* and *send\_data*.
+
+## possible values ##
+
+* `:private` : which tells not to cache or store any data except the browser memory: [no caching](http://code.google.com/p/doctype/wiki/ArticleHttpCaching#No_caching)
+
+* `:protected` : no caching but the browser: [Only the end user's browser is allowed to cache](http://code.google.com/p/doctype/wiki/ArticleHttpCaching#Only_the_end_user%27s_browser_is_allowed_to_cache)
+
+* `:public` : caching is allowed: [Both browser and proxy allowed to cache](http://code.google.com/p/doctype/wiki/ArticleHttpCaching#Both_browser_and_proxy_allowed_to_cache)
+
+* `:my_headers` : custom header method like
+
+> def my_headers
+ no_store = false
+ no_caching(no_store)
+ end
9 TODO
@@ -0,0 +1,9 @@
+* singleton unit tests
+
+* singleton erb templates are not found
+
+* plural attributes are singular in Model.java - have them plural as well
+
+* production.yml => password.yml and see taperoom how to deal with default - maybe
+
+* attr_accessors in model - mass-assignments
6 features/generators.feature
@@ -0,0 +1,6 @@
+Feature: Generators for Ixtlan
+
+ Scenario: Create a rails application and adding 'ixtlan-generators' gem will provide the ixtlan generators
+ Given I create new rails application with template "generators.template"
+ And I execute "rails generate"
+ Then the output should contain "ixtlan:setup" and "ixtlan:configuration_model" and "ixtlan:configuration_scaffold"
170 features/step_definitions/ruby_maven.rb
@@ -0,0 +1,170 @@
+require 'fileutils'
+
+module Maven
+ class RubyMaven
+
+ # make the command line for the goals of the jruby-maven-plugins nicer
+ PLUGINS = {
+ :rake => [:rake],
+ :ruby => [:jruby, :compile],
+ :gem => [:package, :install, :push, :exec, :pom, :initialize, :irb],
+ :gemify => [:gemify, :versions],
+ :rails2 => [:new, :generate, :rake, :server, :console],
+ :rails3 => [:new, :generate, :rake, :server, :console, :dbconsole, :pom, :initialize],
+ :cucumber => [:test],
+ :rspec => [:test],
+ :runit => [:test],
+ :bundler => [:install]
+ }
+ ALIASES = {
+ :jruby => :ruby,
+ :spec => :rspec,
+ :rails => :rails3,
+ :bundle => :bundler
+ }
+
+ def initialize
+ @command = "#{ENV['GEM_HOME']}/bin/rmvn"
+ @jruby = File.read(@command).split("\n")[0].sub(/^#!/, '')
+ @maven_home = File.expand_path(Dir.glob("#{ENV['GEM_HOME']}/gems/ruby-maven-*-java")[0])
+ end
+
+ def launch_jruby(args)
+ classpath_array.each do |path|
+ require path
+ end
+
+ java.lang.System.setProperty("classworlds.conf",
+ File.join(@maven_home, 'bin', "m2.conf"))
+
+ java.lang.System.setProperty("maven.home", @maven_home)
+
+ org.codehaus.plexus.classworlds.launcher.Launcher.main(args)
+ end
+
+ def classpath_array
+ (Dir.glob(File.join(@maven_home, "boot", "*jar")) +
+ Dir.glob(File.join(@maven_home, "ext", "ruby-tools*jar"))).each do |path|
+ path
+ end
+ end
+
+ def launch_java(*args)
+ "java -cp #{classpath_array.join(':')} -Dmaven.home=#{File.expand_path(@maven_home)} -Dclassworlds.conf=#{File.expand_path(File.join(@maven_home, 'bin', 'm2.conf'))} org.codehaus.plexus.classworlds.launcher.Launcher #{args.join ' '}"
+ end
+
+ def prepare(args)
+ if args.size > 0
+ name = args[0].to_sym
+ name = ALIASES[name] || name
+ if PLUGINS.member?(name)
+ start = 1
+ if args.size > 1
+ if PLUGINS[name].member? args[1].to_sym
+ goal = args[1].to_sym
+ start = 2
+ else
+ goal = PLUGINS[name][0]
+ end
+ else
+ goal = PLUGINS[name][0]
+ end
+ aa = if index = args.index("--")
+ args[(index + 1)..-1]
+ else
+ []
+ end
+ ruby_args = (args[start, (index || 1000) - start] || []).join(' ')
+
+ # determine the version and delete from args if given
+ version = args.detect do |a|
+ a =~ /^-Dplugin.version=/
+ end
+ if version
+ aa.delete(version)
+ version.sub!(/^-Dplugin.version=/, ':')
+ end
+ aa << "de.saumya.mojo:#{name}-maven-plugin#{version}:#{goal}"
+ aa << "-Dargs=#{ruby_args}" if ruby_args.size > 0
+ args.replace(aa)
+ else
+ args.delete("--")
+ end
+ end
+ args
+ end
+
+ def log(args)
+ log = File.join('log', 'rmvn.log')
+ if File.exists? File.dirname(log)
+ File.open(log, 'a') do |f|
+ f.puts args.join ' '
+ end
+ end
+ end
+
+ def maybe_print_help(args)
+ if args.size == 0 || args[0] == "--help"
+ puts "usage: rmvn [<plugin name>|<plugin alias> [<args>] [-- <maven options>] | [<maven goal>|<maven phase> <maven options>] | --help"
+ PLUGINS.each do |name, goals|
+ puts
+ print "plugin #{name}"
+ print " - alias: #{ALIASES[name]}" if ALIASES[name]
+ puts
+ if goals.size > 1
+ print "\tgoals : #{goals.join(',')}"
+ puts
+ end
+ print "\tdefault goal: #{goals[0]}"
+ puts
+ end
+ puts
+ ["--help"]
+ else
+ args
+ end
+ end
+
+ def options
+ @options ||= {}
+ end
+
+ def options_string
+ options_array.join ' '
+ end
+
+ def options_array
+ options.collect do |k,v|
+ if k =~ /^-D/
+ v = "=#{v}" if v
+ else
+ v = " #{v}" if v
+ end
+ "#{k}#{v}"
+ end
+ end
+
+ def command_line(args)
+ args = prepare(args)
+ args = maybe_print_help(args)
+ args
+ end
+
+ def exec(*args)
+ a = command_line(args.dup.flatten)
+ a << options_array
+ a.flatten!
+ #puts a.join ' '
+ #launch_jruby(a)
+ args_line = args.join ' '
+ full = "#{@jruby} #{@command} #{args_line} #{args_line =~ / -- / ? '' : '--'} #{options_string}"
+ system full
+ end
+
+ def exec_in(launchdirectory, *args)
+ FileUtils.cd(launchdirectory) do
+ exec(args)
+ end
+ end
+ end
+end
82 features/step_definitions/simple_steps.rb
@@ -0,0 +1,82 @@
+require 'fileutils'
+require File.join(File.dirname(__FILE__), 'ruby_maven')
+
+def rmvn
+ @rmvn ||= Maven::RubyMaven.new
+end
+
+def copy_tests(tests)
+ FileUtils.mkdir_p(@app_directory)
+ FileUtils.cp_r(File.join('templates', "tests-#{tests}", "."),
+ File.join(@app_directory, 'test'))
+end
+
+def copy_specs(specs)
+ FileUtils.mkdir_p(@app_directory)
+ FileUtils.cp_r(File.join('templates', "specs-#{specs}", "."),
+ File.join(@app_directory, 'spec'))
+end
+
+def create_rails_application(template)
+ name = template.sub(/.template$/, '')
+ @app_directory = File.join('target', name)
+
+ # rails version from gemspec
+ gemspec = File.read(Dir.glob("*.gemspec")[0])
+ rails_version = gemspec.split("\n").detect { |l| l =~ /development_dep.*rails/ }.sub(/'$/, '').sub(/.*'/, '')
+
+ rmvn.options['-Dplugin.version'] = '0.28.4-SNAPSHOT'
+ rmvn.options['-Drails.version'] = rails_version
+ rmvn.options['-Dgem.home'] = ENV['GEM_HOME']
+ rmvn.options['-Dgem.path'] = ENV['GEM_PATH']
+ rmvn.options['-o'] = nil
+
+ FileUtils.rm_rf(@app_directory)
+
+ rmvn.exec("rails", "new", @app_directory, "-f")
+
+ # TODO that should be done via the rails new task !!!
+ rmvn.exec_in(@app_directory, "rails", "rake", "rails:template LOCATION=" + File.expand_path("templates/#{template}"))
+end
+
+Given /^I create new rails application with template "(.*)"$/ do |template|
+ create_rails_application(template)
+end
+
+Given /^I create new rails application with template "(.*)" and "(.*)" tests$/ do |template, tests|
+ create_rails_application(template)
+ copy_tests(tests)
+end
+
+Given /^I create new rails application with template "(.*)" and "(.*)" specs$/ do |template, specs|
+ create_rails_application(template)
+ copy_specs(specs)
+end
+
+Given /^me an existing rails application "(.*)"$/ do |name|
+ @app_directory = File.join('target', name)
+end
+
+Given /^me an existing rails application "(.*)" and "(.*)" tests$/ do |name, tests|
+ @app_directory = File.join('target', name)
+ copy_tests(tests)
+end
+
+Given /^me an existing rails application "(.*)" and "(.*)" specs$/ do |name, specs|
+ @app_directory = File.join('target', name)
+ copy_specs(specs)
+end
+
+And /^I execute \"(.*)\"$/ do |args|
+ rmvn.options['-l'] = "output.log"
+ rmvn.exec_in(@app_directory, args)
+end
+
+Then /^the output should contain \"(.*)\"$/ do |expected|
+ result = File.read(File.join(@app_directory, "output.log"))
+ expected.split(/\"?\s+and\s+\"?/).each do |exp|
+ puts exp
+ (result =~ /.*#{exp}.*/).should_not be_nil
+ end
+end
+
31 ixtlan-generators.gemspec
@@ -0,0 +1,31 @@
+# -*- mode: ruby -*-
+Gem::Specification.new do |s|
+ s.name = 'ixtlan-generators'
+ s.version = '0.1.0'
+
+ s.summary = 'rails generator templates for ixtlan gems'
+ s.description = s.summary
+ s.homepage = 'http://github.com/mkristian/ixtlan-generators'
+
+ s.authors = ['mkristian']
+ s.email = ['m.kristian@web.de']
+
+ s.files = Dir['MIT-LICENSE']
+ s.licenses << 'MIT-LICENSE'
+# s.files += Dir['History.txt']
+ s.files += Dir['README.md']
+ s.files += Dir['lib/**/*']
+ s.files += Dir['spec/**/*']
+ s.files += Dir['features/**/*rb']
+ s.files += Dir['features/**/*feature']
+ s.test_files += Dir['spec/**/*_spec.rb']
+ s.test_files += Dir['features/*.feature']
+ s.test_files += Dir['features/step_definitions/*.rb']
+ s.add_development_dependency 'ixtlan-core', '~>0.5'
+ s.add_development_dependency 'rails', '3.0.9'
+ s.add_development_dependency 'rspec', '2.6.0'
+ s.add_development_dependency 'cucumber', '0.9.4'
+ s.add_development_dependency 'ruby-maven', '0.8.3.0.3.0.28.3'
+end
+
+# vim: syntax=Ruby
1  ixtlan-generators.gemspec.files
@@ -0,0 +1 @@
+ixtlan-generators.gemspec
45 lib/generators/ixtlan/base.rb
@@ -0,0 +1,45 @@
+require 'rails/generators/named_base'
+module Ixtlan
+ module Generators
+ class Base < Rails::Generators::Base
+
+ argument :name, :type => :string, :required => false
+
+ protected
+ def generator_name
+ raise "please overwrite generator_name"
+ end
+
+ public
+ def create
+ args = []
+ if name
+ args << ARGV.shift
+ else
+ args << "configuration"
+ end
+
+ if defined? ::Ixtlan::Errors
+ args << "errors_keep_dump:integer"
+ args << "errors_dir:string"
+ args << "errors_from:string"
+ args << "errors_to:string"
+ end
+
+ if defined? ::Ixtlan::Sessions
+ args << "idle_session_timeout:integer"
+ end
+
+ if defined? ::Ixtlan::Audit
+ args << "audit_keep_log:integer"
+ end
+
+ args += ARGV[0, 10000] || []
+
+ args << "--singleton"
+
+ generate generator_name, *args
+ end
+ end
+ end
+end
12 lib/generators/ixtlan/configuration_model/configuration_model_generator.rb
@@ -0,0 +1,12 @@
+require 'generators/ixtlan/base'
+module Ixtlan
+ module Generators
+ class ConfigurationModelGenerator < Base
+
+ protected
+ def generator_name
+ "model"
+ end
+ end
+ end
+end
12 lib/generators/ixtlan/configuration_scaffold/configuration_scaffold_generator.rb
@@ -0,0 +1,12 @@
+require 'generators/ixtlan/base'
+module Ixtlan
+ module Generators
+ class ConfigurationScaffoldGenerator < Base
+
+ protected
+ def generator_name
+ "scaffold"
+ end
+ end
+ end
+end
38 lib/generators/ixtlan/setup/setup_generator.rb
@@ -0,0 +1,38 @@
+require 'rails/generators/base'
+module Ixtlan
+ module Generators
+ class SetupGenerator < Rails::Generators::Base
+
+ source_root File.expand_path('../templates', __FILE__)
+
+ def create_preinitializer_files
+ template 'preinitializer.rb', File.join('config', "preinitializer.rb")
+ template 'gitignore', File.join('config', ".gitignore")
+ template 'production.yml.example', File.join('config', "production.yml.example")
+ template 'database.yml.example', File.join('config', "database.yml.example")
+ end
+
+ def create_initializer_file
+ template 'initializer.rb', File.join('config', "initializers", "ixtlan.rb")
+ end
+
+ # TODO make only if template-engine is ERB
+ def error_templates
+ if defined? Ixtlan::Errors
+ views_dir = File.join('app', 'views', 'errors')
+ ['error', 'error_with_session', 'stale'].each do |f|
+ file = "#{f}.html.erb"
+ template file, File.join(views_dir, file)
+ end
+ end
+ end
+
+ def create_application_layout_file
+ if defined? Ixtlan::Sessions
+ layout = File.join('app', 'views', 'layouts', 'application.html.erb')
+ template 'application_layout.html.erb', layout
+ end
+ end
+ end
+ end
+end
17 lib/generators/ixtlan/setup/templates/application_layout.html.erb
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title><%= app_const_base %></title>
+ <%%= stylesheet_link_tag :all %>
+ <%%= javascript_include_tag :defaults %>
+ <%%= csrf_meta_tag %>
+ <%% if controller.respond_to?(:current_user) && controller.send(:current_user) != nil %>
+ <meta http-equiv="refresh" content="<%%= controller.send(:idle_session_timeout) * 60 + 5 %>" />
+ <%% end %>
+</head>
+<body>
+
+<%%= yield %>
+
+</body>
+</html>
48 lib/generators/ixtlan/setup/templates/database.yml.example
@@ -0,0 +1,48 @@
+# MySQL. Versions 4.1 and 5.0 are recommended.
+#
+# Install the MySQL driver:
+# gem install mysql
+# On Mac OS X:
+# sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql
+# On Mac OS X Leopard:
+# sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
+# This sets the ARCHFLAGS environment variable to your native architecture
+# On Windows:
+# gem install mysql
+# Choose the win32 build.
+# Install MySQL and put its /bin directory on your path.
+#
+# And be sure to use new-style password hashing:
+# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
+development:
+ adapter: mysql
+ encoding: utf8
+ reconnect: false
+ database: test_development
+ pool: 5
+ username: root
+ password:
+ socket: /var/run/mysqld/mysqld.sock
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: mysql
+ encoding: utf8
+ reconnect: false
+ database: test_test
+ pool: 5
+ username: root
+ password:
+ socket: /var/run/mysqld/mysqld.sock
+
+production:
+ adapter: mysql
+ encoding: utf8
+ reconnect: false
+ database: CONFIG[:db][:database]
+ pool: 5
+ username: CONFIG[:db][:username]
+ password: CONFIG[:db][:password]
+ socket: /var/run/mysqld/mysqld.sock
1  lib/generators/ixtlan/setup/templates/error.html.erb
@@ -0,0 +1 @@
+<h1><%%= @notice %></h1>
1  lib/generators/ixtlan/setup/templates/error_with_session.html.erb
@@ -0,0 +1 @@
+<h1><%%= @notice %></h1>
2  lib/generators/ixtlan/setup/templates/gitignore
@@ -0,0 +1,2 @@
+production.yml
+*.example
64 lib/generators/ixtlan/setup/templates/initializer.rb
@@ -0,0 +1,64 @@
+# dynamic configuration through a Configuration singleton model
+
+# configuration model
+# -------------------
+# CONFIGURATION = Configuration
+# config.configuration_model = CONFIGURATION
+begin
+ config_instance = CONFIGURATION.instance
+rescue
+ # allow rake tasks to work without configuration migrated
+ return
+end
+
+# notification email on errors and dump directory for the system dump
+# the error dumps will be cleanup after the days to keeps dump expired
+# --------------------------------------------------------------------
+# config_instance.register("error_dumper") do |config|
+# Rails.configuration.error_dumper.dump_dir = config.errors_dir
+# Rails.configuration.error_dumper.email_from = config.errors_from
+# Rails.configuration.error_dumper.email_to = config.errors_to
+# Rails.configuration.error_dumper.keep_dumps = config.errors_keep_dump # days
+# end
+
+# idle session timeout configuration (in minutes)
+# -----------------------------------------------
+# config_instance.register("session_idle_timeout") do |config|
+# Rails.configuration.session_idle_timeout = config.session_idle_timeout
+# end
+
+# audit log manager
+# -----------------
+
+# config.audit_manager.model = MyAudit # default: Audit
+# config.audit_manager.username_method = :username # default: :login
+
+# config_instance.register("audit_manager") do |config|
+# Rails.configuration.audit_manager.keep_log = config.keep_log # days
+# end
+
+# --------------------
+# static configuration
+# --------------------
+
+# error dumper
+# ------------
+# notification email on errors and dump directory for the system dump. per
+# default there is no email notification and if email_from or email_to is
+# missing then there is no email too
+
+# config.error_dumper.dump_dir = Rails.root + "/log/errors" # default: log/errors
+# config.error_dumper.email_from = "no-reply@example.com"
+# config.error_dumper.email_to = "developer1@example.com,developer2@example.com"
+# config.error_dumper.keep_dumps = 30 # days
+# config.skip_rescue_module = true # do not include the predefined Rescue
+
+# idle session timeout configuration
+# ----------------------------------
+# config.session_idle_timeout = 30 #minutes
+
+# audit log manager
+# -----------------
+# config.audit_manager.model = MyAudit # default: Audit
+# config.audit_manager.username_method = :username # default: :login
+# config.audit_manager.keep_log = 30 # days
31 lib/generators/ixtlan/setup/templates/preinitializer.rb
@@ -0,0 +1,31 @@
+require 'yaml'
+require 'erb'
+module Ixtlan
+ class Configurator
+
+ def self.symbolize_keys(h)
+ result = {}
+
+ h.each do |k, v|
+ v = ' ' if v.nil?
+ if v.is_a?(Hash)
+ result[k.to_sym] = symbolize_keys(v) unless v.size == 0
+ else
+ result[k.to_sym] = v unless k.to_sym == v.to_sym
+ end
+ end
+
+ result
+ end
+
+ def self.load(file)
+ if File.exists?(file)
+ symbolize_keys(YAML::load(ERB.new(IO.read(file)).result))
+ else
+ warn "no file #{file} to load - maybe the is a #{file}.example"
+ end
+ end
+ end
+end
+
+CONFIG = Ixtlan::Configurator.load(File.join(File.dirname(__FILE__), 'production.yml')) || {}
8 lib/generators/ixtlan/setup/templates/production.yml.example
@@ -0,0 +1,8 @@
+db:
+ database: production
+ username: worker
+ password: behappy
+smtp:
+ host: mail.example.com
+ username: mailworker
+ password: secret
2  lib/generators/ixtlan/setup/templates/stale.html.erb
@@ -0,0 +1,2 @@
+<h1>stale resource</h1>
+<p>please reload resource and change it again</p>
12 lib/generators/model/model_generator.rb
@@ -0,0 +1,12 @@
+module Rails
+ module Generators
+ class ModelGenerator < NamedBase #metagenerator
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
+ hook_for :orm, :required => true
+
+ if defined? Resty
+ hook_for :resty, :type => :boolean, :default => true
+ end
+ end
+ end
+end
40 lib/generators/rails/active_record/active_record_generator.rb
@@ -0,0 +1,40 @@
+require 'rails/generators/active_record'
+
+module ActiveRecord
+ module Generators
+ class ModelGenerator < Base
+ include ::Ixtlan::Core::Singleton
+
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
+
+ check_class_collision
+
+ class_option :migration, :type => :boolean
+ class_option :timestamps, :type => :boolean
+ class_option :parent, :type => :string, :desc => "The parent class for the generated model"
+
+ def create_migration_file
+ return unless options[:migration] && options[:parent].nil?
+ migration_template "migration.rb", "db/migrate/create_#{table_name}.rb"
+ end
+
+ def create_model_file
+ template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
+ end
+
+ def create_module_file
+ return if class_path.empty?
+ template 'module.rb', File.join('app/models', "#{class_path.join('/')}.rb") if behavior == :invoke
+ end
+
+ hook_for :test_framework
+
+ protected
+
+ def parent_class_name
+ options[:parent] || "ActiveRecord::Base"
+ end
+
+ end
+ end
+end
19 lib/generators/rails/active_record/model/migration.rb
@@ -0,0 +1,19 @@
+class <%= migration_class_name %> < ActiveRecord::Migration
+ def self.up
+ create_table :<%= table_name %> do |t|
+<% attributes.select {|attr| ![:has_one, :has_many].include?(attr.type) }.each do |attribute| -%>
+ t.<%= attribute.type %> :<%= attribute.name %>
+<% end -%>
+<% if options[:timestamps] %>
+ t.timestamps
+<% end -%>
+<% if options[:modified_by] %>
+ t.references :modified_by
+<% end -%>
+ end
+ end
+
+ def self.down
+ drop_table :<%= table_name %>
+ end
+end
16 lib/generators/rails/active_record/model/model.rb
@@ -0,0 +1,16 @@
+class <%= class_name %> < <%= parent_class_name.classify %>
+<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
+ belongs_to :<%= attribute.name %>
+<% end -%>
+<% attributes.select {|attr| [:has_one, :has_many].include?(attr.type) }.each do |attribute| -%>
+ <%= attribute.type %> :<%= attribute.name %>
+<% end -%>
+<% if options[:modified_by] -%>
+ belongs_to :modified_by, :class_name => "<%= options[:user_model] %>"
+<% end -%>
+<% if options[:singleton] -%>
+ def self.instance
+ self.first || self.new
+ end
+<% end -%>
+end
37 lib/generators/rails/erb/erb_generator.rb
@@ -0,0 +1,37 @@
+require 'rails/generators/erb'
+require 'rails/generators/resource_helpers'
+
+module Erb
+ module Generators
+ class ScaffoldGenerator < Base
+ include Rails::Generators::ResourceHelpers
+
+ class_option :optimistic, :type => :boolean, :default => false
+ class_option :singleton, :type => :boolean, :default => false
+ class_option :timestamps, :type => :boolean, :default => true
+
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
+
+ def create_root_folder
+ empty_directory File.join("app/views", controller_file_path)
+ end
+
+ def copy_view_files
+ available_views.each do |view|
+ filename = filename_with_extensions(view)
+ template filename, File.join("app/views", controller_file_path, filename)
+ end
+ end
+
+ protected
+
+ def available_views
+ if options[:singleton]
+ %w(edit show _form)
+ else
+ %w(index edit show new _form)
+ end
+ end
+ end
+ end
+end
28 lib/generators/rails/erb/scaffold/_form.html.erb
@@ -0,0 +1,28 @@
+<%%= form_for(@<%= singular_table_name %><% if options[:singleton] -%>
+, :url => <%= singular_table_name %>_path, :html => { :method => :put, :class => "edit_<%= singular_table_name %>", :id => "edit_<%= singular_table_name %>"}<% end -%>
+) do |f| %>
+ <%% if @<%= singular_table_name %>.errors.any? %>
+ <div id="error_explanation">
+ <h2><%%= pluralize(@<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
+
+ <ul>
+ <%% @<%= singular_table_name %>.errors.full_messages.each do |msg| %>
+ <li><%%= msg %></li>
+ <%% end %>
+ </ul>
+ </div>
+ <%% end %>
+
+<% for attribute in attributes -%>
+ <div class="field"><!-- begin - <%= attribute.name %> -->
+ <%%= f.label :<%= attribute.name %> %><br />
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
+ </div><!-- end - <%= attribute.name %> -->
+<% end -%>
+ <div class="actions">
+<% if options[:optimistic] && options[:timestamps] -%>
+ <%%= f.hidden_field :updated_at %>
+<% end -%>
+ <%%= f.submit %>
+ </div>
+<%% end %>
24 lib/generators/rails/erb/scaffold/edit.html.erb
@@ -0,0 +1,24 @@
+<h1>Editing <%= singular_table_name %></h1>
+
+<%%= render 'form' %>
+
+<% if defined? ::Ixtlan::Guard -%>
+<%% if allowed?(:<%= table_name %>, :show) %>
+<% end -%>
+<% if options[:singleton] -%>
+<%%= link_to 'Show', <%= singular_table_name %>_path %>
+<% else -%>
+<%%= link_to 'Show', @<%= singular_table_name %> %>
+<% end -%>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<% end -%>
+<% unless options[:singleton] -%>
+<% if defined? ::Ixtlan::Guard -%>
+<%% if allowed?(:<%= table_name %>, :index) %>
+<% end -%>
+| <%%= link_to 'Back', <%= index_helper %>_path %>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<% end -%>
+<% end -%>
49 lib/generators/rails/erb/scaffold/index.html.erb
@@ -0,0 +1,49 @@
+<h1>Listing <%= plural_table_name %></h1>
+
+<table>
+ <tr>
+<% for attribute in attributes -%>
+ <th><%= attribute.human_name %></th>
+<% end -%>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
+ <tr>
+<% for attribute in attributes -%>
+ <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
+<% end -%>
+<% if defined? ::Ixtlan::Guard -%>
+<%% if allowed?(:<%= table_name %>, :show) %>
+<% end -%>
+ <td><%%= link_to 'Show', <%= singular_table_name %> %></td>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<%% if allowed?(:<%= table_name %>, :update) %>
+<% end -%>
+ <td><%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>) %></td>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<%% if allowed?(:<%= table_name %>, :destroy) %>
+<% end -%>
+ <td><% if options[:optimistic] && options[:timestamps] -%>
+<%%= link_to 'Destroy', <%= singular_table_name %>_path(<%= singular_table_name %>) + "?<%= singular_table_name %>[updated_at]=#{<%= singular_table_name %>.updated_at.utc.strftime('%Y-%m-%d %H:%M:%S') + ("%06d" % <%= singular_table_name %>.updated_at.utc)}", :confirm => 'Are you sure?', :method => :delete %><% else -%><%%= link_to 'Destroy', <%= singular_table_name %>, :confirm => 'Are you sure?', :method => :delete %>
+<% end -%></td>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<% end -%>
+ </tr>
+<%% end %>
+</table>
+
+<br />
+
+<% if defined? ::Ixtlan::Guard -%>
+<%% if allowed?(:<%= table_name %>, :create) %>
+<% end -%>
+<%%= link_to 'New <%= human_name %>', new_<%= singular_table_name %>_path %>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<% end -%>
11 lib/generators/rails/erb/scaffold/new.html.erb
@@ -0,0 +1,11 @@
+<h1>New <%= singular_table_name %></h1>
+
+<%%= render 'form' %>
+
+<% if defined? ::Ixtlan::Guard -%>
+<%% if allowed?(:<%= table_name %>, :index) %>
+<% end -%>
+<%%= link_to 'Back', <%= index_helper %>_path %>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<% end -%>
30 lib/generators/rails/erb/scaffold/show.html.erb
@@ -0,0 +1,30 @@
+<p id="notice"><%%= notice %></p>
+
+<% for attribute in attributes -%>
+<p>
+ <b><%= attribute.human_name %>:</b>
+ <%%= @<%= singular_table_name %>.<%= attribute.name %> %>
+</p>
+
+<% end -%>
+
+<% if defined? ::Ixtlan::Guard -%>
+<%% if allowed?(:<%= table_name %>, :update) %>
+<% end -%>
+<% if options[:singleton] -%>
+<%%= link_to 'Edit', edit_<%= singular_table_name %>_path %>
+<% else -%>
+<%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>) %>
+<% end -%>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<% end -%>
+<% unless options[:singleton] -%>
+<% if defined? ::Ixtlan::Guard -%>
+<%% if allowed?(:<%= table_name %>, :index) %>
+<% end -%>
+ | <%%= link_to 'Back', <%= index_helper %>_path %>
+<% if defined? ::Ixtlan::Guard -%>
+<%% end %>
+<% end -%>
+<% end -%>
129 lib/generators/rails/scaffold_controller/scaffold_controller/controller.rb
@@ -0,0 +1,129 @@
+class <%= controller_class_name %>Controller < ApplicationController
+ # GET <%= route_url %>
+ # GET <%= route_url %>.xml
+ # GET <%= route_url %>.json
+ def index
+ @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @<%= plural_table_name %> }
+ format.json { render :json => @<%= plural_table_name %> }
+ end
+ end
+
+ # GET <%= route_url %>/1
+ # GET <%= route_url %>/1.xml
+ # GET <%= route_url %>/1.json
+ def show
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @<%= singular_table_name %> }
+ format.json { render :json => @<%= singular_table_name %> }
+ end
+ end
+
+ # GET <%= route_url %>/new
+ def new
+ @<%= singular_table_name %> = <%= orm_class.build(class_name) %>
+ end
+
+ # GET <%= route_url %>/1/edit
+ def edit
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
+ end
+
+ # POST <%= route_url %>
+ # POST <%= route_url %>.xml
+ # POST <%= route_url %>.json
+ def create
+ @<%= singular_table_name %> = <%= orm_class.build(class_name, "params[:#{singular_table_name}]") %>
+<% if options[:modified_by] -%>
+ @<%= singular_table_name %>.current_user = current_user
+<% end -%>
+
+ respond_to do |format|
+ if @<%= orm_instance.save %>
+ format.html { redirect_to(@<%= singular_table_name %>, :notice => '<%= human_name %> was successfully created.') }
+ format.xml { render :xml => @<%= singular_table_name %>, :status => :created, :location => @<%= singular_table_name %> }
+ format.json { render :json => @<%= singular_table_name %>, :status => :created, :location => @<%= singular_table_name %> }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @<%= orm_instance.errors %>, :status => :unprocessable_entity }
+ format.json { render :json => @<%= orm_instance.errors %>, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT <%= route_url %>/1
+ # PUT <%= route_url %>/1.xml
+ # PUT <%= route_url %>/1.json
+ def update
+<% if options[:optimistic] && options[:timestamps] -%>
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "(params[:#{singular_table_name}]||[]).delete(:updated_at), params[:id]").sub(/\.(get|find)/, '.optimistic_\1') %>
+
+ if @<%= singular_table_name %>.nil?
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
+ respond_to do |format|
+ format.html { render :action => "edit" }
+ format.xml { render :xml => nil, :status => :conflict }
+ format.json { render :json => nil, :status => :conflict }
+ end
+ return
+ end
+<% else -%>
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
+ (params[:<%= singular_table_name %>]||[]).delete(:updated_at)
+<% end -%>
+ (params[:<%= singular_table_name %>]||[]).delete(:id)
+<% if options[:modified_by] -%>
+ @<%= singular_table_name %>.current_user = current_user
+<% end -%>
+
+ respond_to do |format|
+ if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %>
+ format.html { redirect_to(@<%= singular_table_name %>, :notice => '<%= human_name %> was successfully updated.') }
+ format.xml { render :xml => @<%= singular_table_name %> }
+ format.json { render :json => @<%= singular_table_name %> }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @<%= orm_instance.errors %>, :status => :unprocessable_entity }
+ format.json { render :json => @<%= orm_instance.errors %>, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE <%= route_url %>/1
+ # DELETE <%= route_url %>/1.xml
+ # DELETE <%= route_url %>/1.json
+ def destroy
+<% if options[:optimistic] && options[:timestamps] -%>
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "(params[:#{singular_table_name}]||[]).delete(:updated_at), params[:id]").sub(/\.(get|find)/, '.optimistic_\1') %>
+
+ if @<%= singular_table_name %>.nil?
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
+ respond_to do |format|
+ format.html { render :action => "edit" }
+ format.xml { render :xml => nil, :status => :conflict }
+ format.json { render :json => nil, :status => :conflict }
+ end
+ return
+ end
+<% else -%>
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
+<% end -%>
+<% if options[:modified_by] -%>
+ @<%= singular_table_name %>.current_user = current_user
+<% end -%>
+
+ @<%= orm_instance.destroy %>
+
+ respond_to do |format|
+ format.html { redirect_to(<%= index_helper %>_url) }
+ format.xml { head :ok }
+ format.json { head :ok }
+ end
+ end
+end
43 lib/generators/rails/scaffold_controller/scaffold_controller/singleton_controller.rb
@@ -0,0 +1,43 @@
+class <%= controller_class_name %>Controller < ApplicationController
+
+ # GET <%= route_url %>
+ # GET <%= route_url %>.xml
+ # GET <%= route_url %>.json
+ def show
+ @<%= singular_table_name %> = <%= class_name %>.instance
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @<%= singular_table_name %> }
+ format.json { render :json => @<%= singular_table_name %> }
+ end
+ end
+
+ # GET <%= route_url %>/edit
+ def edit
+ @<%= singular_table_name %> = <%= class_name %>.instance
+ end
+
+ # PUT <%= route_url %>
+ # PUT <%= route_url %>.xml
+ # PUT <%= route_url %>.json
+ def update
+ @<%= singular_table_name %> = <%= class_name %>.instance
+<% orm_class.find(class_name)
+ if options[:modified_by] -%>
+ @<%= singular_table_name %>.current_user = current_user
+<% end -%>
+
+ respond_to do |format|
+ if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %>
+ format.html { redirect_to(<%= singular_table_name %>_path, :notice => '<%= human_name %> was successfully updated.') }
+ format.xml { render :xml => @<%= singular_table_name %> }
+ format.json { render :json => @<%= singular_table_name %> }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @<%= orm_instance.errors %>, :status => :unprocessable_entity }
+ format.json { render :json => @<%= orm_instance.errors %>, :status => :unprocessable_entity }
+ end
+ end
+ end
+end
35 lib/generators/scaffold/scaffold_generator.rb
@@ -0,0 +1,35 @@
+require 'rails/generators/rails/resource/resource_generator'
+
+module Rails
+ module Generators
+ class ScaffoldGenerator < ResourceGenerator #metagenerator
+ remove_hook_for :resource_controller
+ remove_class_option :actions
+
+ class_option :singleton, :type => :boolean, :default => false
+
+ hook_for :scaffold_controller, :required => true, :in => :scaffold_controller
+ hook_for :stylesheets
+
+ if defined? Resty
+ hook_for :resty, :type => :boolean, :default => true
+ end
+
+ if defined? ::Ixtlan::Guard
+ hook_for :guard, :type => :boolean, :default => true
+ end
+
+ def add_resource_route
+ return if options[:actions].present?
+ route_config = class_path.collect{|namespace| "namespace :#{namespace} do " }.join(" ")
+ if options[:singleton]
+ route_config << "resource :#{file_name}"
+ else
+ route_config << "resources :#{file_name.pluralize}"
+ end
+ route_config << " end" * class_path.size
+ route route_config
+ end
+ end
+ end
+end
34 lib/generators/scaffold_controller/scaffold_controller_generator.rb
@@ -0,0 +1,34 @@
+require 'rails/generators/resource_helpers'
+require 'rails/generators/named_base'
+
+module ScaffoldController
+ module Generators
+ class ScaffoldControllerGenerator < ::Rails::Generators::NamedBase
+ include ::Rails::Generators::ResourceHelpers
+
+ check_class_collision :suffix => "Controller"
+
+ class_option :orm, :banner => "NAME", :type => :string, :required => true,
+ :desc => "ORM to generate the controller for"
+
+ class_option :singleton, :type => :boolean, :default => false
+ class_option :optimistic, :type => :boolean, :default => false
+ class_option :timestamps, :type => :boolean, :default => true
+
+ def create_controller_files
+ if options[:singleton]
+ template 'singleton_controller.rb', File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb")
+ else
+ template 'controller.rb', File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb")
+ end
+ end
+
+ hook_for :template_engine, :test_framework, :as => :scaffold, :in => :rails
+
+ # Invoke the helper using the controller name (pluralized)
+ hook_for :helper, :as => :scaffold, :in => :rails do |invoked|
+ invoke invoked, [ controller_name ]
+ end
+ end
+ end
+end
3  lib/ixtlan-generators.rb
@@ -0,0 +1,3 @@
+if defined?(Rails)
+ require 'ixtlan/railtie'
+end
9 lib/ixtlan/railtie.rb
@@ -0,0 +1,9 @@
+module Ixtlan
+ class Railtie < Rails::Railtie
+ config.generators do |config|
+
+ config.templates << File.expand_path('../../generators/rails', __FILE__)
+
+ end
+ end
+end
6 templates/generators.template
@@ -0,0 +1,6 @@
+#-*- mode: ruby -*-
+
+gem 'ruby-maven', '0.8.3.0.3.0.28.3'
+gem 'ixtlan-generators', :path => '../..'
+
+# vim: syntax=Ruby
Please sign in to comment.
Something went wrong with that request. Please try again.