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 =
JSON.parse(File.read(File.('sources.json', __dir__))).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'; connect-src https://www.flippercloud.io; 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
- #asset_hash(src) ⇒ Object
- #bootstrap_css ⇒ Object
- #bootstrap_js ⇒ Object
- #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.
-
#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? ⇒ Boolean
-
#redirect_to(location) ⇒ Object
Public: Redirect to a new location.
-
#render_read_only ⇒ Object
Internal: Method to call when the UI is in read only mode and you want to inform people of that fact.
-
#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.
-
#url_for(*parts) ⇒ Object
Internal: Generate urls relative to the app’s script name.
- #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.
- #write_allowed? ⇒ Boolean
Constructor Details
#initialize(flipper, request) ⇒ Action
Returns a new instance of Action.
91 92 93 94 95 96 |
# File 'lib/flipper/ui/action.rb', line 91 def initialize(flipper, request) @flipper = flipper @request = request @code = 200 @headers = {Rack::CONTENT_TYPE => 'text/plain'} end |
Instance Attribute Details
#flipper ⇒ Object (readonly)
Public: The instance of the Flipper::DSL the middleware was initialized with.
83 84 85 |
# File 'lib/flipper/ui/action.rb', line 83 def flipper @flipper end |
#request ⇒ Object (readonly)
Public: The Rack::Request to provide a response for.
86 87 88 |
# File 'lib/flipper/ui/action.rb', line 86 def request @request end |
Class Method Details
.public_path ⇒ Object
Private: The path to the public folder.
77 78 79 |
# File 'lib/flipper/ui/action.rb', line 77 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.
47 48 49 |
# File 'lib/flipper/ui/action.rb', line 47 def self.route(regex) @route_regex = regex end |
.route_match?(path) ⇒ Boolean
Internal: Does this action’s route match the path.
52 53 54 |
# File 'lib/flipper/ui/action.rb', line 52 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.
57 58 59 |
# File 'lib/flipper/ui/action.rb', line 57 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.
67 68 69 |
# File 'lib/flipper/ui/action.rb', line 67 def self.run(flipper, request) new(flipper, request).run end |
Instance Method Details
#asset_hash(src) ⇒ Object
282 283 284 285 286 287 288 |
# File 'lib/flipper/ui/action.rb', line 282 def asset_hash(src) v = ENV["RACK_ENV"] == "development" ? Time.now.to_i : Flipper::VERSION { src: "#{src}?v=#{v}", hash: SOURCES[src] } end |
#bootstrap_css ⇒ Object
270 271 272 |
# File 'lib/flipper/ui/action.rb', line 270 def bootstrap_css asset_hash "/css/bootstrap.min.css" end |
#bootstrap_js ⇒ Object
274 275 276 |
# File 'lib/flipper/ui/action.rb', line 274 def bootstrap_js asset_hash "/js/bootstrap.min.js" end |
#csrf_input_tag ⇒ Object
247 248 249 |
# File 'lib/flipper/ui/action.rb', line 247 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.
129 130 131 |
# File 'lib/flipper/ui/action.rb', line 129 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.
182 183 184 |
# File 'lib/flipper/ui/action.rb', line 182 def header(name, value) @headers[name] = value 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.
151 152 153 154 155 156 157 158 159 160 |
# File 'lib/flipper/ui/action.rb', line 151 def json_response(object) header Rack::CONTENT_TYPE, 'application/json' body = case object when String object else Typecast.to_json(object) end halt [@code, @headers, [body]] end |
#popper_js ⇒ Object
278 279 280 |
# File 'lib/flipper/ui/action.rb', line 278 def popper_js asset_hash "/js/popper.min.js" end |
#public_path ⇒ Object
Private
238 239 240 |
# File 'lib/flipper/ui/action.rb', line 238 def public_path self.class.public_path end |
#read_only? ⇒ Boolean
262 263 264 |
# File 'lib/flipper/ui/action.rb', line 262 def read_only? Flipper::UI.configuration.read_only || flipper.read_only? end |
#redirect_to(location) ⇒ Object
Public: Redirect to a new location.
location - The String location to set the Location header to.
165 166 167 168 169 |
# File 'lib/flipper/ui/action.rb', line 165 def redirect_to(location) status 302 header 'location', "#{script_name}#{Rack::Utils.escape_path(location)}" halt [@code, @headers, ['']] end |
#render_read_only ⇒ Object
Internal: Method to call when the UI is in read only mode and you want to inform people of that fact.
257 258 259 260 |
# File 'lib/flipper/ui/action.rb', line 257 def render_read_only status 403 halt view_response(:read_only) end |
#request_method_name ⇒ Object
Private: Returns the request method converted to an action method.
243 244 245 |
# File 'lib/flipper/ui/action.rb', line 243 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.
101 102 103 104 105 106 107 108 |
# File 'lib/flipper/ui/action.rb', line 101 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.
121 122 123 |
# File 'lib/flipper/ui/action.rb', line 121 def run_other_action(action_class) action_class.new(flipper, request).run end |
#script_name ⇒ Object
Internal: The path the app is mounted at.
218 219 220 |
# File 'lib/flipper/ui/action.rb', line 218 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.
174 175 176 |
# File 'lib/flipper/ui/action.rb', line 174 def status(code) @code = code.to_i end |
#url_for(*parts) ⇒ Object
Internal: Generate urls relative to the app’s script name.
url_for("feature") # => "http://localhost:9292/flipper/feature"
url_for("/thing") # => "http://localhost:9292/thing"
url_for("https://example.com") # => "https://example.com"
228 229 230 |
# File 'lib/flipper/ui/action.rb', line 228 def url_for(*parts) URI.join(request.base_url, script_name + '/', *parts).to_s end |
#valid_request_method? ⇒ Boolean
251 252 253 |
# File 'lib/flipper/ui/action.rb', line 251 def valid_request_method? VALID_REQUEST_METHOD_NAMES.include?(request_method_name) end |
#view(name) ⇒ Object
Private
210 211 212 213 214 215 |
# File 'lib/flipper/ui/action.rb', line 210 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.
138 139 140 141 142 143 |
# File 'lib/flipper/ui/action.rb', line 138 def view_response(name) header Rack::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
200 201 202 |
# File 'lib/flipper/ui/action.rb', line 200 def view_with_layout(&block) view :layout, &block end |
#view_without_layout(name) ⇒ Object
Private
205 206 207 |
# File 'lib/flipper/ui/action.rb', line 205 def view_without_layout(name) view name end |
#views_path ⇒ Object
Private
233 234 235 |
# File 'lib/flipper/ui/action.rb', line 233 def views_path self.class.views_path end |
#write_allowed? ⇒ Boolean
266 267 268 |
# File 'lib/flipper/ui/action.rb', line 266 def write_allowed? !read_only? end |