Class: Praxis::ActionDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/praxis.rb,
lib/praxis/action_definition.rb,
lib/praxis/action_definition/headers_dsl_compiler.rb

Defined Under Namespace

Classes: HeadersDSLCompiler

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, resource_definition, **opts, &block) ⇒ ActionDefinition

Returns a new instance of ActionDefinition.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/praxis/action_definition.rb', line 29

def initialize(name, resource_definition, **opts, &block)
  @name = name
  @resource_definition = resource_definition
  @responses = Hash.new

  if (media_type = resource_definition.media_type)
    if media_type.kind_of?(Class) && media_type < Praxis::MediaType
      @reference_media_type = media_type
    end
  end

  resource_definition.action_defaults.each do |defaults|
    self.instance_eval(&defaults)
  end

  self.instance_eval(&block) if block_given?
end

Class Attribute Details

.doc_decorationsObject

Returns the value of attribute doc_decorations.



20
21
22
# File 'lib/praxis/action_definition.rb', line 20

def doc_decorations
  @doc_decorations
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



12
13
14
# File 'lib/praxis/action_definition.rb', line 12

def name
  @name
end

#named_routesObject (readonly)

Returns the value of attribute named_routes.



16
17
18
# File 'lib/praxis/action_definition.rb', line 16

def named_routes
  @named_routes
end

#primary_routeObject (readonly)

Returns the value of attribute primary_route.



15
16
17
# File 'lib/praxis/action_definition.rb', line 15

def primary_route
  @primary_route
end

#resource_definitionObject (readonly)

Returns the value of attribute resource_definition.



13
14
15
# File 'lib/praxis/action_definition.rb', line 13

def resource_definition
  @resource_definition
end

#responsesObject (readonly)

Returns the value of attribute responses.



17
18
19
# File 'lib/praxis/action_definition.rb', line 17

def responses
  @responses
end

#routesObject (readonly)

Returns the value of attribute routes.



14
15
16
# File 'lib/praxis/action_definition.rb', line 14

def routes
  @routes
end

Class Method Details

.decorate_docs(&callback) ⇒ Object



25
26
27
# File 'lib/praxis/action_definition.rb', line 25

def self.decorate_docs(&callback)
  self.doc_decorations << callback
end

Instance Method Details

#create_attribute(type = Attributor::Struct, **opts, &block) ⇒ Object



57
58
59
60
61
62
63
# File 'lib/praxis/action_definition.rb', line 57

def create_attribute(type=Attributor::Struct, **opts, &block)
  unless opts[:reference]
    opts[:reference] = @reference_media_type if @reference_media_type && block
  end

  return Attributor::Attribute.new(type, opts, &block)
end

#describeObject



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/praxis/action_definition.rb', line 146

def describe
  {}.tap do |hash|
    hash[:description] = description
    hash[:name] = name
    # FIXME: change to :routes along with api browser
    hash[:urls] = routes.collect(&:describe)
    hash[:headers] = headers.describe if headers
    hash[:params] = params.describe if params
    hash[:payload] = payload.describe if payload
    hash[:responses] = responses.inject({}) do |memo, (response_name, response)|
      memo[response.name] = response.describe
      memo
    end
    self.class.doc_decorations.each do |callback|
      callback.call(self, hash)
    end
  end
end

#description(text = nil) ⇒ Object



140
141
142
143
# File 'lib/praxis/action_definition.rb', line 140

def description(text = nil)
  @description = text if text
  @description
end

#headers(type = Attributor::Hash.of(key:String), **opts, &block) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
# File 'lib/praxis/action_definition.rb', line 102

def headers(type=Attributor::Hash.of(key:String), **opts, &block)
  return @headers unless block
  if @headers
    update_attribute(@headers, opts, block)
  else
    @headers = create_attribute(type,
      dsl_compiler: HeadersDSLCompiler, case_insensitive_load: true, 
      **opts, &block)
  end
  @precomputed_header_keys_for_rack = nil #clear memoized data
end

#params(type = Attributor::Struct, **opts, &block) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/praxis/action_definition.rb', line 72

def params(type=Attributor::Struct, **opts, &block)
  return @params if !block && type == Attributor::Struct

  if @params
    unless type == Attributor::Struct && @params.type < Attributor::Struct
      raise Exceptions::InvalidConfiguration.new(
        "Invalid type received for extending params: #{type.name}"
      )
    end
    update_attribute(@params, opts, block)
  else
    @params = create_attribute(type, **opts, &block)
  end
end

#payload(type = Attributor::Struct, **opts, &block) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/praxis/action_definition.rb', line 87

def payload(type=Attributor::Struct, **opts, &block)
  return @payload if !block && type == Attributor::Struct

  if @payload
    unless type == Attributor::Struct && @payload.type < Attributor::Struct
      raise Exceptions::InvalidConfiguration.new(
        "Invalid type received for extending params: #{type.name}"
      )
    end
    update_attribute(@payload, opts, block)
  else
    @payload = create_attribute(type, **opts, &block)
  end
end

#precomputed_header_keys_for_rackObject

Good optimization to avoid creating lots of strings and comparisons on a per-request basis. However, this is hacky, as it is rack-specific, and does not really belong here



117
118
119
120
121
122
123
124
125
# File 'lib/praxis/action_definition.rb', line 117

def precomputed_header_keys_for_rack
  @precomputed_header_keys_for_rack ||= begin
    @headers.attributes.keys.each_with_object(Hash.new) do |key,hash|
      name = key.to_s
      name = "HTTP_#{name.gsub('-','_').upcase}" unless ( name == "CONTENT_TYPE" || name == "CONTENT_LENGTH" )
      hash[name] = key
    end
  end
end

#response(name, **args) ⇒ Object



52
53
54
55
# File 'lib/praxis/action_definition.rb', line 52

def response( name, **args )
  template = ApiDefinition.instance.response(name)
  @responses[name] = template.compile(self, **args)
end

#routing(&block) ⇒ Object



128
129
130
131
132
133
134
135
136
137
# File 'lib/praxis/action_definition.rb', line 128

def routing(&block)
  routing_config = Skeletor::RestfulRoutingConfig.new(name, resource_definition, &block)

  @routes = routing_config.routes
  @primary_route = routing_config.routes.first
  @named_routes = routing_config.routes.each_with_object({}) do |route, hash|
    next if route.name.nil?
    hash[route.name] = route
  end
end

#update_attribute(attribute, options, block) ⇒ Object



47
48
49
50
# File 'lib/praxis/action_definition.rb', line 47

def update_attribute(attribute, options, block)
  attribute.options.merge!(options)
  attribute.type.attributes(options, &block)
end

#use(trait_name) ⇒ Object



65
66
67
68
69
70
# File 'lib/praxis/action_definition.rb', line 65

def use(trait_name)
  unless ApiDefinition.instance.traits.has_key? trait_name
    raise Exceptions::InvalidTrait.new("Trait #{trait_name} not found in the system")
  end
  self.instance_eval(&ApiDefinition.instance.traits[trait_name])
end