Class: Sinatra::Hat::Maker

Inherits:
Object show all
Includes:
Authorization::Helpers, Actions, Extendor
Defined in:
lib/sinatras-hat/maker.rb

Overview

This is where it all comes together

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Actions

included, #set_cache_headers, #set_etag, #set_last_modified

Methods included from Authorization::Helpers

#authorized?, #protect!

Methods included from Extendor

#mount

Constructor Details

#initialize(klass, overrides = {}) ⇒ Maker



24
25
26
27
28
# File 'lib/sinatras-hat/maker.rb', line 24

def initialize(klass, overrides={})
  @klass = klass
  options.merge!(overrides)
  with(options)
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



8
9
10
# File 'lib/sinatras-hat/maker.rb', line 8

def app
  @app
end

#klassObject (readonly)

Returns the value of attribute klass.



8
9
10
# File 'lib/sinatras-hat/maker.rb', line 8

def klass
  @klass
end

Class Method Details

.action(name, path, options = {}, &block) ⇒ Object



14
15
16
17
18
# File 'lib/sinatras-hat/maker.rb', line 14

def self.action(name, path, options={}, &block)
  verb = options[:verb] || :get
  Router.cache << [verb, name, path]
  actions[name] = { :path => path, :verb => verb, :fn => block }
end

.actionsObject



10
11
12
# File 'lib/sinatras-hat/maker.rb', line 10

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

Instance Method Details

#after(action) {|HashMutator.new(responder.defaults[action])| ... } ⇒ Object

Allows the DSL for specifying custom flow controls in a #mount block by altering the responder’s defaults hash.

Yields:



50
51
52
# File 'lib/sinatras-hat/maker.rb', line 50

def after(action)
  yield HashMutator.new(responder.defaults[action])
end

#authenticator(&block) ⇒ Object

The authenticator block gets called before protected actions. It gets passed the basic auth username and password.



77
78
79
80
81
82
83
# File 'lib/sinatras-hat/maker.rb', line 77

def authenticator(&block)
  if block_given?
    options[:authenticator] = block
  else
    options[:authenticator]
  end
end

#finder(&block) ⇒ Object

The finder block is used when loading all records for the index action. It gets passed the model proxy and the request params hash.



56
57
58
59
60
61
62
# File 'lib/sinatras-hat/maker.rb', line 56

def finder(&block)
  if block_given?
    options[:finder] = block
  else
    options[:finder]
  end
end

#generate_routes!Object

Generates routes in the context of the given app.



151
152
153
# File 'lib/sinatras-hat/maker.rb', line 151

def generate_routes!
  Router.new(self).generate(@app)
end

#handle(action, request) ⇒ Object

Processes a request, using the action specified in actions.rb

TODO The work of handling a request should probably be wrapped

up in a class.


39
40
41
42
43
44
45
46
# File 'lib/sinatras-hat/maker.rb', line 39

def handle(action, request)
  request.error(404) unless only.include?(action)
  protect!(request) if protect.include?(action)
  
  log_with_benchmark(request, action) do
    instance_exec(request, &self.class.actions[action][:fn])
  end
end

#loggerObject

TODO Hook this into Rack::CommonLogger



170
171
172
# File 'lib/sinatras-hat/maker.rb', line 170

def logger
  @logger ||= Logger.new(self)
end

#modelObject

Handles ORM/model related logic.



165
166
167
# File 'lib/sinatras-hat/maker.rb', line 165

def model
  @model ||= Model.new(self)
end

#only(*actions) ⇒ Object

A list of actions that get generated by this maker instance. By default it’s all of the actions specified in actions.rb



87
88
89
90
91
92
93
# File 'lib/sinatras-hat/maker.rb', line 87

def only(*actions)
  if actions.empty?
    options[:only] ||= Set.new(options[:only])
  else
    Set.new(options[:only] = actions)
  end
end

#optionsObject

Default options



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/sinatras-hat/maker.rb', line 136

def options
  @options ||= {
    :only => Set.new(Maker.actions.keys),
    :parent => nil,
    :finder => proc { |model, params| model.all },
    :record => proc { |model, params| model.send("find_by_#{to_param}", params[:id]) },
    :protect => [ ],
    :formats => { },
    :to_param => :id,
    :credentials => { :username => 'username', :password => 'password', :realm => "The App" },
    :authenticator => proc { |username, password| [username, password] == [:username, :password].map(&credentials.method(:[])) }
  }
end

#parentsObject

An array of parent Maker instances under which this instance was nested.



125
126
127
# File 'lib/sinatras-hat/maker.rb', line 125

def parents
  @parents ||= parent ? parent.parents + Array(parent) : []
end

#prefixObject

The path prefix to use for routes and such.



119
120
121
# File 'lib/sinatras-hat/maker.rb', line 119

def prefix
  options[:prefix] ||= model.plural
end

#protect(*actions) ⇒ Object

A list of actions to protect via basic auth. Protected actions will have the authenticator block called before they are handled.



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/sinatras-hat/maker.rb', line 106

def protect(*actions)
  credentials.merge!(actions.extract_options!)
  
  if actions.empty?
    options[:protect] ||= Set.new([])
  else
    actions == [:all] ? 
      Set.new(options[:protect] = only) :
      Set.new(options[:protect] = actions)
  end
end

#record(&block) ⇒ Object

The finder block is used when loading a single record, which is the case for most actions. It gets passed the model proxy and the request params hash.



67
68
69
70
71
72
73
# File 'lib/sinatras-hat/maker.rb', line 67

def record(&block)
  if block_given?
    options[:record] = block
  else
    options[:record]
  end
end

#resource_path(*args) ⇒ Object

Looks up the resource path for the specified arguments using this maker’s Resource instance.



131
132
133
# File 'lib/sinatras-hat/maker.rb', line 131

def resource_path(*args)
  resource.path(*args)
end

#responderObject

The responder determines what kind of response should used for a given action.

TODO It might be better off to instantiate a new one of these per request, instead of having one per maker instance.



160
161
162
# File 'lib/sinatras-hat/maker.rb', line 160

def responder
  @responder ||= Responder.new(self)
end

#setup(app) ⇒ Object

Simply stores the app instance when #mount is called.



31
32
33
# File 'lib/sinatras-hat/maker.rb', line 31

def setup(app)
  @app = app
end

#to_param(name = nil) ⇒ Object

A way to determine a record’s representation in the database



96
97
98
99
100
101
102
# File 'lib/sinatras-hat/maker.rb', line 96

def to_param(name=nil)
  if name
    options[:to_param] = name
  else
    options[:to_param]
  end
end