Class: Ruport::Controller

Inherits:
Object show all
Defined in:
lib/ruport/controller.rb

Overview

This class implements the core controller for Ruport’s formatting system. It is designed to implement the low level tools necessary to build report controllers for different kinds of tasks. See Controller::Table for a tabular data controller.

Direct Known Subclasses

Group, Grouping, Row, Table

Defined Under Namespace

Modules: Hooks Classes: ControllerNotSetError, Group, Grouping, Options, RequiredOptionNotSet, Row, StageAlreadyDefinedError, Table, UnknownFormatError

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.final_stageObject

:nodoc:



287
288
289
# File 'lib/ruport/controller.rb', line 287

def final_stage
  @final_stage
end

.first_stageObject

:nodoc:



287
288
289
# File 'lib/ruport/controller.rb', line 287

def first_stage
  @first_stage
end

.required_optionsObject

:nodoc:



287
288
289
# File 'lib/ruport/controller.rb', line 287

def required_options
  @required_options
end

.stagesObject

:nodoc:



287
288
289
# File 'lib/ruport/controller.rb', line 287

def stages
  @stages
end

Instance Attribute Details

#formatObject

The name of format being used.



496
497
498
# File 'lib/ruport/controller.rb', line 496

def format
  @format
end

#formatter(&block) ⇒ Object

Returns the active formatter.

If a block is given, it is evaluated in the context of the formatter.



535
536
537
538
# File 'lib/ruport/controller.rb', line 535

def formatter(&block)
  @formatter.instance_eval(&block) if block   
  return @formatter
end

Class Method Details

.built_in_formatsObject

Returns a hash that maps format names to their formatter classes, for use with the formatter shortcut. Supported formats are :html, :csv, :pdf, and :text by default.

Sample override:

class MyController < Ruport::Controller

  def built_in_formats
    super.extend(:xml => MyXMLFormatter,
                 :json => MyJSONFormatter)
  end
end

This would allow for:

class ChildController < MyController

  formatter :xml do
    # ...
  end

  formatter :json do
    # ...
  end
end


220
221
222
223
224
225
# File 'lib/ruport/controller.rb', line 220

def built_in_formats
 { :html => Ruport::Formatter::HTML,
   :csv  => Ruport::Formatter::CSV,
   :pdf  => Ruport::Formatter::PDF,
   :text => Ruport::Formatter::Text }
end

.finalize(stage) ⇒ Object

Registers a hook to look for in the Formatter object when the render() method is called.

Usage:

 class MyController < Ruport::Controller
    # other details omitted...
    finalize :apple
 end

 class MyFormatter < Ruport::Formatter
    renders :example, :for => MyController

    # other details omitted... 

    def finalize_apple
       # this method will be called when MyController tries to render
       # the :example format
    end
 end  

If a formatter does not implement this hook, it is simply ignored.


311
312
313
314
315
316
# File 'lib/ruport/controller.rb', line 311

def finalize(stage)
  if final_stage
    raise StageAlreadyDefinedError, 'final stage already defined'      
  end
  self.final_stage = stage
end

.formatsObject

Lists the formatters that are currently registered on a controller, as a hash keyed by format name.

Example:

>> Ruport::Controller::Table.formats
=> {:html=>Ruport::Formatter::HTML, 
?>  :csv=>Ruport::Formatter::CSV, 
?>  :text=>Ruport::Formatter::Text, 
?>  :pdf=>Ruport::Formatter::PDF}


415
416
417
# File 'lib/ruport/controller.rb', line 415

def formats
  @formats ||= {}
end

.formatter(*a, &b) ⇒ Object

Generates an anonymous formatter class and ties it to the Controller. This method looks up the built in formats in the hash returned by built_in_formats, but also explicitly specify a custom Formatter class to subclass from.

Sample usage:

class ControllerWithAnonymousFormatters < Ruport::Controller

  stage :report

  formatter :html do
    build :report do
      output << textile("h1. Hi there")
    end
  end

  formatter :csv do
    build :report do
      build_row([1,2,3])
    end
  end

  formatter :pdf do
    build :report do
      add_text "hello world"
    end
  end

  formatter :text do
    build :report do
      output << "Hello world"
    end
  end

  formatter :custom => CustomFormatter do

    build :report do
      output << "This is "
      custom_helper
    end

  end

end


274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/ruport/controller.rb', line 274

def formatter(*a,&b)
  case a[0]
  when Symbol
    klass = Class.new(built_in_formats[a[0]])
    klass.renders a[0], :for => self
  when Hash
    k,v = a[0].to_a[0]
    klass = Class.new(v)
    klass.renders k, :for => self
  end
  klass.class_eval(&b)
end

.method_missing(id, *args, &block) ⇒ Object

Provides a shortcut to render() to allow render(:csv) to become render_csv



