aerogel-core 1.3.0 → 1.4.10
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/aerogel-core.gemspec +8 -2
- data/app/helpers/assets.rb +22 -8
- data/app/helpers/core.rb +82 -0
- data/app/helpers/i18n.rb +11 -0
- data/app/helpers/icon.rb +12 -0
- data/app/helpers/render.rb +89 -17
- data/app/helpers/tags.rb +18 -3
- data/app/routes/aerogel.rb +30 -0
- data/app/routes/core.rb +16 -1
- data/app/routes/i18n.rb +14 -0
- data/config/application.conf +8 -0
- data/config/development/aerogel.conf +9 -0
- data/config/production/aerogel.conf +10 -0
- data/lib/aerogel/core/application.rb +3 -0
- data/lib/aerogel/core/assets.rb +24 -0
- data/lib/aerogel/core/cache.rb +72 -0
- data/lib/aerogel/core/config.rb +10 -2
- data/lib/aerogel/core/core.rb +55 -10
- data/lib/aerogel/core/core_ext/array.rb +38 -0
- data/lib/aerogel/core/core_ext/hash.rb +48 -0
- data/lib/aerogel/core/db.rb +28 -8
- data/lib/aerogel/core/db/model.rb +52 -4
- data/lib/aerogel/core/errors.rb +23 -1
- data/lib/aerogel/core/helpers.rb +1 -1
- data/lib/aerogel/core/i18n.rb +134 -0
- data/lib/aerogel/core/i18n/number_helper.rb +126 -0
- data/lib/aerogel/core/reloader.rb +49 -5
- data/lib/aerogel/core/routes.rb +5 -3
- data/lib/aerogel/core/routes/namespace.rb +1 -1
- data/lib/aerogel/core/version.rb +3 -1
- data/locales/core/en.yml +17 -0
- data/locales/core/ru.yml +17 -0
- data/locales/db/en.yml +25 -0
- data/locales/db/ru.yml +24 -0
- data/locales/i18n-defaults/en.yml +211 -0
- data/locales/i18n-defaults/ru.yml +257 -0
- data/rake/console.rake +8 -0
- data/views/layouts/application.html.erb +1 -1
- data/views/lorem.html.erb +48 -0
- metadata +91 -3
- data/app/routes/static.rb +0 -7
data/lib/aerogel/core/errors.rb
CHANGED
@@ -1,10 +1,32 @@
|
|
1
1
|
module Aerogel
|
2
2
|
module Errors
|
3
3
|
|
4
|
-
|
4
|
+
module Translated
|
5
|
+
def initialize( *args )
|
6
|
+
@translation_key = nil
|
7
|
+
if args.first.is_a? Symbol
|
8
|
+
@translation_key = args.shift
|
9
|
+
end
|
10
|
+
super( *args )
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
if @translation_key
|
15
|
+
Aerogel::I18n.t @translation_key, scope: 'errors.messages'
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end # module Translated
|
5
21
|
|
22
|
+
class NotFoundError < StandardError
|
23
|
+
include Translated
|
6
24
|
end # class NotFoundError
|
7
25
|
|
26
|
+
class InvalidOperationError < StandardError
|
27
|
+
include Translated
|
28
|
+
end # class InvalidOperationError
|
29
|
+
|
8
30
|
end # module Errors
|
9
31
|
end # module Aerogel
|
10
32
|
|
data/lib/aerogel/core/helpers.rb
CHANGED
@@ -19,7 +19,7 @@ private
|
|
19
19
|
# Sets up reloader for helpers.
|
20
20
|
#
|
21
21
|
def self.setup_reloader(app)
|
22
|
-
app.use Aerogel::Reloader, ->{ Aerogel.get_resource_list( :app, "helpers/**/*.rb" ) } do |files|
|
22
|
+
app.use Aerogel::Reloader, ->{ Aerogel.get_resource_list( :app, "helpers/**/*.rb" ) }, group: :helpers do |files|
|
23
23
|
files.each do |filename|
|
24
24
|
Aerogel.require_into( Aerogel::Helpers, filename )
|
25
25
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
require 'aerogel/core/i18n/number_helper'
|
3
|
+
|
4
|
+
# Aerogel::I18n provides localization support for aerogel applications.
|
5
|
+
#
|
6
|
+
module Aerogel::I18n
|
7
|
+
|
8
|
+
def self.registered(app)
|
9
|
+
# load locales
|
10
|
+
reload!
|
11
|
+
|
12
|
+
# register reloader
|
13
|
+
setup_reloader(app) if Aerogel.config.aerogel.reloader?
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# Translation helper with chainable key access support.
|
18
|
+
# You can call #t using standard i18n way:
|
19
|
+
#
|
20
|
+
# t 'aerogel.admin.welcome', username: 'John'
|
21
|
+
#
|
22
|
+
# Or using aerogel syntactic sugar:
|
23
|
+
#
|
24
|
+
# t.aerogel.admin.welcome username: 'John'
|
25
|
+
#
|
26
|
+
def self.t( *args )
|
27
|
+
if args.size > 0
|
28
|
+
# puts "** I18n.t original t: #{args}"
|
29
|
+
::I18n.t( *args )
|
30
|
+
else
|
31
|
+
# puts "** I18n.t chainable t: #{args}"
|
32
|
+
Chainable.new( *args )
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.l( *args )
|
37
|
+
if args.first.nil? && args.second.is_a?( Hash ) && args.second.key?(:default)
|
38
|
+
default_value = args.second[:default]
|
39
|
+
if default_value.is_a? Symbol
|
40
|
+
::I18n.t default_value
|
41
|
+
else
|
42
|
+
default_value
|
43
|
+
end
|
44
|
+
else
|
45
|
+
::I18n.l( *args )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.locale( *args )
|
50
|
+
::I18n.locale( *args )
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.locale=( *args )
|
54
|
+
::I18n.send :'locale=', *args
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.default_locale
|
58
|
+
::I18n.default_locale
|
59
|
+
end
|
60
|
+
def self.available_locales
|
61
|
+
::I18n.available_locales
|
62
|
+
end
|
63
|
+
|
64
|
+
# Human file size helper.
|
65
|
+
#
|
66
|
+
extend NumberHelper
|
67
|
+
#def self.number_to_human_size( *args )
|
68
|
+
# ActiveSupport::NumberHelper.number_to_human_size( *args )
|
69
|
+
#end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Sets up reloader for locales.
|
74
|
+
#
|
75
|
+
def self.setup_reloader(app)
|
76
|
+
app.use Aerogel::Reloader, ->{ get_locale_files } do |files|
|
77
|
+
reload! files
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns list of locale translation files.
|
82
|
+
#
|
83
|
+
def self.get_locale_files
|
84
|
+
Aerogel.get_resource_list( :locales, "**/*.yml" )
|
85
|
+
end
|
86
|
+
|
87
|
+
# Reload locales.
|
88
|
+
#
|
89
|
+
def self.reload!( files = nil )
|
90
|
+
::I18n.load_path = files || get_locale_files
|
91
|
+
::I18n.reload!
|
92
|
+
::I18n.available_locales = Aerogel.config.locales.enabled! if Aerogel.config.locales.enabled?
|
93
|
+
if Aerogel.config.locales.default?
|
94
|
+
::I18n.default_locale = Aerogel.config.locales.default!
|
95
|
+
else
|
96
|
+
::I18n.default_locale = ::I18n.available_locales.first
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Chainable #t helper support class.
|
102
|
+
# Example:
|
103
|
+
# t.aerogel.admin.welcome # => t 'aerogel.admin.welcome'
|
104
|
+
# t.aerogel.admin.welcome username: 'John' # => t 'aerogel.admin.welcome', username: 'John'
|
105
|
+
#
|
106
|
+
class Chainable
|
107
|
+
def initialize( *args )
|
108
|
+
@path = []
|
109
|
+
call( *args ) if args.size > 0
|
110
|
+
end
|
111
|
+
|
112
|
+
def method_missing( name, *args )
|
113
|
+
@path << name.to_sym
|
114
|
+
if args.size > 0
|
115
|
+
call( *args )
|
116
|
+
else
|
117
|
+
self
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def call( *args )
|
122
|
+
::I18n.t translation_key, *args
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_s()
|
126
|
+
::I18n.t translation_key
|
127
|
+
end
|
128
|
+
|
129
|
+
def translation_key
|
130
|
+
@path.join(".")
|
131
|
+
end
|
132
|
+
end # class Chainable
|
133
|
+
|
134
|
+
end # module Aerogel::I18n
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Aerogel::I18n
|
2
|
+
module NumberHelper
|
3
|
+
|
4
|
+
def number_with_delimiter(number, options = {})
|
5
|
+
options.symbolize_keys!
|
6
|
+
|
7
|
+
options[:delimiter] = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter]
|
8
|
+
options[:separator] = ERB::Util.html_escape(options[:separator]) if options[:separator]
|
9
|
+
|
10
|
+
begin
|
11
|
+
Float(number)
|
12
|
+
rescue ArgumentError, TypeError
|
13
|
+
if options[:raise]
|
14
|
+
raise # InvalidNumberError, number
|
15
|
+
else
|
16
|
+
return number
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
defaults = ::I18n.translate(:'number.format', :locale => options[:locale], :default => {})
|
21
|
+
options = options.reverse_merge(defaults)
|
22
|
+
|
23
|
+
parts = number.to_s.to_str.split('.')
|
24
|
+
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
|
25
|
+
parts.join(options[:separator]).html_safe
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
DECIMAL_UNITS = {0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
|
30
|
+
-1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto}
|
31
|
+
|
32
|
+
def number_with_precision(number, options = {})
|
33
|
+
options.symbolize_keys!
|
34
|
+
|
35
|
+
number = begin
|
36
|
+
Float(number)
|
37
|
+
rescue ArgumentError, TypeError
|
38
|
+
if options[:raise]
|
39
|
+
raise # InvalidNumberError, number
|
40
|
+
else
|
41
|
+
return number
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
defaults = ::I18n.translate(:'number.format', :locale => options[:locale], :default => {})
|
46
|
+
precision_defaults = ::I18n.translate(:'number.precision.format', :locale => options[:locale], :default => {})
|
47
|
+
defaults = defaults.merge(precision_defaults)
|
48
|
+
|
49
|
+
options = options.reverse_merge(defaults) # Allow the user to unset default values: Eg.: :significant => false
|
50
|
+
precision = options.delete :precision
|
51
|
+
significant = options.delete :significant
|
52
|
+
strip_insignificant_zeros = options.delete :strip_insignificant_zeros
|
53
|
+
|
54
|
+
if significant and precision > 0
|
55
|
+
if number == 0
|
56
|
+
digits, rounded_number = 1, 0
|
57
|
+
else
|
58
|
+
digits = (Math.log10(number.abs) + 1).floor
|
59
|
+
rounded_number = (BigDecimal.new(number.to_s) / BigDecimal.new((10 ** (digits - precision)).to_f.to_s)).round.to_f * 10 ** (digits - precision)
|
60
|
+
digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
|
61
|
+
end
|
62
|
+
precision -= digits
|
63
|
+
precision = precision > 0 ? precision : 0 #don't let it be negative
|
64
|
+
else
|
65
|
+
rounded_number = BigDecimal.new(number.to_s).round(precision).to_f
|
66
|
+
end
|
67
|
+
formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options)
|
68
|
+
if strip_insignificant_zeros
|
69
|
+
escaped_separator = Regexp.escape(options[:separator])
|
70
|
+
formatted_number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '').html_safe
|
71
|
+
else
|
72
|
+
formatted_number
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb]
|
78
|
+
|
79
|
+
# TODO: use NumberHelper from 'activesupport ~> 4.0',
|
80
|
+
# at the moment it is incompatible with mongoid,
|
81
|
+
#
|
82
|
+
#
|
83
|
+
def number_to_human_size(number, options = {})
|
84
|
+
options.symbolize_keys!
|
85
|
+
|
86
|
+
number = begin
|
87
|
+
Float(number)
|
88
|
+
rescue ArgumentError, TypeError
|
89
|
+
if options[:raise]
|
90
|
+
raise # InvalidNumberError, number
|
91
|
+
else
|
92
|
+
return number
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
defaults = ::I18n.translate(:'number.format', :locale => options[:locale], :default => {})
|
97
|
+
human = ::I18n.translate(:'number.human.format', :locale => options[:locale], :default => {})
|
98
|
+
defaults = defaults.merge(human)
|
99
|
+
|
100
|
+
options = options.reverse_merge(defaults)
|
101
|
+
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
|
102
|
+
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
|
103
|
+
|
104
|
+
storage_units_format = ::I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
|
105
|
+
|
106
|
+
base = options[:prefix] == :si ? 1000 : 1024
|
107
|
+
|
108
|
+
if number.to_i < base
|
109
|
+
unit = ::I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true)
|
110
|
+
storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit).html_safe
|
111
|
+
else
|
112
|
+
max_exp = STORAGE_UNITS.size - 1
|
113
|
+
exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base
|
114
|
+
exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
|
115
|
+
number /= base ** exponent
|
116
|
+
|
117
|
+
unit_key = STORAGE_UNITS[exponent]
|
118
|
+
unit = ::I18n.translate(:"number.human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true)
|
119
|
+
|
120
|
+
formatted_number = number_with_precision(number, options)
|
121
|
+
storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).html_safe
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end # module NumberHelper
|
126
|
+
end # module Aerogel::I18n
|
@@ -2,6 +2,9 @@
|
|
2
2
|
#
|
3
3
|
module Aerogel
|
4
4
|
class Reloader
|
5
|
+
|
6
|
+
attr_accessor :files, :group, :opts, :action
|
7
|
+
|
5
8
|
# Use as middleware:
|
6
9
|
#
|
7
10
|
# # single file
|
@@ -17,12 +20,36 @@ class Reloader
|
|
17
20
|
# files.each{|f| load f}
|
18
21
|
# end
|
19
22
|
#
|
20
|
-
|
23
|
+
# # named groups of files
|
24
|
+
# use Aerogel::Reloader, "routes/*.rb", group: :routes do |files|
|
25
|
+
# files.each{|f| load f }
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # adding observer on a named group
|
29
|
+
# use Aerogel::Reloader, :routes, before: true do |files|
|
30
|
+
# # do more stuff before group :routes is reloaded
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Valid options are:
|
34
|
+
# :group => name group of files
|
35
|
+
# :before => if true invoke action block before group is reloaded
|
36
|
+
# :after => if true invoke action block after group is reloaded
|
37
|
+
#
|
38
|
+
#
|
39
|
+
def initialize( app, files, opts = {}, &blk )
|
21
40
|
@app = app
|
22
|
-
|
41
|
+
if files.is_a? Symbol
|
42
|
+
@group = files
|
43
|
+
@files = nil
|
44
|
+
else
|
45
|
+
@files = files
|
46
|
+
@group = opts[:group]
|
47
|
+
end
|
48
|
+
@opts = opts
|
23
49
|
@action = blk
|
24
|
-
@file_list = file_list( @files )
|
25
|
-
@signature = signature( @file_list )
|
50
|
+
@file_list = file_list( @files ) if @files
|
51
|
+
@signature = signature( @file_list ) if @file_list
|
52
|
+
Aerogel::Reloader.reloaders << self
|
26
53
|
end
|
27
54
|
|
28
55
|
def call( env )
|
@@ -30,18 +57,35 @@ class Reloader
|
|
30
57
|
@app.call( env )
|
31
58
|
end
|
32
59
|
|
60
|
+
def self.reloaders
|
61
|
+
@reloaders ||= []
|
62
|
+
end
|
63
|
+
|
33
64
|
private
|
34
65
|
|
35
66
|
# Checks if files are changed and reloads if so.
|
36
67
|
#
|
37
68
|
def check!
|
69
|
+
return unless @files
|
38
70
|
@file_list = file_list( @files )
|
39
71
|
new_signature = signature( @file_list )
|
40
72
|
if @signature != new_signature
|
41
73
|
# reload file list
|
42
|
-
puts "* Aerogel::Reloader reloading: #{@file_list}"
|
74
|
+
puts "* Aerogel::Reloader reloading: #{@file_list}, group: #{@group}"
|
75
|
+
if @group
|
76
|
+
# invoke :before group actions
|
77
|
+
Aerogel::Reloader.reloaders.select{|r| r.group == @group && r.opts[:before] }.each do |r|
|
78
|
+
r.action.call @file_list
|
79
|
+
end
|
80
|
+
end
|
43
81
|
@action.call @file_list
|
44
82
|
@signature = new_signature
|
83
|
+
if @group
|
84
|
+
# invoke :after group actions
|
85
|
+
Aerogel::Reloader.reloaders.select{|r| r.group == @group && r.opts[:after] }.each do |r|
|
86
|
+
r.action.call @file_list
|
87
|
+
end
|
88
|
+
end
|
45
89
|
end
|
46
90
|
end
|
47
91
|
|
data/lib/aerogel/core/routes.rb
CHANGED
@@ -6,7 +6,7 @@ module Aerogel::Routes
|
|
6
6
|
def self.registered(app)
|
7
7
|
reset!(app)
|
8
8
|
# load routes
|
9
|
-
Aerogel.
|
9
|
+
Aerogel.get_reverse_resource_list( :app, "routes/**/*.rb" ).each do |filename|
|
10
10
|
Aerogel.require_into( Aerogel::Application, filename )
|
11
11
|
end
|
12
12
|
|
@@ -42,10 +42,12 @@ private
|
|
42
42
|
# Sets up reloader for routes.
|
43
43
|
#
|
44
44
|
def self.setup_reloader(app)
|
45
|
-
app.use Aerogel::Reloader,
|
45
|
+
app.use Aerogel::Reloader,
|
46
|
+
->{ Aerogel.get_reverse_resource_list( :app, "routes/**/*.rb" ) },
|
47
|
+
group: :routes do |files|
|
46
48
|
# reset routes
|
47
49
|
reset!(app)
|
48
|
-
files.
|
50
|
+
files.each do |filename|
|
49
51
|
Aerogel.require_into( Aerogel::Application, filename )
|
50
52
|
end
|
51
53
|
end
|
@@ -14,7 +14,7 @@ class Namespace
|
|
14
14
|
|
15
15
|
def prefixed( method, *args, &block )
|
16
16
|
options = Hash === args.last ? args.pop : {}
|
17
|
-
routes = [*(args.pop || '')]
|
17
|
+
routes = [*(args.pop || '*')]
|
18
18
|
routes, args = routes+args, [] unless method == :route
|
19
19
|
routes.map!{|r| @prefix_path+r }
|
20
20
|
routes = [routes] if method == :route
|
data/lib/aerogel/core/version.rb
CHANGED
data/locales/core/en.yml
ADDED