module Ruport class Generator #:nodoc: extend FileUtils module Helpers #:nodoc: def format_class_name(string) string.downcase.split("_").map { |s| s.capitalize }.join end def check_for_files if File.exist? "lib/reports/#{ARGV[1]}.rb" raise "Report #{ARGV[1]} exists!" end if File.exist? "lib/controllers/#{ARGV[1]}.rb" raise "Controller #{ARGV[1]} exists!" end end end begin require "rubygems" rescue LoadError nil end require "ruport" require "ruport/util" def self.build(proj) @project = proj build_directory_structure build_init build_config build_utils build_rakefile build_readme puts "\nSuccessfully generated project: #{proj}" end def self.write_file(path,options={}) options = {:io => STDOUT}.merge(options) m = "#{project}/#{path}" options[:io].puts " #{m}" if options[:file] options[:file] << yield else File.open(m,"w") { |f| f << yield } end end def self.build_init write_file("lib/init.rb") { INIT } end # Generates a trivial rakefile for use with Ruport. def self.build_rakefile write_file("Rakefile") { RAKEFILE } end def self.build_readme write_file("README") { README } end # Generates the build.rb and sql_exec.rb utilities def self.build_utils m = "#{project}/util/build" puts " #{m}" File.open(m,"w") { |f| f << BUILD } chmod(0755, m) m = "#{project}/util/sql_exec" puts " #{m}" File.open(m,"w") { |f| f << SQL_EXEC } chmod(0755, m) end # sets up the basic directory layout for a Ruport application def self.build_directory_structure mkdir project puts "creating directories.." %w[ test config output data data/models lib lib/reports lib/controllers sql util ].each do |d| m="#{project}/#{d}" puts " #{m}" mkdir(m) end puts "creating files.." %w[reports helpers controllers templates].each { |f| m = "#{project}/lib/#{f}.rb" puts " #{m}" touch(m) } end def self.build_config write_file("config/environment.rb") { CONFIG } end # returns the project's name def self.project; @project; end RAKEFILE = <<'END_RAKEFILE' begin; require "rubygems"; rescue LoadError; end require "rake/testtask" task :default => [:test] Rake::TestTask.new do |test| test.libs << "test" test.pattern = 'test/**/test_*.rb' test.verbose = true end task :build do if ENV['report'] sh "ruby util/build report #{ENV['report']}" elsif ENV['controller'] sh "ruby util/build controller #{ENV['controller']}" elsif ENV['model'] sh "ruby util/build model #{ENV['model']}" end end task :run do sh "ruby lib/reports/#{ENV['report']}.rb" end END_RAKEFILE CONFIG = < "root", # :dsn => "dbi:mysql:mydb" # Uncomment and modify the lines below if you want to use AAR # # require "active_record" # require "ruport/acts_as_reportable" # ActiveRecord::Base.establish_connection( # :adapter => 'mysql', # :host => 'localhost', # :username => 'name', # :password => 'password', # :database => 'mydb' # ) END_CONFIG BUILD = <<'END_BUILD' #!/usr/bin/env ruby require 'fileutils' require 'lib/init.rb' require "ruport/util" include FileUtils include Ruport::Generator::Helpers unless ARGV.length > 1 puts "usage: build [command] [options]" exit end class_name = format_class_name(ARGV[1]) if ARGV[0].eql? "report" check_for_files File.open("lib/reports.rb", "a") { |f| f.puts("require \"lib/reports/#{ARGV[1]}\"") } REP = < #{class_name} def build_#{class_name.downcase} end end EOR TEST = < "root", # :dsn => "dbi:mysql:mydb" # Uncomment and modify the lines below if you want to use AAR # # require "active_record" # require "ruport/acts_as_reportable" # ActiveRecord::Base.establish_connection( # :adapter => 'mysql', # :host => 'localhost', # :username => 'name', # :password => 'password', # :database => 'mydb' # ) You'll need to tweak this as needed to fit your database configuration needs. If you need to require any third party libraries which are shared across your project, you should do it in this file. # Custom rendering with rope generators. -- By Example $ rope my_reverser $ cd my_reverser $ rake build controller=reverser Edit test/test_reverser.rb to look like the code below: require "test/unit" require "lib/controllers/reverser" class TestReverser < Test::Unit::TestCase def test_reverser assert_equal "baz", Reverser.render_text("zab") end end Now edit lib/controllers/reverser.rb to look like this: require "lib/init" class Reverser < Ruport::Controller stage :reverser end class ReverserFormatter < Ruport::Formatter renders :text, :for => Reverser def build_reverser output << data.reverse end end The tests should pass. You can now generate a quick report using this controller $ rake build report=reversed_report Edit test/test_reversed_report.rb as such: require "test/unit" require "lib/reports/reversed_report" class TestReversedReport < Test::Unit::TestCase def test_reversed_report report = ReversedReport.new report.message = "hello" assert_equal "olleh", report.to_text end end edit lib/reports/reversed_report.rb as below and run the tests. require "lib/init" require "lib/controllers/reverser" class ReversedReport < Ruport::Report renders_with Reverser attr_accessor :message def generate message end end # ActiveRecord integration the lazy way. Ruport now has built in support for acts_as_reportable, which provides ActiveRecord integration with ruport. -- Setup details Edit the following code in config/environment.rb (change as needed to match your config information) ActiveRecord::Base.establish_connection( :adapter => 'mysql', :host => 'localhost', :username => 'name', :password => 'password', :database => 'mydb' ) -- Generating a model Here is an example of generating the model file: $ util/build model my_model model file: data/models/my_model.rb class name: MyModel This will create a barebones model that looks like this: class MyModel < ActiveRecord::Base acts_as_reportable end The data/models.rb file will require all generated models, but you can of course require specific models in your reports. This should be enought to get you started, but for more complex needs, check the appropriate acts_as_reportable / ActiveRecord documentation. # Getting Help / Reporting Problems rope is an officially supported utility for the Ruby Reports project, in the ruport-util package. If you run into problems or have feature requests, please contact us at http://list.rubyreports.org END_README end end