543
544
545
546
547
548
549
# File 'lib/ruport/controller.rb', line 543

def self.method_missing(id,*args,&block)
  id.to_s =~ /^render_(.*)/
  unless args[0].kind_of? Hash
    args = [ (args[1] || {}).merge(:data => args[0]) ]
  end
  $1 ? render($1.to_sym,*args,&block) : super
end

.options {|@options| ... } ⇒ Object

Allows you to set class-wide default options.

Example:

options { |o| o.style = :justified }

Yields:



447
448
449
450
451
452
# File 'lib/ruport/controller.rb', line 447

def options
  @options ||= Ruport::Controller::Options.new
  yield(@options) if block_given?

  return @options
end

.prepare(stage) ⇒ Object

Registers a hook to look for in the Formatter object when the render() method is called.

Usage:

 class MyController < Ruport::Controller
    # other details omitted...
    prepare :apple
 end

 class MyFormatter < Ruport::Formatter
    renders :example, :for => MyController

    def prepare_apple
       # this method will be called when MyController tries to render
       # the :example format
    end        

    # other details omitted...
 end  

If a formatter does not implement this hook, it is simply ignored.


340
341
342
343
344
345
# File 'lib/ruport/controller.rb', line 340

def prepare(stage)
  if first_stage
    raise StageAlreadyDefinedError, "prepare stage already defined"      
  end 
  self.first_stage = stage
end

.render(format, add_options = nil) ⇒ Object

Builds up a controller object, looks up the appropriate formatter, sets the data and options, and then does the following process:

* If the controller contains a module Helpers, mix it in to the instance.
* If a block is given, yield the Controller instance.
* If a setup() method is defined on the Controller, call it.
* Call the run() method.
* If the :file option is set to a file name, appends output to the file.
* Return the results of formatter.output

Please see the examples/ directory for custom controller examples, because this is not nearly as complicated as it sounds in most cases.



431
432
433
434
435
436
437
438
439
# File 'lib/ruport/controller.rb', line 431

def render(format, add_options=nil)
  rend = build(format, add_options) { |r|
      yield(r) if block_given?   
    r.setup if r.respond_to? :setup
  }  
  rend.run
  rend.formatter.save_output(rend.options.file) if rend.options.file
  return rend.formatter.output
end

.required_option(*opts) ⇒ Object

Defines attribute writers for the Controller::Options object shared between Controller and Formatter. Will throw an error if the user does not provide values for these options upon rendering.

usage:

class MyController < Ruport::Controller
   required_option :employee_name, :address
   # other details omitted
end


391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/ruport/controller.rb', line 391

def required_option(*opts) 
  self.required_options ||= []
  opts.each do |opt|
    self.required_options << opt 

    o = opt
    unless instance_methods(false).include?(o.to_s)
      define_method(o) { options.send(o.to_s) }
    end
    opt = "#{opt}="
    define_method(opt) {|t| options.send(opt, t) }
  end
end

.stage(*stage_list) ⇒ Object

Registers hooks to look for in the Formatter object when the render() method is called.

Usage:

 class MyController < Ruport::Controller
    # other details omitted...
    stage :apple,:banana
 end

 class MyFormatter < Ruport::Formatter
    renders :example, :for => MyController

    def build_apple
       # this method will be called when MyController tries to render
       # the :example format
    end 

    def build_banana
       # this method will be called when MyController tries to render
       # the :example format
    end    

    # other details omitted...
 end  

If a formatter does not implement these hooks, they are simply ignored.


374
375
376
377
378
379
# File 'lib/ruport/controller.rb', line 374

def stage(*stage_list)
  self.stages ||= []
  stage_list.each { |stage|
    self.stages << stage.to_s 
  }
end

Instance Method Details

#dataObject

The data that has been passed to the active formatter.



502
503
504
# File 'lib/ruport/controller.rb', line 502

def data
  formatter.data
end

#data=(val) ⇒ Object

Sets data attribute on the active formatter.



507
508
509
# File 'lib/ruport/controller.rb', line 507

def data=(val)
  formatter.data = val
end

#io=(obj) ⇒ Object

If an IO object is given, Formatter#output will use it instead of the default String. For Ruport’s core controllers, we technically can use any object that supports the << method, but it’s meant for IO objects such as File or STDOUT



528
529
530
# File 'lib/ruport/controller.rb', line 528

def io=(obj)
  options.io=obj    
end

#options {|formatter.options| ... } ⇒ Object

Controller::Options object which is shared with the current formatter.

Yields:



512
513
514
515
# File 'lib/ruport/controller.rb', line 512

def options
  yield(formatter.options) if block_given?
  formatter.options
end

#runObject

Call the run method. You can override this method in your custom controller if you need to define other actions.



519
520
521
# File 'lib/ruport/controller.rb', line 519

def run
  _run_
end