Class: Saper::Action

Inherits:
Object
  • Object
show all
Defined in:
lib/saper/core/action.rb

Constant Summary collapse

INPUT_TYPES =
text atom document html json markdown nothing time url xml

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Saper::Action

Returns a new instance of Saper::Action.


149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/saper/core/action.rb', line 149

def initialize(*args)
  @arguments = []
  @options   = {}
  if args.last.is_a?(Hash)
    @options = args.pop
  end
  self.class.arguments.each_with_index do |opts, i|
    opts.merge!(:value => args[i], :action => self)
    @arguments << Argument.new(opts[:type], opts)
  end
  if block_given?
    yield self
  end
end

Instance Attribute Details

#argumentsObject (readonly)


145
146
147
# File 'lib/saper/core/action.rb', line 145

def arguments
  @arguments
end

#optionsObject (readonly)


142
143
144
# File 'lib/saper/core/action.rb', line 142

def options
  @options
end

Class Method Details

.[](type) ⇒ Saper::Action

Returns a subclass with specified type.


27
28
29
# File 'lib/saper/core/action.rb', line 27

def self.[](type)
  subclasses[type.to_s] || raise(Errors::ActionNotFound, type)
end

.accepts(input = nil, options = {}) ⇒ Array<Symbol>, ...

Sets or returns acceptable input types.


52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/saper/core/action.rb', line 52

def self.accepts(input = nil, options = {})
  @types ||= {}
  if input.nil?
    return @types.keys
  end
  if input.is_a? Proc
    @input = input; input = :anything
  end
  if input == :anything
    return INPUT_TYPES.each { |type| accepts(type, options) }
  end
  @types[input] = options[:returns] || input
end

.accepts?(type, instance = nil) ⇒ Boolean

Returns `true` if action accepts specified type as input.


70
71
72
73
74
75
76
77
78
# File 'lib/saper/core/action.rb', line 70

def self.accepts?(type, instance = nil)
  if @input.nil?
    return accepts.include?(type)
  end
  if instance.nil?
    raise(RuntimeRequired)
  end
  @input.call(instance, type)
end

.argument(type, options = {}) ⇒ void

This method returns an undefined value.

Defines a new argument.


35
36
37
38
39
40
41
# File 'lib/saper/core/action.rb', line 35

def self.argument(type, options = {})
  if Argument.exists?(type)
    arguments.push options.merge(:type => type)
  else
    raise(Errors::InvalidType, "Invalid action argument: %s" % type)
  end
end

.argumentsArray<Hash>

Returns a list of arguments assigned to this action.


45
46
47
# File 'lib/saper/core/action.rb', line 45

def self.arguments
  @arguments ||= []
end

.inherited(base) ⇒ Class

Tracks subclasses of Saper::Action.


8
9
10
# File 'lib/saper/core/action.rb', line 8

def self.inherited(base)
  subclasses[base.type] = base
end

.new(*args, &block) ⇒ Saper::Action

Returns a new instance of Saper::Action.


133
134
135
136
137
138
139
# File 'lib/saper/core/action.rb', line 133

def self.new(*args, &block)
  if self == Action
    self[args.shift].new(*args, &block)
  else
    super(*args, &block)
  end
end

.output_for(type, instance = nil, runtime = nil) ⇒ Array<Symbol>

Returns the type of output for specfied input type.


90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/saper/core/action.rb', line 90

def self.output_for(type, instance = nil, runtime = nil)
  unless accepts?(type, instance)
    return :nothing
  end
  unless @types[type].is_a?(Proc)
    return @types[type]
  end
  if instance.nil?
    raise Errors::RuntimeRequired
  end
  @types[type].call(instance, type, runtime)
end

.returns_multiple_items!void

This method returns an undefined value.

Sets a flag, indicating that this action returns multiple items.


110
111
112
# File 'lib/saper/core/action.rb', line 110

def self.returns_multiple_items!
  @multiple = true
end

.returns_multiple_items?Boolean

