Class: Flipper::UI::Action
- Inherits:
-
Object
- Object
- Flipper::UI::Action
- Extended by:
- Forwardable
- Defined in:
- lib/flipper/ui/action.rb
Direct Known Subclasses
Flipper::UI::Actions::ActorsGate, Flipper::UI::Actions::AddFeature, Flipper::UI::Actions::BooleanGate, Flipper::UI::Actions::Export, Flipper::UI::Actions::Feature, Flipper::UI::Actions::Features, Flipper::UI::Actions::File, Flipper::UI::Actions::GroupsGate, Flipper::UI::Actions::Home, Flipper::UI::Actions::Import, Flipper::UI::Actions::PercentageOfActorsGate, Flipper::UI::Actions::PercentageOfTimeGate, Flipper::UI::Actions::Settings
Defined Under Namespace
Modules: FeatureNameFromRoute Classes: Breadcrumb
Constant Summary collapse
- VALID_REQUEST_METHOD_NAMES =
Set.new([ 'get'.freeze, 'post'.freeze, 'put'.freeze, 'delete'.freeze, ]).freeze
- SOURCES =
{ bootstrap_css: { src: '/css/bootstrap-4.6.0.min.css'.freeze, hash: 'sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l'.freeze }.freeze, jquery_js: { src: '/js/jquery-3.6.0.slim.js'.freeze, hash: 'sha256-HwWONEZrpuoh951cQD1ov2HUK5zA5DwJ1DNUXaM6FsY='.freeze }.freeze, popper_js: { src: '/js/popper-1.12.9.min.js'.freeze, hash: 'sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q'.freeze }.freeze, bootstrap_js: { src: '/js/bootstrap-4.6.0.min.js'.freeze, hash: 'sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF'.freeze }.freeze }.freeze
- CONTENT_SECURITY_POLICY =
<<-CSP.delete("\n") default-src 'none'; img-src 'self'; font-src 'self'; script-src 'report-sample' 'self'; style-src 'self' 'unsafe-inline'; style-src-attr 'unsafe-inline' ; style-src-elem 'self'; CSP
Instance Attribute Summary collapse
-
#flipper ⇒ Object
readonly
Public: The instance of the Flipper::DSL the middleware was initialized with.
-
#request ⇒ Object
readonly
Public: The Rack::Request to provide a response for.
Class Method Summary collapse
-
.public_path ⇒ Object
Private: The path to the public folder.
-
.route(regex) ⇒ Object
Public: Call this in subclasses so the action knows its route.
-
.route_match?(path) ⇒ Boolean
Internal: Does this action’s route match the path.
-
.route_regex ⇒ Object
Internal: The regex that matches which routes this action will work for.
-
.run(flipper, request) ⇒ Object
Internal: Initializes and runs an action for a given request.
-
.views_path ⇒ Object
Private: The path to the views folder.
Instance Method Summary collapse
- #bootstrap_css ⇒ Object
- #bootstrap_js ⇒ Object
-
#breadcrumb(text, href = nil) ⇒ Object
Public: Add a breadcrumb to the trail.
- #csrf_input_tag ⇒ Object
-
#halt(response) ⇒ Object
Public: Call this with a response to immediately stop the current action and respond however you want.
-
#header(name, value) ⇒ Object
Public: Set a header.
-
#initialize(flipper, request) ⇒ Action
constructor
A new instance of Action.
- #jquery_js ⇒ Object
-
#json_response(object) ⇒ Object
Public: Dumps an object as json and returns rack response with that as the body.
- #popper_js ⇒ Object
-
#public_path ⇒ Object
Private.
-
#read_only ⇒ Object
Internal: Method to call when the UI is in read only mode and you want to inform people of that fact.
-
#redirect_to(location) ⇒ Object
Public: Redirect to a new location.
-
#request_method_name ⇒ Object
Private: Returns the request method converted to an action method.
-
#run ⇒ Object
Public: Runs the request method for the provided request.
-
#run_other_action(action_class) ⇒ Object
Public: Runs another action from within the request method of a different action.
-
#script_name ⇒ Object
Internal: The path the app is mounted at.
-
#status(code) ⇒ Object
Public: Set the status code for the response.
- #valid_request_method? ⇒ Boolean
-
#view(name) ⇒ Object
Private.
-
#view_response(name) ⇒ Object
Public: Compiles a view and returns rack response with that as the body.
-
#view_with_layout(&block) ⇒ Object
Private.
-
#view_without_layout(name) ⇒ Object
Private.
-
#views_path ⇒ Object
Private.
Constructor Details
#initialize(flipper, request) ⇒ Action
Returns a new instance of Action.
107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/flipper/ui/action.rb', line 107 def initialize(flipper, request) @flipper = flipper @request = request @code = 200 @headers = { 'content-type' => 'text/plain' } @breadcrumbs = if Flipper::UI.configuration. [Breadcrumb.new('App', Flipper::UI.configuration.)] else [] end end |
Instance Attribute Details
#flipper ⇒ Object (readonly)
Public: The instance of the Flipper::DSL the middleware was initialized with.
99 100 101 |
# File 'lib/flipper/ui/action.rb', line 99 def flipper @flipper end |
#request ⇒ Object (readonly)
Public: The Rack::Request to provide a response for.
102 103 104 |
# File 'lib/flipper/ui/action.rb', line 102 def request @request end |
Class Method Details
.public_path ⇒ Object
Private: The path to the public folder.
93 94 95 |
# File 'lib/flipper/ui/action.rb', line 93 def self.public_path @public_path ||= Flipper::UI.root.join('public') end |
.route(regex) ⇒ Object
Public: Call this in subclasses so the action knows its route.
regex - The Regexp that this action should run for.
Returns nothing.
63 64 65 |
# File 'lib/flipper/ui/action.rb', line 63 def self.route(regex) @route_regex = regex end |
.route_match?(path) ⇒ Boolean
Internal: Does this action’s route match the path.
68 69 70 |
# File 'lib/flipper/ui/action.rb', line 68 def self.route_match?(path) path.match(route_regex) end |
.route_regex ⇒ Object
Internal: The regex that matches which routes this action will work for.
73 74 75 |
# File 'lib/flipper/ui/action.rb', line 73 def self.route_regex @route_regex || raise("#{name}.route is not set") end |
.run(flipper, request) ⇒ Object
Internal: Initializes and runs an action for a given request.
flipper - The Flipper::DSL instance. request - The Rack::Request that was sent.
Returns result of Action#run.
83 84 85 |
# File 'lib/flipper/ui/action.rb', line 83 def self.run(flipper, request) new(flipper, request).run end |
Instance Method Details
#bootstrap_css ⇒ Object
289 290 291 |
# File 'lib/flipper/ui/action.rb', line 289 def bootstrap_css SOURCES[:bootstrap_css] end |
#bootstrap_js ⇒ Object
293 294 295 |
# File 'lib/flipper/ui/action.rb', line 293 def bootstrap_js SOURCES[:bootstrap_js] end |
#breadcrumb(text, href = nil) ⇒ Object
Public: Add a breadcrumb to the trail.
text - The String text for the breadcrumb. href - The String href for the anchor tag (optional). If nil, breadcrumb
is assumed to be the end of the trail.
226 227 228 229 |
# File 'lib/flipper/ui/action.rb', line 226 def (text, href = nil) = href.nil? ? href : "#{script_name}#{href}" @breadcrumbs << Breadcrumb.new(text, ) end |
#csrf_input_tag ⇒ Object
269 270 271 |
# File 'lib/flipper/ui/action.rb', line 269 def csrf_input_tag %(<input type="hidden" name="authenticity_token" value="#{@request.session[:csrf]}">) end |
#halt(response) ⇒ Object
Public: Call this with a response to immediately stop the current action and respond however you want.
response - The response you would like to return.
151 152 153 |
# File 'lib/flipper/ui/action.rb', line 151 def halt(response) throw :halt, response end |
#header(name, value) ⇒ Object
Public: Set a header.
name - The String name of the header. value - The value of the header.
204 205 206 |
# File 'lib/flipper/ui/action.rb', line 204 def header(name, value) @headers[name] = value end |
#jquery_js ⇒ Object
301 302 303 |
# File 'lib/flipper/ui/action.rb', line 301 def jquery_js SOURCES[:jquery_js] end |
#json_response(object) ⇒ Object
Public: Dumps an object as json and returns rack response with that as the body. Automatically sets content-type to “application/json”.
object - The Object that should be dumped as json.
Returns a response.
173 174 175 176 177 178 179 180 181 182 |
# File 'lib/flipper/ui/action.rb', line 173 def json_response(object) header 'content-type', 'application/json' body = case object when String object else JSON.dump(object) end halt [@code, @headers, [body]] end |
#popper_js ⇒ Object
297 298 299 |
# File 'lib/flipper/ui/action.rb', line 297 def popper_js SOURCES[:popper_js] end |
#public_path ⇒ Object
Private
260 261 262 |
# File 'lib/flipper/ui/action.rb', line 260 def public_path self.class.public_path end |
#read_only ⇒ Object
Internal: Method to call when the UI is in read only mode and you want to inform people of that fact.
279 280 281 282 283 284 285 286 287 |
# File 'lib/flipper/ui/action.rb', line 279 def read_only status 403 'Home', '/' 'Features', '/features' 'Noooooope' halt view_response(:read_only) end |
#redirect_to(location) ⇒ Object
Public: Redirect to a new location.
location - The String location to set the Location header to.
187 188 189 190 191 |
# File 'lib/flipper/ui/action.rb', line 187 def redirect_to(location) status 302 header 'location', "#{script_name}#{Rack::Utils.escape_path(location)}" halt [@code, @headers, ['']] end |
#request_method_name ⇒ Object
Private: Returns the request method converted to an action method.
265 266 267 |
# File 'lib/flipper/ui/action.rb', line 265 def request_method_name @request_method_name ||= @request.request_method.downcase end |
#run ⇒ Object
Public: Runs the request method for the provided request.
Returns whatever the request method returns in the action.
123 124 125 126 127 128 129 130 |
# File 'lib/flipper/ui/action.rb', line 123 def run if valid_request_method? && respond_to?(request_method_name) catch(:halt) { send(request_method_name) } else raise UI::RequestMethodNotSupported, "#{self.class} does not support request method #{request_method_name.inspect}" end end |
#run_other_action(action_class) ⇒ Object
Public: Runs another action from within the request method of a different action.
action_class - The class of the other action to run.
Examples
run_other_action Home
# => result of running Home action
Returns result of other action.
143 144 145 |
# File 'lib/flipper/ui/action.rb', line 143 def run_other_action(action_class) action_class.new(flipper, request).run end |
#script_name ⇒ Object
Internal: The path the app is mounted at.
250 251 252 |
# File 'lib/flipper/ui/action.rb', line 250 def script_name request.env['SCRIPT_NAME'] end |
#status(code) ⇒ Object
Public: Set the status code for the response.
code - The Integer code you would like the response to return.
196 197 198 |
# File 'lib/flipper/ui/action.rb', line 196 def status(code) @code = code.to_i end |
#valid_request_method? ⇒ Boolean
273 274 275 |
# File 'lib/flipper/ui/action.rb', line 273 def valid_request_method? VALID_REQUEST_METHOD_NAMES.include?(request_method_name) end |
#view(name) ⇒ Object
Private
242 243 244 245 246 247 |
# File 'lib/flipper/ui/action.rb', line 242 def view(name) path = views_path.join("#{name}.erb") raise "Template does not exist: #{path}" unless path.exist? eval(Erubi::Engine.new(path.read, escape: true).src) end |
#view_response(name) ⇒ Object
Public: Compiles a view and returns rack response with that as the body.
name - The Symbol name of the view.
Returns a response.
160 161 162 163 164 165 |
# File 'lib/flipper/ui/action.rb', line 160 def view_response(name) header 'content-type', 'text/html' header 'content-security-policy', CONTENT_SECURITY_POLICY body = view_with_layout { view_without_layout name } halt [@code, @headers, [body]] end |
#view_with_layout(&block) ⇒ Object
Private
232 233 234 |
# File 'lib/flipper/ui/action.rb', line 232 def view_with_layout(&block) view :layout, &block end |
#view_without_layout(name) ⇒ Object
Private
237 238 239 |
# File 'lib/flipper/ui/action.rb', line 237 def view_without_layout(name) view name end |
#views_path ⇒ Object
Private
255 256 257 |
# File 'lib/flipper/ui/action.rb', line 255 def views_path self.class.views_path end |