Class: Bridgetown::Rack::Routes

Inherits:
Object
  • Object
show all
Includes:
Prioritizable
Defined in:
bridgetown-core/lib/bridgetown-core/rack/routes.rb

Direct Known Subclasses

Bridgetown::Routes::ManifestRouter

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Prioritizable

#<=>, included

Constructor Details

#initialize(roda_app) ⇒ Routes

Returns a new instance of Routes.

Parameters:



149
150
151
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 149

def initialize(roda_app)
  @_roda_app = roda_app
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name) ⇒ Object

Any missing methods are passed along to the underlying Roda app if possible



162
163
164
165
166
167
168
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 162

def method_missing(method_name, ...)
  if @_roda_app.respond_to?(method_name.to_sym)
    @_roda_app.send(method_name.to_sym, ...)
  else
    super
  end
end

Class Attribute Details

.router_blockProc

Returns:

  • (Proc)


49
50
51
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 49

def router_block
  @router_block
end

Class Method Details

.<=>(other) ⇒ Integer

Spaceship is priority [higher -> lower]

Parameters:

  • other (Class(Routes))

    The class to be compared.

Returns:

  • (Integer)

    -1, 0, 1.



55
56
57
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 55

def <=>(other)
  "#{priorities[priority]}#{self}" <=> "#{priorities[other.priority]}#{other}"
end

.load_all(roda_app) ⇒ void

This method returns an undefined value.

Set up live reload if allowed, then run through all the Routes blocks.

Parameters:



95
96
97
98
99
100
101
102
103
104
105
106
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 95

def load_all(roda_app)
  if Bridgetown.env.development? &&
      !Bridgetown::Current.preloaded_configuration.skip_live_reload
    setup_live_reload roda_app
  end

  Bridgetown::Rack::Routes.sorted_subclasses&.each do |klass|
    klass.merge roda_app
  end

  nil # required for proper 404 handling
end

.merge(roda_app) ⇒ Object

Initialize a new Routes instance and execute the route as part of the Roda app request cycle

Parameters:



85
86
87
88
89
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 85

def merge(roda_app)
  return unless router_block

  new(roda_app).handle_routes
end

rubocop:disable Bridgetown/NoPutsAllowed, Metrics/MethodLength



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 18

def print_routes
  # TODO: this needs to be fully documented
  routes = begin
    JSON.parse(
      File.read(
        File.join(Bridgetown::Current.preloaded_configuration.root_dir, ".routes.json")
      )
    )
  rescue StandardError
    []
  end
  puts
  puts "Routes:"
  puts "=======\n"
  if routes.blank?
    puts "No routes found. Have you commented all of your routes?"
    puts "Documentation: https://github.com/jeremyevans/roda-route_list#basic-usage-"
  end

  routes.each do |route|
    puts [
      route["methods"]&.join("|") || "GET",
      route["path"],
      route["file"] ? "\n  File: #{route["file"]}" : nil,
    ].compact.join(" ")
  end
  puts
end

.route(&block) ⇒ Object

Add a router block via the current Routes class

Example:

class Routes::Hello < Bridgetown::Rack::Routes route do |r| r.get “hello”, String do |name| { hello: “friend #name” } end end end

Parameters:

  • block (Proc)


77
78
79
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 77

def route(&block)
  self.router_block = block
end

.setup_live_reload(app) ⇒ Object

Parameters:



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 109

def setup_live_reload(app) # rubocop:disable Metrics
  sleep_interval = 0.5
  file_to_check = File.join(Bridgetown::Current.preloaded_configuration.destination,
                            "index.html")
  errors_file = Bridgetown.build_errors_path

  app.request.get "_bridgetown/live_reload" do
    @_mod = File.exist?(file_to_check) ? File.stat(file_to_check).mtime.to_i : 0
    event_stream = proc do |stream|
      Thread.new do
        loop do
          new_mod = File.exist?(file_to_check) ? File.stat(file_to_check).mtime.to_i : 0

          if @_mod < new_mod
            stream.write "data: reloaded!\n\n"
            break
          elsif File.exist?(errors_file)
            stream.write "event: builderror\ndata: #{File.read(errors_file).to_json}\n\n"
          else
            stream.write "data: #{new_mod}\n\n"
          end

          sleep sleep_interval
        rescue Errno::EPIPE # User refreshed the page
          break
        end
      ensure
        stream.close
      end
    end

    app.request.halt [200, {
      "Content-Type"  => "text/event-stream",
      "cache-control" => "no-cache",
    }, event_stream,]
  end
end

.sorted_subclassesArray<Class(Routes)>

Returns:



60
61
62
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 60

def sorted_subclasses
  Bridgetown::Rack::Routes.descendants.sort
end

Instance Method Details

#handle_routesObject

Execute the router block via the instance, passing it the Roda request

Returns:

  • (Object)

    whatever is returned by the router block as expected by the Roda API



157
158
159
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 157

def handle_routes
  instance_exec(@_roda_app.request, &self.class.router_block)
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


170
171
172
# File 'bridgetown-core/lib/bridgetown-core/rack/routes.rb', line 170

def respond_to_missing?(method_name, include_private = false)
  @_roda_app.respond_to?(method_name.to_sym, include_private) || super
end