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
@@ -8,6 +8,8 @@ require 'aerogel/core/assets'
|
|
8
8
|
require 'aerogel/core/db'
|
9
9
|
require 'aerogel/core/render'
|
10
10
|
require 'aerogel/core/errors'
|
11
|
+
require 'aerogel/core/i18n'
|
12
|
+
require 'aerogel/core/cache'
|
11
13
|
|
12
14
|
class Aerogel::Application < Sinatra::Base
|
13
15
|
|
@@ -35,4 +37,5 @@ Aerogel.on_load do |app|
|
|
35
37
|
app.register Aerogel::Assets
|
36
38
|
app.register Aerogel::Db
|
37
39
|
app.register Aerogel::Render
|
40
|
+
app.register Aerogel::I18n
|
38
41
|
end
|
data/lib/aerogel/core/assets.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'sprockets-sass'
|
2
|
+
require 'sass'
|
1
3
|
require 'sinatra/asset_pipeline'
|
2
4
|
|
3
5
|
module Aerogel::Assets
|
@@ -5,6 +7,28 @@ module Aerogel::Assets
|
|
5
7
|
# Registers and configures assets pipeline
|
6
8
|
#
|
7
9
|
def self.registered( app )
|
10
|
+
setup_reloader(app) if Aerogel.config.aerogel.reloader?
|
11
|
+
setup_assets_pipeline app
|
12
|
+
end
|
13
|
+
|
14
|
+
# Configures reloader for assets.
|
15
|
+
#
|
16
|
+
def self.setup_reloader(app)
|
17
|
+
app.use Aerogel::Reloader, :routes, after: true do
|
18
|
+
reset!(app)
|
19
|
+
setup_assets_pipeline( app )
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Resets assets pipeline
|
24
|
+
#
|
25
|
+
def self.reset!(app)
|
26
|
+
# TODO how to remove middleware? anyone?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Configures assets pipeline.
|
30
|
+
#
|
31
|
+
def self.setup_assets_pipeline( app )
|
8
32
|
# Include these files when precompiling assets
|
9
33
|
app.set :assets_precompile,
|
10
34
|
%w(application.js controllers/*.js application.css controllers/*.css) +
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Aerogel::Cache implements LRU cache storage for partials (or other data?) caching.
|
2
|
+
#
|
3
|
+
|
4
|
+
require 'lru_redux'
|
5
|
+
|
6
|
+
module Aerogel
|
7
|
+
module Cache
|
8
|
+
|
9
|
+
# Calculates a cache key for a single object,
|
10
|
+
# or a compound cache key for a list of objects.
|
11
|
+
#
|
12
|
+
def self.cache_key( args )
|
13
|
+
if Array === args
|
14
|
+
args.flatten.map{|o| object_to_cache_key o }.join("/")
|
15
|
+
else
|
16
|
+
object_to_cache_key args
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Retrieves cache entry by calculated cache key of +args+,
|
21
|
+
# or runs given +block+, stores its result in the cache and returns its value.
|
22
|
+
#
|
23
|
+
def self.cacheable( *args, &block )
|
24
|
+
key = cache_key args
|
25
|
+
cache.getset key do
|
26
|
+
yield key
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns cache structure.
|
31
|
+
#
|
32
|
+
def self.cache
|
33
|
+
@cache ||= initialize_cache
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns list of stored keys.
|
37
|
+
#
|
38
|
+
def self.keys
|
39
|
+
cache.to_a.map(&:first)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Clears cache completely.
|
43
|
+
#
|
44
|
+
def self.clear!
|
45
|
+
@cache.clear
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Creates LRU cache with maximum objects count
|
51
|
+
# specified by config value 'aerogel.cache.max_size'.
|
52
|
+
#
|
53
|
+
def self.initialize_cache
|
54
|
+
max_size = Aerogel.config.aerogel.cache.max_size! rescue 1000
|
55
|
+
LruRedux::Cache.new( max_size )
|
56
|
+
end
|
57
|
+
|
58
|
+
# Calculates a cache key for given +object+.
|
59
|
+
#
|
60
|
+
# If the object responds to :cache_key, its result is returned,
|
61
|
+
# otherwise cache key is the object converted to String.
|
62
|
+
#
|
63
|
+
def self.object_to_cache_key( object )
|
64
|
+
if object.respond_to? :cache_key
|
65
|
+
object.cache_key
|
66
|
+
else
|
67
|
+
object.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end # module Cache
|
72
|
+
end # module Aerogel
|
data/lib/aerogel/core/config.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'aerogel/configurator'
|
2
2
|
require 'rack-flash'
|
3
|
+
require 'sinatra/redirect_with_flash'
|
3
4
|
require 'sinatra/multi_route'
|
4
5
|
|
5
6
|
module Aerogel
|
@@ -28,11 +29,18 @@ module Aerogel
|
|
28
29
|
|
29
30
|
# set :protection, true
|
30
31
|
# set :protect_from_csrf, true
|
31
|
-
app.
|
32
|
+
app.enable :sessions
|
33
|
+
if Aerogel.config.hostname?
|
34
|
+
app.set :sessions, domain: "."+Aerogel.config.hostname!
|
35
|
+
end
|
32
36
|
# TODO: demand to configure session secret on application level
|
33
|
-
|
37
|
+
if Aerogel.config.session_secret?
|
38
|
+
app.set :session_secret, Aerogel.config.session_secret!
|
39
|
+
end
|
40
|
+
|
34
41
|
app.use Rack::Protection::AuthenticityToken
|
35
42
|
app.use Rack::Flash, :sweep => true
|
43
|
+
app.helpers Sinatra::RedirectWithFlash
|
36
44
|
|
37
45
|
app.register Sinatra::MultiRoute
|
38
46
|
end
|
data/lib/aerogel/core/core.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
require 'aerogel/core/core_ext/array'
|
3
|
+
require 'aerogel/core/core_ext/hash'
|
4
|
+
|
1
5
|
module Aerogel
|
2
6
|
|
3
7
|
class << self
|
@@ -7,7 +11,7 @@ module Aerogel
|
|
7
11
|
# Returns module version.
|
8
12
|
#
|
9
13
|
def self.version
|
10
|
-
Aerogel::VERSION
|
14
|
+
Aerogel::Core::VERSION
|
11
15
|
end
|
12
16
|
|
13
17
|
# Registers a new path for all resource loaders.
|
@@ -20,7 +24,9 @@ module Aerogel
|
|
20
24
|
#
|
21
25
|
def self.register_path( path, type = nil )
|
22
26
|
@registered_paths ||= []
|
23
|
-
|
27
|
+
path = File.expand_path( path )
|
28
|
+
module_name = File.basename path
|
29
|
+
@registered_paths << { path: path, module_name: module_name, type: type }
|
24
30
|
end
|
25
31
|
|
26
32
|
# Returns registered paths.
|
@@ -32,15 +38,54 @@ module Aerogel
|
|
32
38
|
|
33
39
|
# Returns list of paths for specified resource type.
|
34
40
|
#
|
35
|
-
def self.get_resource_paths( type )
|
36
|
-
|
37
|
-
|
41
|
+
def self.get_resource_paths( type, &block )
|
42
|
+
paths = []
|
43
|
+
registered_paths( type ).each do |base_path|
|
44
|
+
path = base_path[:type].nil? ? File.join( base_path[:path], type.to_s ) : base_path[:path]
|
45
|
+
paths << { base_path: base_path, path: path }
|
46
|
+
yield path, base_path if block_given?
|
38
47
|
end
|
48
|
+
paths.map {|p| p[:path] }
|
39
49
|
end
|
40
50
|
|
41
51
|
# Returns list of filenames of resources of specified type,
|
42
52
|
# environment sub-folders included, filtered by wildcard mask.
|
43
53
|
#
|
54
|
+
# Resources are listed in a forward order of paths, files within each
|
55
|
+
# path listed in alphabetic order.
|
56
|
+
#
|
57
|
+
# The resources are searched in following order:
|
58
|
+
# path1 + wildcard
|
59
|
+
# path1 + environment + wildcard
|
60
|
+
# path2 + wildcard
|
61
|
+
# path2 + environment + wildcard
|
62
|
+
# etc
|
63
|
+
#
|
64
|
+
def self.get_resource_list( type, wildcard, environment = nil, &block )
|
65
|
+
resource_list = []
|
66
|
+
get_resource_paths( type ) do |path, base_path|
|
67
|
+
paths = Dir.glob( File.join( path, wildcard ) ).sort
|
68
|
+
if environment
|
69
|
+
paths << Dir.glob( File.join( path, environment.to_s, wildcard ) ).sort
|
70
|
+
end
|
71
|
+
# puts "Aerogel::get_resource_list: type=#{type} environment=#{environment} path=#{path}: #{paths}"
|
72
|
+
if block_given?
|
73
|
+
paths.each do |filename|
|
74
|
+
relative_filename = filename.sub( /^#{path}\/?/, '' )
|
75
|
+
yield filename, relative_filename, path, base_path
|
76
|
+
end
|
77
|
+
end
|
78
|
+
resource_list << paths
|
79
|
+
end
|
80
|
+
resource_list.flatten
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns reversed list of filenames of resources of specified type,
|
84
|
+
# environment sub-folders included, filtered by wildcard mask.
|
85
|
+
#
|
86
|
+
# Reverse order is applied to registered paths, but not to files within single path,
|
87
|
+
# which are listed in alphabetic order.
|
88
|
+
#
|
44
89
|
# The resources are searched in following order:
|
45
90
|
# path1 + wildcard
|
46
91
|
# path1 + environment + wildcard
|
@@ -48,11 +93,11 @@ module Aerogel
|
|
48
93
|
# path2 + environment + wildcard
|
49
94
|
# etc
|
50
95
|
#
|
51
|
-
def self.
|
52
|
-
get_resource_paths( type ).map do |path|
|
53
|
-
paths = Dir.glob( File.join( path, wildcard ) )
|
96
|
+
def self.get_reverse_resource_list( type, wildcard, environment = nil )
|
97
|
+
get_resource_paths( type ).reverse.map do |path|
|
98
|
+
paths = Dir.glob( File.join( path, wildcard ) ).sort
|
54
99
|
if environment
|
55
|
-
paths << Dir.glob( File.join( path, environment.to_s, wildcard ) )
|
100
|
+
paths << Dir.glob( File.join( path, environment.to_s, wildcard ) ).sort
|
56
101
|
end
|
57
102
|
# puts "Aerogel::get_resource_list: type=#{type} environment=#{environment} path=#{path}: #{paths}"
|
58
103
|
paths
|
@@ -82,7 +127,7 @@ module Aerogel
|
|
82
127
|
# Require resources specified by type and wildcard in reverse order.
|
83
128
|
#
|
84
129
|
def self.require_resources_reverse( type, wildcard, environment = nil )
|
85
|
-
files_to_require = Aerogel.
|
130
|
+
files_to_require = Aerogel.get_reverse_resource_list( type, wildcard, environment )
|
86
131
|
files_to_require.each do |filename|
|
87
132
|
# begin
|
88
133
|
require filename
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# Core extensions to Array.
|
3
|
+
#
|
4
|
+
|
5
|
+
class Array
|
6
|
+
|
7
|
+
# Returns array with excluded elements.
|
8
|
+
#
|
9
|
+
def except( *args )
|
10
|
+
self - [ *args ]
|
11
|
+
end
|
12
|
+
|
13
|
+
# Modifies and returns array with excluded elements.
|
14
|
+
#
|
15
|
+
def except!( *args )
|
16
|
+
self.replace( self.except! *args )
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns array containing only elements listed in +args+.
|
20
|
+
#
|
21
|
+
def only( *args )
|
22
|
+
self & [*args]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Modifies and returns array containing only elements listed in +args+.
|
26
|
+
#
|
27
|
+
def only!( *args )
|
28
|
+
self.replace( self.only *args )
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns +true+ if this array contains +other+ completely.
|
32
|
+
#
|
33
|
+
def contains?( other )
|
34
|
+
( other - self ).blank?
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
end # class Array
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#
|
2
|
+
# Core extensions to Hash.
|
3
|
+
#
|
4
|
+
|
5
|
+
class Hash
|
6
|
+
|
7
|
+
# defined in ActiveSupport: #except, #except!
|
8
|
+
|
9
|
+
# Returns hash containing only elements listed in +args+.
|
10
|
+
#
|
11
|
+
def only( *keys )
|
12
|
+
self.select{|key,v| [*keys].include? key }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Modifies and returns hash containing only elements listed in +args+.
|
16
|
+
#
|
17
|
+
def only!( *keys )
|
18
|
+
self.select!{|key,v| [*keys].include? key }
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns hash containing all elements except those with specified +keys+.
|
23
|
+
#
|
24
|
+
def except( *keys )
|
25
|
+
dup.except!( *keys )
|
26
|
+
end
|
27
|
+
|
28
|
+
# Modifies and returns hash containing all elements except those with specified +keys+.
|
29
|
+
#
|
30
|
+
def except!( *keys )
|
31
|
+
keys.each do |k|
|
32
|
+
if String === k || Symbol === k
|
33
|
+
delete k.to_sym
|
34
|
+
delete k.to_s
|
35
|
+
else
|
36
|
+
delete k
|
37
|
+
end
|
38
|
+
end
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns Hash converted to a string of HTML tag attributes.
|
43
|
+
#
|
44
|
+
def to_html_params
|
45
|
+
self.map{|n, v| v.nil? ? "#{n}" : "#{n}=\"#{v}\""}.join(" ")
|
46
|
+
end
|
47
|
+
|
48
|
+
end # class Array
|
data/lib/aerogel/core/db.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'mongoid'
|
2
|
+
require 'mongoid/tree'
|
2
3
|
require 'aerogel/configurator'
|
3
4
|
require 'aerogel/core/db/model'
|
4
5
|
|
@@ -41,6 +42,11 @@ module Aerogel::Db
|
|
41
42
|
#
|
42
43
|
def self.clear!
|
43
44
|
puts "* clearing database"
|
45
|
+
models.each do |model_class|
|
46
|
+
puts "** destroing all objects in #{model_class.name}"
|
47
|
+
model_class.destroy_all
|
48
|
+
end
|
49
|
+
puts "* purging database"
|
44
50
|
Mongoid.purge!
|
45
51
|
end
|
46
52
|
|
@@ -56,10 +62,11 @@ private
|
|
56
62
|
#
|
57
63
|
def self.load_models
|
58
64
|
reset!
|
59
|
-
Aerogel.get_resource_list( 'db/model', '
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
Aerogel.get_resource_list( 'db/model', '**/*.rb' ) do |full_filename, model_filename, path|
|
66
|
+
# puts "** loading model: #{path} #{model_filename}"
|
67
|
+
load full_filename
|
68
|
+
# puts "** classify: #{class_name}"
|
69
|
+
self.models << filename_to_model( model_filename )
|
63
70
|
end
|
64
71
|
end
|
65
72
|
|
@@ -68,8 +75,8 @@ private
|
|
68
75
|
def self.reset!(app = nil)
|
69
76
|
self.models ||= []
|
70
77
|
# reset model classes
|
71
|
-
self.models.each do |model|
|
72
|
-
|
78
|
+
self.models.uniq.each do |model|
|
79
|
+
model.parent.send(:remove_const, model.name.demodulize.to_sym)
|
73
80
|
end
|
74
81
|
self.models = []
|
75
82
|
end
|
@@ -78,7 +85,9 @@ private
|
|
78
85
|
# Configures reloader for models.
|
79
86
|
#
|
80
87
|
def self.setup_reloader(app)
|
81
|
-
app.use Aerogel::Reloader,
|
88
|
+
app.use Aerogel::Reloader,
|
89
|
+
->{ Aerogel.get_resource_list( "db/model", "**/*.rb" ) },
|
90
|
+
group: :'db/model' do
|
82
91
|
reset!(app)
|
83
92
|
load_models
|
84
93
|
end
|
@@ -99,7 +108,12 @@ private
|
|
99
108
|
def self.load_and_process_seeds!
|
100
109
|
seed_files = Aerogel.get_resource_list( 'db/seed', '*.seed', environment )
|
101
110
|
seed_files.each do |seed_file|
|
102
|
-
|
111
|
+
begin
|
112
|
+
load_and_process_single_seed! seed_file
|
113
|
+
rescue => e
|
114
|
+
puts "!!! Failed to process seed: #{seed_file}"
|
115
|
+
puts "!!! #{e}"
|
116
|
+
end
|
103
117
|
end
|
104
118
|
end
|
105
119
|
|
@@ -148,5 +162,11 @@ private
|
|
148
162
|
obj_keys.map{|k,v| "#{k}:'#{v}'"}.join(', ')
|
149
163
|
end
|
150
164
|
|
165
|
+
# Returns class object inferred from filename.
|
166
|
+
#
|
167
|
+
def self.filename_to_model( filename )
|
168
|
+
filename.chomp('.rb').split("/").map(&:camelize).join("::").constantize
|
169
|
+
end
|
170
|
+
|
151
171
|
end # module Aerogel::Db
|
152
172
|
|
@@ -3,22 +3,54 @@
|
|
3
3
|
module Model
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
def self.redefined_field_types
|
7
|
+
@redefined_field_types ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.define_field_type( type, method_name )
|
11
|
+
redefined_field_types[type] = method_name.to_sym
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
8
15
|
|
9
16
|
# Finds document by id.
|
10
17
|
# Raises error if document is not found.
|
11
18
|
#
|
12
|
-
def
|
19
|
+
def find!( *args )
|
13
20
|
raise_not_found_error_was = Mongoid.raise_not_found_error
|
14
21
|
begin
|
15
22
|
Mongoid.raise_not_found_error = true
|
16
|
-
self.find *args
|
23
|
+
self.find( *args )
|
17
24
|
ensure
|
18
25
|
Mongoid.raise_not_found_error = raise_not_found_error_was
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
29
|
+
# ...
|
30
|
+
# other class methods can be defined inside Model::ClassMethods by aerogel modules
|
31
|
+
# ...
|
32
|
+
|
33
|
+
end # module ClassMethods
|
34
|
+
|
35
|
+
included do
|
36
|
+
include Mongoid::Document
|
37
|
+
|
38
|
+
class << self
|
39
|
+
alias_method :define_field_mongoid, :field
|
40
|
+
end
|
41
|
+
|
42
|
+
# Defines native Mongoid field or calls field type handler
|
43
|
+
# in case of redefined field types.
|
44
|
+
#
|
45
|
+
def self.field( name, opts = {} )
|
46
|
+
if opts[:type] && Model.redefined_field_types.key?( opts[:type] )
|
47
|
+
self.send Model.redefined_field_types[opts[:type]], name, opts
|
48
|
+
else
|
49
|
+
self.define_field_mongoid( name, opts )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
extend ClassMethods
|
22
54
|
end
|
23
55
|
|
24
56
|
module NonPersistent
|
@@ -31,4 +63,20 @@ module Model
|
|
31
63
|
end
|
32
64
|
end # module NonPersistent
|
33
65
|
|
66
|
+
module Timestamps
|
67
|
+
extend ActiveSupport::Concern
|
68
|
+
included do
|
69
|
+
include Mongoid::Timestamps
|
70
|
+
end
|
71
|
+
end # module Timestamps
|
72
|
+
|
73
|
+
module OrderedTree
|
74
|
+
extend ActiveSupport::Concern
|
75
|
+
included do
|
76
|
+
include Mongoid::Tree
|
77
|
+
include Mongoid::Tree::Ordering
|
78
|
+
include Mongoid::Tree::Traversal
|
79
|
+
end
|
80
|
+
end # module OrderedTree
|
81
|
+
|
34
82
|
end # module Model
|