Module: Gear::Nancy

Defined in:
lib/gear/nancy.rb

Overview

Nancy

Nancy is Camping gear that adds Sinatra style routing shortcuts to the Object namespace and to camping controllers themselves:

get '/' {
  "Hello World"
}

Calling the get method creates a controller, and in the event of no default app yet, creates an app named Frank.

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Class Method Details

.controller_script(name:, routes:) ⇒ Object

returns a formatted string for making a controller class in the Controllers module



128
129
130
131
132
133
# File 'lib/gear/nancy.rb', line 128

def controller_script(name:, routes:)
	%Q[
		class #{name} < R #{routes}
		end
	]
end

.ensure_app(app) ⇒ Object

ensures an app exists for the controllers.



39
40
41
42
43
44
45
46
47
48
# File 'lib/gear/nancy.rb', line 39

def ensure_app(app)
	if Camping::Apps.count == 0
		# In the case of a naked sinatra style invokation
		Camping.goes :Frank
		m = Camping::Apps.first
	else
		m = app
	end
	m
end

.included(mod) ⇒ Object



135
136
137
138
# File 'lib/gear/nancy.rb', line 135

def included(mod)
	mod.extend(ClassMethods)
	mod::Controllers.extend(ClassMethods)
end

.make_camping_route(method, routes, app = nil, &block) ⇒ Object

Make a camping route provided with a method type, a route, an optional app, and a required block:

get '/another/thing' do
  render :another_view
end

Calling the shorthand make route helper methods inside of an app module, adds The route to that App. If you don’t have any apps yet, then an app named Frank will be made for you.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/gear/nancy.rb', line 60

def make_camping_route(method, routes, app=nil, &block)

	inf = caller.first.split(":")
	file_name, line_number = inf[0], inf[1]

	meth = method.to_s

	self.normalize_routes(routes) => {rs:, symbol:}

	m = self.ensure_app app

	# Controller name
	cname = "#{meth.capitalize}#{symbol.to_s}"

	begin

		# Find out which eval script to use.
		eval_script = m.name.include?("Controllers") ? controller_script(name: cname,routes: rs) : module_script(name: cname,routes: rs)

		m.module_eval(eval_script, file_name, line_number.to_i)
	rescue => error
		if error.message.include? "superclass mismatch for class"
			raise "You've probably tried to define the same route twice using the sinatra method. ['#{rs}']"
		else
			raise error
		end
	end

	# This is an interesting block. At times we'll pass an App to a route
	# which will implicitly call it's `to_proc` method. In those cases, it's
	# that block that is set as the block here, and it returns a Rack response.
	# If we have a rack response instead of string, then we need to extract
	# the response then reassign the values. the r method  is a great helper
	# for that.
	constantine = m.name.include?("Controllers") ? m.const_get("#{cname}") : m::X.const_get("#{cname}")

	if block.arity == -1
		constantine.send(:define_method, meth) { |*args|
			block[*args]
		}
	elsif block.arity == 1
		constantine.send(:define_method, meth) {
			res = block[@env] # if we're forwarding a response
			status = res[0]
			headers = res[1]
			body = res[2].flatten.first
			r(status, body, headers)
		}
	else # assuming arity is 0
		constantine.send(:define_method, meth) {
			block[]
		}
	end

	return nil
end

.module_script(name:, routes:) ⇒ Object

returns a formatted string for making a controller class in the App module



118
119
120
121
122
123
124
125
# File 'lib/gear/nancy.rb', line 118

def module_script(name:, routes:)
	%Q[
	module Controllers
		class #{name} < R #{routes}
		end
	end
	]
end

.normalize_routes(routes) ⇒ Object

normalizes the routes provided to the controller, then returns some variables used in make_camping_route



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/gear/nancy.rb', line 20

def normalize_routes(routes)
	s = ""
	rs = ""
	routes.each do |r|
		rs += "'#{r}'" + ","
		if r == '/'
			r = 'Index'
		end
		r.split("/").each(&:capitalize!).each{|t|
			s << t.gsub(/[^a-z0-9A-Z ]/, '')
		}
	end
	rs.chop!

	symbol = s.to_sym
	{rs: rs, symbol: symbol}
end

.setup(app, *a, &block) ⇒ Object

required for compliance reasons



141
# File 'lib/gear/nancy.rb', line 141

def setup(app, *a, &block) end