Returns `true` if action returns multiple items. Note that this method will report incorrect data for some actions. Use #multiple? instead.


104
105
106
# File 'lib/saper/core/action.rb', line 104

def self.returns_multiple_items?
  @multiple == true
end

.run(&block) ⇒ void

This method returns an undefined value.

Saves Proc that encapsulates action logic and will be used later for data processing.


82
83
84
# File 'lib/saper/core/action.rb', line 82

def self.run(&block)
  @block ||= block
end

.subclassesHash

Returns a hash of subclasses.


14
15
16
# File 'lib/saper/core/action.rb', line 14

def self.subclasses
  @subclasses ||= {}
end

.typeString

Returns class name as an underscored string.


20
21
22
# File 'lib/saper/core/action.rb', line 20

def self.type
  name.split("::").last.gsub(/([a-z])([A-Z])/,'\1_\2').downcase
end

.unserialize(data, namespace = nil, &block) ⇒ Saper::Action

Returns a new instance of Saper::Action.


117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/saper/core/action.rb', line 117

def self.unserialize(data, namespace = nil, &block)
  if data.is_a?(Array)
    return data.map { |item| unserialize(item, namespace) }
  end
  unless data.is_a?(Hash)
    raise Errors::InvalidAction.new(data)
  end
  new(data[:type], *data[:args], :namespace => namespace) do |action|
    if block_given?
      yield action
    end
  end
end

Instance Method Details

#accepts?(type) ⇒ Boolean

Returns `true` if action accepts specified type as input.


189
190
191
# File 'lib/saper/core/action.rb', line 189

def accepts?(type)
  self.class.accepts?(type, self)
end

#argsArray

Returns values of action arguments.


203
204
205
# File 'lib/saper/core/action.rb', line 203

def args
  @arguments.map(&:value)
end

#blockProc

Returns Proc that encapsulates action logic (i.e. processes data).


227
228
229
# File 'lib/saper/core/action.rb', line 227

def block
  self.class.run || Proc.new { |runtime, input, *args| input }
end

#multiple?Boolean

Returns `true` if action returns multiple items.


221
222
223
# File 'lib/saper/core/action.rb', line 221

def multiple?
  self.class.returns_multiple_items?
end

#nameString

Returns human readable action name.


176
177
178
# File 'lib/saper/core/action.rb', line 176

def name
  self.class.name.split("::").last.gsub(/([a-z])([A-Z])/,'\1 \2')
end

#namespaceNamespace

Returns Saper::Namespace instance.


182
183
184
# File 'lib/saper/core/action.rb', line 182

def namespace
  @options[:namespace].is_a?(Namespace) ? @options[:namespace] : nil
end

#output_for(type, runtime = nil) ⇒ Array<Symbol>

Returns the type of output for specfied input type.


197
198
199
# File 'lib/saper/core/action.rb', line 197

def output_for(type, runtime = nil)
  self.class.output_for(type, self, runtime)
end

#run(input = nil, runtime = nil) ⇒ void

This method returns an undefined value.

Runs action and returns results.


167
168
169
170
171
172
# File 'lib/saper/core/action.rb', line 167

def run(input = nil, runtime = nil)
  runtime ||= Runtime.new(input.is_a?(Hash) ? input : {})
  input  = validate_input(input)
  output = block.call(runtime, input, *args)
  validate_output output, output_for(input.type, runtime)
end

#serializeHash

Returns a serialized representation of this action.


209
210
211
# File 'lib/saper/core/action.rb', line 209

def serialize
  { :type => self.class.type, :args => @arguments.map(&:serialize) }
end

#to_json(*args) ⇒ String

Returns a JSON representation of this action.


215
216
217
# File 'lib/saper/core/action.rb', line 215

def to_json(*args)
  serialize.to_json(*args)
end

#to_stringString

Returns string representation of Action.


233
234
235
# File 'lib/saper/core/action.rb', line 233

def to_string
  "\t%s %s" % [self.class.type, @arguments.map(&:to_string).join(", ")]
end