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