Class: Ruport::Controller

Inherits:
Object
  • 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:



284
285
286
# File 'lib/ruport/controller.rb', line 284

def final_stage
  @final_stage
end

.first_stageObject

:nodoc:



284
285
286
# File 'lib/ruport/controller.rb', line 284

def first_stage
  @first_stage
end

.required_optionsObject

:nodoc:



284
285
286
# File 'lib/ruport/controller.rb', line 284

def required_options
  @required_options
end

.stagesObject

:nodoc:



284
285
286
# File 'lib/ruport/controller.rb', line 284

def stages
  @stages
end

Instance Attribute Details

#formatObject

The name of format being used.



493
494
495
# File 'lib/ruport/controller.rb', line 493

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.



532
533
534
535
# File 'lib/ruport/controller.rb', line 532

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


216
217
218
219
220
221
222
# File 'lib/ruport/controller.rb', line 216

def built_in_formats
 { :html => Ruport::Formatter::HTML,
   :csv  => Ruport::Formatter::CSV,
   :pdf  => Ruport::Formatter::PrawnPDF,
   :prawn_pdf => Ruport::Formatter::PrawnPDF,
   :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.


308
309
310
311
312
313
# File 'lib/ruport/controller.rb', line 308

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}


412
413
414
# File 'lib/ruport/controller.rb', line 412

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


271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/ruport/controller.rb', line 271

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



540
541
542
543
544
545
546
# File 'lib/ruport/controller.rb', line 540

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:



444
445
446
447
448
449
# File 'lib/ruport/controller.rb', line 444

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.


337
338
339
340
341
342
# File 'lib/ruport/controller.rb', line 337

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.



428
429
430
431
432
433
434
435
436
# File 'lib/ruport/controller.rb', line 428

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


388
389
390
391
392
393
394
395
396
397
398
399
400
# File 'lib/ruport/controller.rb', line 388

def required_option(*opts) 
  (self.required_options ||= []).concat(opts)

  opts.each do |opt|
    unless method_defined?(opt)
      define_method(opt) { options.send(opt) }
    end
    setter = "#{opt}="
    unless method_defined?(setter)
      define_method(setter) {|t| options.send(setter, t) }
    end
  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.


371
372
373
374
375
376
# File 'lib/ruport/controller.rb', line 371

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.



499
500
501
# File 'lib/ruport/controller.rb', line 499

def data
  formatter.data
end

#data=(val) ⇒ Object

Sets data attribute on the active formatter.



504
505
506
# File 'lib/ruport/controller.rb', line 504

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



525
526
527
# File 'lib/ruport/controller.rb', line 525

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

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

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

Yields:



509
510
511
512
# File 'lib/ruport/controller.rb', line 509

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.



516
517
518
# File 'lib/ruport/controller.rb', line 516

def run
  _run_
end