ballast 1.9.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +35 -0
- data/.travis-gemfile +4 -5
- data/.travis.yml +3 -2
- data/CHANGELOG.md +62 -6
- data/Gemfile +7 -8
- data/README.md +2 -2
- data/ballast.gemspec +9 -12
- data/doc/Ballast/AjaxResponse.html +1380 -0
- data/doc/Ballast/Concerns/AjaxHandling.html +662 -0
- data/doc/Ballast/Concerns/Common.html +81 -361
- data/doc/Ballast/Concerns/ErrorsHandling.html +18 -36
- data/doc/Ballast/Concerns/View.html +181 -157
- data/doc/Ballast/Concerns.html +6 -6
- data/doc/Ballast/Configuration.html +204 -31
- data/doc/Ballast/Emoji/Character.html +411 -0
- data/doc/Ballast/Emoji/Utils.html +794 -0
- data/doc/Ballast/Emoji.html +125 -0
- data/doc/Ballast/Errors/{BaseError.html → Base.html} +61 -34
- data/doc/Ballast/Errors/{PerformError.html → Failure.html} +21 -17
- data/doc/Ballast/Errors/InvalidDomain.html +11 -11
- data/doc/Ballast/Errors/{ValidationError.html → ValidationFailure.html} +24 -16
- data/doc/Ballast/Errors.html +5 -5
- data/doc/Ballast/Middlewares/DefaultHost.html +6 -6
- data/doc/Ballast/Middlewares.html +4 -4
- data/doc/Ballast/RequestDomainMatcher.html +28 -28
- data/doc/Ballast/Service/Response.html +1243 -0
- data/doc/Ballast/Service.html +1314 -0
- data/doc/Ballast/Version.html +7 -7
- data/doc/Ballast.html +15 -15
- data/doc/_index.html +59 -30
- data/doc/class_list.html +6 -2
- data/doc/css/style.css +1 -0
- data/doc/file.README.html +6 -6
- data/doc/file_list.html +5 -1
- data/doc/frames.html +1 -1
- data/doc/index.html +6 -6
- data/doc/js/full_list.js +4 -1
- data/doc/method_list.html +167 -79
- data/doc/top-level-namespace.html +41 -4
- data/lib/ballast/ajax_response.rb +76 -0
- data/lib/ballast/concerns/ajax_handling.rb +73 -0
- data/lib/ballast/concerns/common.rb +25 -47
- data/lib/ballast/concerns/errors_handling.rb +21 -30
- data/lib/ballast/concerns/view.rb +24 -22
- data/lib/ballast/configuration.rb +30 -10
- data/lib/ballast/emoji.rb +114 -0
- data/lib/ballast/errors.rb +16 -13
- data/lib/ballast/middlewares/default_host.rb +3 -3
- data/lib/ballast/request_domain_matcher.rb +7 -7
- data/lib/ballast/service.rb +147 -0
- data/lib/ballast/version.rb +3 -3
- data/lib/ballast.rb +22 -22
- data/spec/ballast/ajax_response_spec.rb +61 -0
- data/spec/ballast/concerns/ajax_handling_spec.rb +86 -0
- data/spec/ballast/concerns/common_spec.rb +17 -52
- data/spec/ballast/concerns/errors_handling_spec.rb +35 -29
- data/spec/ballast/concerns/view_spec.rb +21 -32
- data/spec/ballast/configuration_spec.rb +66 -16
- data/spec/ballast/emoji_spec.rb +103 -0
- data/spec/ballast/errors_spec.rb +5 -5
- data/spec/ballast/middlewares/default_host_spec.rb +3 -5
- data/spec/ballast/request_domain_matcher_spec.rb +4 -4
- data/spec/ballast/service_spec.rb +137 -0
- data/spec/spec_helper.rb +1 -13
- metadata +42 -80
- data/doc/Ballast/Concerns/Ajax.html +0 -945
- data/doc/Ballast/Context.html +0 -417
- data/doc/Ballast/Operation.html +0 -1304
- data/doc/Ballast/OperationsChain.html +0 -597
- data/lib/ballast/concerns/ajax.rb +0 -134
- data/lib/ballast/context.rb +0 -38
- data/lib/ballast/operation.rb +0 -136
- data/lib/ballast/operations_chain.rb +0 -45
- data/spec/ballast/concerns/ajax_spec.rb +0 -141
- data/spec/ballast/context_spec.rb +0 -23
- data/spec/ballast/operation_spec.rb +0 -177
- data/spec/ballast/operations_chain_spec.rb +0 -61
@@ -0,0 +1,73 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the ballast gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
3
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
4
|
+
#
|
5
|
+
|
6
|
+
module Ballast
|
7
|
+
# A set of concerns to address common issues.
|
8
|
+
module Concerns
|
9
|
+
# A concern to handle AJAX and HTTP requests.
|
10
|
+
module AjaxHandling
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
# Checks if the current request is AJAX.
|
14
|
+
#
|
15
|
+
# @return [Boolean] `true` if the request is AJAX, `false` otherwise.
|
16
|
+
def ajax_request?
|
17
|
+
request.safe_send(:xhr?).to_boolean || params[:xhr].to_boolean
|
18
|
+
end
|
19
|
+
|
20
|
+
# Prepares an AJAX response.
|
21
|
+
#
|
22
|
+
# @param status [Symbol|Fixnum] The HTTP status of the response.
|
23
|
+
# @param data [Object] The data of the response.
|
24
|
+
# @param error [Object|NilClass] The error of the response.
|
25
|
+
def prepare_ajax_response(status: :ok, data: {}, error: nil)
|
26
|
+
Ballast::AjaxResponse.new(status: status, data: data, error: error, transport: self)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Prevents HTTP caching.
|
30
|
+
def prevent_caching
|
31
|
+
response.headers.merge!({
|
32
|
+
"Cache-Control" => "no-cache, no-store, max-age=0, must-revalidate",
|
33
|
+
"Pragma" => "no-cache",
|
34
|
+
"Expires" => "Fri, 01 Jan 1990 00:00:00 GMT"
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
# Allows HTTP Cross-Origin Resource Sharing.
|
39
|
+
#
|
40
|
+
# @param allow_origin [String] The value for the `Access-Control-Allow-Origin` header.
|
41
|
+
# @param allow_methods [Array] A list of methods for the `Access-Control-Allow-Methods` header.
|
42
|
+
# @param allow_headers [String] The value for the `Access-Control-Allow-Headers` header.
|
43
|
+
# @param max_age [Float|Fixnum] The value for the `Access-Control-Max-Age` header.
|
44
|
+
# @param allow_credentials [Boolean] The value for the `Access-Control-Allow-Credentials` header.
|
45
|
+
def allow_cors(allow_origin: "*", allow_methods: [:post, :get, :options], allow_headers: "*", max_age: 1.year, allow_credentials: false)
|
46
|
+
headers.merge!({
|
47
|
+
"Access-Control-Allow-Origin" => allow_origin,
|
48
|
+
"Access-Control-Allow-Methods" => allow_methods.map { |m| m.to_s.upcase }.join(", "),
|
49
|
+
"Access-Control-Allow-Headers" => allow_headers,
|
50
|
+
"Access-Control-Max-Age" => max_age.to_i.to_s
|
51
|
+
})
|
52
|
+
|
53
|
+
headers["Access-Control-Allow-Credentials"] = "true" if allow_credentials
|
54
|
+
end
|
55
|
+
|
56
|
+
# Generates a `robots.txt file.
|
57
|
+
#
|
58
|
+
# @param configuration [Hash|NilClass] An hash of agent and list of paths to include.
|
59
|
+
def generate_robots_txt(configuration = nil)
|
60
|
+
configuration ||= {"*" => "/"}
|
61
|
+
rv = configuration.reduce([]) { |accu, (agent, paths)|
|
62
|
+
paths = paths.ensure_array.map { |e| "Disallow: #{e}" }
|
63
|
+
|
64
|
+
accu << "User-agent: #{agent}\n#{paths.join("\n")}"
|
65
|
+
accu
|
66
|
+
}.join("\n\n")
|
67
|
+
|
68
|
+
render(text: rv, content_type: "text/plain")
|
69
|
+
end
|
70
|
+
alias_method :disallow_robots, :generate_robots_txt
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -9,53 +9,32 @@ module Ballast
|
|
9
9
|
module Common
|
10
10
|
# Checks if the current request wants JSON or JSONP as response.
|
11
11
|
#
|
12
|
-
# @return [Boolean] `true` if the request is JSON, `false` otherwise.
|
13
|
-
def
|
14
|
-
|
12
|
+
# @return [Boolean] `true` if the request is JSON(P), `false` otherwise.
|
13
|
+
def json?
|
14
|
+
[:json, :jsonp].include?(request.format.to_sym) || params[:json].to_boolean
|
15
15
|
end
|
16
16
|
|
17
17
|
# Checks if the user is sending any data.
|
18
18
|
#
|
19
19
|
# @return [Boolean] `true` if the user is sending data, `false` otherwise.
|
20
|
-
def
|
21
|
-
request.post? || request.put?
|
22
|
-
end
|
23
|
-
|
24
|
-
# Performs an operation, using itself as owner by default.
|
25
|
-
#
|
26
|
-
# @param klass [Class] The operation to perform.
|
27
|
-
# @param owner [Object] The owner to use. By default it uses itself.
|
28
|
-
# @param kwargs [Hash] The arguments for performing.
|
29
|
-
# @return [Operation] The performed operation.
|
30
|
-
def perform_operation(klass, owner = nil, **kwargs)
|
31
|
-
@operation = klass.perform(owner || self, **kwargs)
|
32
|
-
end
|
33
|
-
|
34
|
-
# Performs an operations chain, using itself as owner by default.
|
35
|
-
#
|
36
|
-
# @param klasses [Array] The operations to perform.
|
37
|
-
# @param owner [Object] The owner to use. By default it uses itself.
|
38
|
-
# @param kwargs [Hash] The arguments for performing.
|
39
|
-
# @return [OperationChain] The performed operation chain.
|
40
|
-
def perform_operations_chain(klasses, owner = nil, **kwargs)
|
41
|
-
@operation = Ballast::OperationsChain.perform(owner || self, klasses, **kwargs)
|
20
|
+
def request_data?
|
21
|
+
request.post? || request.put? || request.patch?
|
42
22
|
end
|
43
23
|
|
44
24
|
# Formats a relative date using abbreviation or short formats.
|
45
25
|
#
|
46
26
|
# @param date [DateTime] The date to format.
|
47
|
-
# @param reference [DateTime] The reference date.
|
27
|
+
# @param reference [DateTime|NilClass] The reference date.
|
48
28
|
# @param suffix [String] The suffix to add to the formatted date.
|
49
29
|
# @return [String] The formatted date.
|
50
|
-
def format_short_duration(date, reference
|
51
|
-
reference
|
52
|
-
amount = (reference.to_i - date.to_i).to_i
|
30
|
+
def format_short_duration(date, reference: nil, suffix: "")
|
31
|
+
amount = (reference || Time.now).to_i - date.to_i
|
53
32
|
|
54
|
-
if amount <= 0
|
33
|
+
if amount <= 0
|
55
34
|
"now"
|
56
|
-
elsif amount < 1.day
|
35
|
+
elsif amount < 1.day
|
57
36
|
format_short_amount(amount, suffix)
|
58
|
-
elsif amount < 1.year
|
37
|
+
elsif amount < 1.year
|
59
38
|
date.strftime("%b %d")
|
60
39
|
else
|
61
40
|
date.strftime("%b %d %Y")
|
@@ -68,9 +47,9 @@ module Ballast
|
|
68
47
|
# @param suffix [String] The suffix to add to the formatted amount.
|
69
48
|
# @return [String] The formatted amount.
|
70
49
|
def format_short_amount(amount, suffix = "")
|
71
|
-
if amount < 1.minute
|
50
|
+
if amount < 1.minute
|
72
51
|
"#{amount.floor}s#{suffix}"
|
73
|
-
elsif amount < 1.hour
|
52
|
+
elsif amount < 1.hour
|
74
53
|
"#{(amount / 60).floor}m#{suffix}"
|
75
54
|
else
|
76
55
|
"#{(amount / 3600).floor}h#{suffix}"
|
@@ -83,29 +62,28 @@ module Ballast
|
|
83
62
|
# @param separator [String] The separator between date and time.
|
84
63
|
# @param format [String] The format of the date, like in strftime. Use `%-` for the separator, `%o` for the ordinalized version of the day of the month
|
85
64
|
# and `%:Z` for the zone name considering also DST.
|
86
|
-
def format_long_date(date, separator
|
65
|
+
def format_long_date(date, separator: "•", format: "%I:%M%p %- %b %o, %Y (%:Z)")
|
87
66
|
tz = Time.zone
|
88
|
-
replacements = {"%-" => separator, "%o" => date.day.ordinalize, "%:Z" => tz.
|
89
|
-
date.strftime(format).gsub(/%(-|o|(:Z))/) {|r| replacements.fetch(r, r) }
|
67
|
+
replacements = {"%-" => separator, "%o" => date.day.ordinalize, "%:Z" => tz.current_name(tz.uses_dst? && date.dst?)}
|
68
|
+
date.strftime(format).gsub(/%(-|o|(:Z))/) { |r| replacements.fetch(r, r) }
|
90
69
|
end
|
91
70
|
|
92
71
|
# Authenticates a user via HTTP, handling the error if the authentication failed.
|
93
72
|
#
|
94
|
-
# @param area [String] The name of the area.
|
95
|
-
# @param title [String] A title for authentication errors.
|
96
|
-
# @param message [String] A message for authentication errors.
|
73
|
+
# @param area [String|NilClass] The name of the area.
|
74
|
+
# @param title [String|NilClass] A title for authentication errors.
|
75
|
+
# @param message [String|NilClass] A message for authentication errors.
|
97
76
|
# @param authenticator [Proc] A block to verify if authentication is valid.
|
98
|
-
def authenticate_user(area
|
77
|
+
def authenticate_user(area: nil, title: nil, message: nil, &authenticator)
|
78
|
+
return if authenticate_with_http_basic { |username, password| authenticator.call(username, password) }
|
79
|
+
|
99
80
|
area ||= "Private Area"
|
100
81
|
title ||= "Authentication required."
|
101
82
|
message ||= "To view this resource you have to authenticate."
|
102
|
-
authenticated = authenticate_with_http_basic { |username, password| authenticator.call(username, password) }
|
103
83
|
|
104
|
-
|
105
|
-
|
106
|
-
handle_error({status: 401, title: title, message: message})
|
107
|
-
end
|
84
|
+
headers["WWW-Authenticate"] = "Basic realm=\"#{area}\""
|
85
|
+
handle_error({status: 401, title: title, message: message})
|
108
86
|
end
|
109
87
|
end
|
110
88
|
end
|
111
|
-
end
|
89
|
+
end
|
@@ -12,44 +12,35 @@ module Ballast
|
|
12
12
|
# Handles an error in the application.
|
13
13
|
#
|
14
14
|
# @param exception [Hash|Exception] The exception to handle.
|
15
|
-
# @param layout [String] The layout to use to render the error.
|
15
|
+
# @param layout [String] The layout to use to render the error. The `@error` variable will be exposed.
|
16
16
|
# @param title [String] The title to set in case of custom errors.
|
17
|
-
# @param format [String|Symbol] The format of the response.
|
18
|
-
def handle_error(exception
|
19
|
-
@error
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@error_message = @error[:error]
|
28
|
-
else
|
29
|
-
@error_title = "Error - #{@error.class.to_s}"
|
30
|
-
@error_code = 500
|
31
|
-
end
|
17
|
+
# @param format [String|Symbol|NilClass] The format of the response.
|
18
|
+
def handle_error(exception, layout: "error", title: "Error - Application", format: nil)
|
19
|
+
@error =
|
20
|
+
if exception.is_a?(Lazier::Exceptions::Debug)
|
21
|
+
{status: 503, title: "Debug", error: exception.message, exception: exception}
|
22
|
+
elsif exception.is_a?(::Hash)
|
23
|
+
exception.reverse_merge({title: title})
|
24
|
+
else
|
25
|
+
{status: 500, title: "Error - #{exception.class}", error: exception.message, exception: exception}
|
26
|
+
end
|
32
27
|
|
33
28
|
send_or_render_error(layout, format)
|
34
29
|
end
|
35
30
|
|
36
31
|
private
|
37
|
-
# Send an AJAX error o renders it.
|
38
|
-
#
|
39
|
-
# @param layout [String] The layout to use to render the error.
|
40
|
-
# @param format [String|Symbol] The format of the response.
|
41
|
-
def send_or_render_error(layout, format = nil)
|
42
|
-
format ||= request.format.to_sym
|
43
32
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
33
|
+
# :nodoc:
|
34
|
+
def send_or_render_error(layout, format = nil)
|
35
|
+
format ||= request.format.to_sym
|
36
|
+
|
37
|
+
if ajax_request? || format.match(/^json/)
|
38
|
+
details = {description: @error[:title], backtrace: @error[:exception].safe_send(:backtrace)}
|
39
|
+
prepare_ajax_response(status: @error[:status], data: details, error: @error[:error]).reply(format: format)
|
40
|
+
else
|
41
|
+
render(html: "", status: @error[:status], layout: layout, formats: [:html])
|
52
42
|
end
|
43
|
+
end
|
53
44
|
end
|
54
45
|
end
|
55
46
|
end
|
@@ -11,30 +11,30 @@ module Ballast
|
|
11
11
|
#
|
12
12
|
# @return [String] The scoped string.
|
13
13
|
def scope_css
|
14
|
-
"%s %s"
|
14
|
+
format("%s %s", controller_path.gsub("/", "-"), action_name)
|
15
15
|
end
|
16
16
|
|
17
17
|
# Returns an instance of the browser.
|
18
18
|
#
|
19
19
|
# @return [Browser] A browser object.
|
20
20
|
def browser
|
21
|
-
@browser ||= Brauser::Browser.new(request.user_agent)
|
21
|
+
@browser ||= Brauser::Browser.new(request.user_agent, request.headers["Accept-Language"])
|
22
22
|
end
|
23
23
|
|
24
24
|
# Checks if the current browser is supported according to a definition YAML file.
|
25
25
|
#
|
26
|
-
# @param
|
26
|
+
# @param file [String] The configuration file which holds the definitions.
|
27
|
+
# @param root [String|NilClass] The directory that contains the configuration file.
|
27
28
|
# @return [Boolean] `true` if the browser is supported, `false` otherwise.
|
28
|
-
def browser_supported?(
|
29
|
-
|
30
|
-
browser.supported?(conf_file)
|
29
|
+
def browser_supported?(file = "config/supported-browsers.yml", root: nil)
|
30
|
+
browser.supported?(((Ballast::Configuration.default_root || root) + "/" + file).to_s)
|
31
31
|
end
|
32
32
|
|
33
33
|
# Returns one or all layout parameters.
|
34
34
|
#
|
35
35
|
# @param key [String|Symbol|NilClass] The parameter to return. If set to `nil`, all the parameters will be returned as an hash.
|
36
|
-
# @param default_value [Object] The default value if the parameter is not present.
|
37
|
-
# @return [Object|Hash] The parameter or the entire layout parameters hash.
|
36
|
+
# @param default_value [Object|NilClass] The default value if the parameter is not present.
|
37
|
+
# @return [Object|Hash|NilClass] The parameter or the entire layout parameters hash.
|
38
38
|
def layout_params(key = nil, default_value = nil)
|
39
39
|
initialize_view_params
|
40
40
|
key ? @layout_params.fetch(key, default_value) : @layout_params
|
@@ -43,8 +43,8 @@ module Ballast
|
|
43
43
|
|
44
44
|
# Adds/Replaces layout parameters.
|
45
45
|
#
|
46
|
-
# @param args [Hash] The
|
47
|
-
def
|
46
|
+
# @param args [Hash] The parameters to add or replace.
|
47
|
+
def update_layout_params(**args)
|
48
48
|
initialize_view_params
|
49
49
|
@layout_params.merge!(args)
|
50
50
|
end
|
@@ -53,18 +53,19 @@ module Ballast
|
|
53
53
|
#
|
54
54
|
# @param id [String|NilClass|FalseClass] The id for the tag. If `nil` or `false`, the parameters will be returned as an hash.
|
55
55
|
# @param tag [Symbol] The tag to use for HTML.
|
56
|
-
# @
|
57
|
-
|
56
|
+
# @param attribute [Symbol] The attribute to use for the HTML element id.
|
57
|
+
# @return [String|Hash] Javascript parameters as HTML or as an hash.
|
58
|
+
def javascript_params(id = nil, tag: :details, attribute: "data-jid")
|
58
59
|
initialize_view_params
|
59
|
-
id ? content_tag(tag, @javascript_params.to_json.html_safe,
|
60
|
+
id ? content_tag(tag, @javascript_params.to_json.html_safe, attribute => id) : @javascript_params
|
60
61
|
end
|
61
62
|
|
62
|
-
#
|
63
|
+
# Adds/Replaces Javascript parameters.
|
63
64
|
#
|
64
65
|
# @param key [String|Symbol] The key of the new parameters. If `nil`, the root will be merged/replaced.
|
65
|
-
# @param data [Hash] The data to add.
|
66
|
+
# @param data [Hash] The data to add or replace.
|
66
67
|
# @param replace [Boolean] Whether to replace existing data rather than merge.
|
67
|
-
def
|
68
|
+
def update_javascript_params(key, data, replace: false)
|
68
69
|
initialize_view_params
|
69
70
|
|
70
71
|
if key
|
@@ -79,11 +80,12 @@ module Ballast
|
|
79
80
|
end
|
80
81
|
|
81
82
|
private
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
|
84
|
+
# :nodoc:
|
85
|
+
def initialize_view_params
|
86
|
+
@layout_params ||= HashWithIndifferentAccess.new
|
87
|
+
@javascript_params ||= HashWithIndifferentAccess.new
|
88
|
+
end
|
87
89
|
end
|
88
90
|
end
|
89
|
-
end
|
91
|
+
end
|
@@ -7,24 +7,44 @@ module Ballast
|
|
7
7
|
# A class which loads a list of YAML files in a folder and expose them in a dotted notation.
|
8
8
|
# For each file, only the subsection for the current environment is loaded, so each YAML document should be an hash.
|
9
9
|
class Configuration < HashWithIndifferentAccess
|
10
|
+
# Returns the default root directory to lookup a configuration. It will be the Rails root if set or the current folder.
|
11
|
+
#
|
12
|
+
# @return [String] The default root directory to lookup a configuration.
|
13
|
+
def self.default_root
|
14
|
+
defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the default environment. It will be the first non-nil of the following: Rails environment, the Rack environment or "production".
|
18
|
+
#
|
19
|
+
# @return [String] The default environment.
|
20
|
+
def self.default_environment
|
21
|
+
defined?(Rails) ? Rails.env : ENV.fetch("RACK_ENV", "production")
|
22
|
+
end
|
23
|
+
|
10
24
|
# Creates a new configuration.
|
11
25
|
#
|
12
26
|
# @param sections [Array] A list of sections to load. Each section name should be the basename (without extension) of a file in the root folder.
|
13
27
|
# Subfolders are not supported.
|
14
|
-
# @param root [String] The root folder where look for file.
|
15
|
-
# @param environment [String] The environment to load.
|
16
|
-
def initialize(sections
|
28
|
+
# @param root [String|NilClass] The root folder where look for file.
|
29
|
+
# @param environment [String|NilClass] The environment to load.
|
30
|
+
def initialize(*sections, root: nil, environment: nil)
|
17
31
|
super()
|
18
|
-
root ||=
|
19
|
-
environment ||=
|
32
|
+
root ||= ::Ballast::Configuration.default_root
|
33
|
+
environment ||= ::Ballast::Configuration.default_environment
|
20
34
|
|
21
35
|
sections.each do |section|
|
22
|
-
content = (
|
23
|
-
self[section] = content
|
24
|
-
self[section.underscore] = self[section] if section.index("-")
|
36
|
+
content = load_section(root, section)
|
37
|
+
self[section.underscore] = content.fetch(environment, {})
|
25
38
|
end
|
26
39
|
|
27
|
-
|
40
|
+
enable_dotted_access
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# :nodoc:
|
46
|
+
def load_section(root, section)
|
47
|
+
YAML.load_file("#{root}/config/#{section}.yml") rescue {}
|
28
48
|
end
|
29
49
|
end
|
30
|
-
end
|
50
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the ballast gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
3
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
4
|
+
#
|
5
|
+
|
6
|
+
module Ballast
|
7
|
+
# A module to ease emoji handling.
|
8
|
+
module Emoji
|
9
|
+
# General utility methods.
|
10
|
+
#
|
11
|
+
# @attribute url_mapper
|
12
|
+
# @return [Proc] The current URL mapper or a default one (which will return the relative URL unmodified).
|
13
|
+
module Utils
|
14
|
+
attr_accessor :url_mapper
|
15
|
+
|
16
|
+
# Returns the regular expression which matches all the known emojis.
|
17
|
+
#
|
18
|
+
# @return [Regexp] The regular expression which matches all the known emojis.
|
19
|
+
def replace_regex
|
20
|
+
@replace_regex ||= /(#{::Emoji.send(:unicodes_index).keys.join("|")})/
|
21
|
+
end
|
22
|
+
|
23
|
+
# Replaces all the emojis in the text using the requested mod.
|
24
|
+
#
|
25
|
+
# @param text [String] The text to manipulate.
|
26
|
+
# @param mode [Symbol] The method to use when replacing icons.
|
27
|
+
# @param options [Hash] The options to pass to the replacing method.
|
28
|
+
# @return [String] The text with all emojis replaced.
|
29
|
+
def replace(text, mode: :html, **options)
|
30
|
+
mode = :markup unless mode && ::Emoji::Character.new(nil).respond_to?(mode)
|
31
|
+
text.ensure_string.gsub(replace_regex) { invoke(::Emoji.find_by_unicode(Regexp.last_match[1]), mode, options) }
|
32
|
+
end
|
33
|
+
|
34
|
+
# Lists all the emoji known in a hash.
|
35
|
+
#
|
36
|
+
# @param keys_method [Symbol] The method to use for keys.
|
37
|
+
# @param values_method [Symbol] The method to use for values.
|
38
|
+
# @param options [Hash] The options to pass to all methods.
|
39
|
+
# @return [Hash] A hash of all known emojis.
|
40
|
+
def enumerate(keys_method: :markup, values_method: :html, **options)
|
41
|
+
tester = ::Emoji::Character.new(nil)
|
42
|
+
keys_method = :markup unless keys_method && tester.respond_to?(keys_method)
|
43
|
+
values_method = :html unless values_method && tester.respond_to?(values_method)
|
44
|
+
|
45
|
+
::Emoji.all.reduce({}) { |accu, icon|
|
46
|
+
accu[invoke(icon, keys_method, options)] = invoke(icon, values_method, options)
|
47
|
+
accu
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the URL mapper for the emojis.
|
52
|
+
#
|
53
|
+
# @return [Proc] The current URL mapper or a default one (which will return the relative URL unmodified).
|
54
|
+
def url_mapper
|
55
|
+
@url_mapper || ->(url) { url }
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns a absolute URL for a emoji image.
|
59
|
+
#
|
60
|
+
# @param image [String] The relative URL of the emoji filename.
|
61
|
+
# @return [String] The absolute URL of the emoji filename.
|
62
|
+
def url_for(image)
|
63
|
+
url_mapper.call(image)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# :nodoc:
|
69
|
+
def invoke(subject, method, options)
|
70
|
+
subject.method(method).arity == 1 ? subject.send(method, options) : subject.send(method)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Extensions for a emoji character.
|
75
|
+
module Character
|
76
|
+
include ActionView::Helpers::TagHelper
|
77
|
+
include ActiveSupport::Concern
|
78
|
+
|
79
|
+
# Returns a markup for the current character.
|
80
|
+
#
|
81
|
+
# @return [String] The markup for a character.
|
82
|
+
def markup
|
83
|
+
":#{name}:"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns a image URL for the current character.
|
87
|
+
#
|
88
|
+
# @return [String] The image URL for the current character.
|
89
|
+
def url
|
90
|
+
::Emoji.url_for(image_filename)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a image tag for the current character.
|
94
|
+
# @see ActionView::Helpers::TagHelper#tag
|
95
|
+
#
|
96
|
+
# @return [String] The options for the tag generation.
|
97
|
+
def image_tag(options = {})
|
98
|
+
options = options.reverse_merge({alt: markup, title: markup, rel: "tooltip"})
|
99
|
+
classes = options[:class].ensure_string.tokenize(pattern: /[\s,]+/, no_duplicates: true)
|
100
|
+
classes << "emoji" unless classes.include?("emoji")
|
101
|
+
|
102
|
+
options[:src] = url
|
103
|
+
options[:class] = classes.uniq.join(" ")
|
104
|
+
|
105
|
+
tag(:img, options)
|
106
|
+
end
|
107
|
+
alias_method :image, :url
|
108
|
+
alias_method :html, :image_tag
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
::Emoji.extend(Ballast::Emoji::Utils)
|
114
|
+
::Emoji::Character.include(Ballast::Emoji::Character)
|
data/lib/ballast/errors.rb
CHANGED
@@ -8,27 +8,30 @@ module Ballast
|
|
8
8
|
module Errors
|
9
9
|
# The base error raised from an application.
|
10
10
|
#
|
11
|
-
# @attribute [r]
|
12
|
-
# @return [String|Hash] The
|
13
|
-
class
|
14
|
-
attr_reader :
|
11
|
+
# @attribute [r] details
|
12
|
+
# @return [String|Hash|NilClass] The details of the error. If a Hash, it should contain the keys `status` and `error`.
|
13
|
+
class Base < RuntimeError
|
14
|
+
attr_reader :details
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
# Creates a new error.
|
17
|
+
#
|
18
|
+
# @param details [String|Hash|NilClass] The details of this error.
|
19
|
+
def initialize(details = nil)
|
20
|
+
super("")
|
21
|
+
@details = details
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
22
25
|
# This is raised when an invalid domain is requested.
|
23
|
-
class InvalidDomain <
|
26
|
+
class InvalidDomain < Base
|
24
27
|
end
|
25
28
|
|
26
|
-
# This is raised when something went wrong during the processing of a operation.
|
27
|
-
class
|
29
|
+
# This is raised when something went wrong during the processing of a operation or a service.
|
30
|
+
class Failure < Base
|
28
31
|
end
|
29
32
|
|
30
|
-
# This is raised when some invalid parameters are passed to a operation.
|
31
|
-
class
|
33
|
+
# This is raised when some invalid parameters are passed to a operation or a service.
|
34
|
+
class ValidationFailure < Failure
|
32
35
|
end
|
33
36
|
end
|
34
|
-
end
|
37
|
+
end
|
@@ -22,9 +22,9 @@ module Ballast
|
|
22
22
|
# @param env [Hash] A Rack environment.
|
23
23
|
def call(env)
|
24
24
|
old_host = env["SERVER_NAME"].ensure_string
|
25
|
-
new_host = @hosts[ENV
|
25
|
+
new_host = @hosts[ENV.fetch("RACK_ENV", "production")]
|
26
26
|
|
27
|
-
if old_host =~ /^\d/ && new_host
|
27
|
+
if old_host =~ /^\d/ && new_host
|
28
28
|
env["ORIG_SERVER_NAME"] = old_host
|
29
29
|
env["ORIG_HTTP_HOST"] = env["HTTP_HOST"].dup
|
30
30
|
env["SERVER_NAME"] = new_host
|
@@ -35,4 +35,4 @@ module Ballast
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
-
end
|
38
|
+
end
|
@@ -9,20 +9,20 @@ module Ballast
|
|
9
9
|
# @attribute domains
|
10
10
|
# @return [Array] The list of domains which mark a positive match.
|
11
11
|
# @attribute replace_pattern
|
12
|
-
# @return [String|Regexp] A optional pattern to
|
12
|
+
# @return [String|Regexp] A optional pattern to manipulate the request host before trying the match. See `String#gsub`.
|
13
13
|
# @attribute replace_string
|
14
|
-
# @return [String] A string to
|
14
|
+
# @return [String] A string to manipulate the request host before trying the match. See `String#gsub`.
|
15
15
|
# @attribute replace_block
|
16
|
-
# @return [Proc] A block to use
|
16
|
+
# @return [Proc] A block to use to manipulate the request host before trying the match. See `String#gsub`.
|
17
17
|
class RequestDomainMatcher
|
18
18
|
attr_accessor :domains, :replace_pattern, :replace_string, :replace_block
|
19
19
|
|
20
20
|
# Creates a new matcher.
|
21
21
|
#
|
22
22
|
# @param domains [String|Array] The list of domains which mark a positive match.
|
23
|
-
# @param replace_pattern [String|Regexp] A optional pattern to
|
24
|
-
# @param replace_string [String] A string to
|
25
|
-
# @param replace_block [Proc] A block to use
|
23
|
+
# @param replace_pattern [String|Regexp] A optional pattern to manipulate the request host before trying the match. See `String#gsub`.
|
24
|
+
# @param replace_string [String] A string to manipulate the request host before trying the match. See `String#gsub`.
|
25
|
+
# @param replace_block [Proc] A block to use to manipulate the request host before trying the match. See `String#gsub`.
|
26
26
|
def initialize(domains, replace_pattern = /\.dev$/, replace_string = "", &replace_block)
|
27
27
|
@domains = domains.ensure_array
|
28
28
|
@replace_pattern = replace_pattern
|
@@ -39,4 +39,4 @@ module Ballast
|
|
39
39
|
@domains.include?(final_host)
|
40
40
|
end
|
41
41
|
end
|
42
|
-
end
|
42
|
+
end
|