ballast 1.9.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|