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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/aerogel-core.gemspec +8 -2
  3. data/app/helpers/assets.rb +22 -8
  4. data/app/helpers/core.rb +82 -0
  5. data/app/helpers/i18n.rb +11 -0
  6. data/app/helpers/icon.rb +12 -0
  7. data/app/helpers/render.rb +89 -17
  8. data/app/helpers/tags.rb +18 -3
  9. data/app/routes/aerogel.rb +30 -0
  10. data/app/routes/core.rb +16 -1
  11. data/app/routes/i18n.rb +14 -0
  12. data/config/application.conf +8 -0
  13. data/config/development/aerogel.conf +9 -0
  14. data/config/production/aerogel.conf +10 -0
  15. data/lib/aerogel/core/application.rb +3 -0
  16. data/lib/aerogel/core/assets.rb +24 -0
  17. data/lib/aerogel/core/cache.rb +72 -0
  18. data/lib/aerogel/core/config.rb +10 -2
  19. data/lib/aerogel/core/core.rb +55 -10
  20. data/lib/aerogel/core/core_ext/array.rb +38 -0
  21. data/lib/aerogel/core/core_ext/hash.rb +48 -0
  22. data/lib/aerogel/core/db.rb +28 -8
  23. data/lib/aerogel/core/db/model.rb +52 -4
  24. data/lib/aerogel/core/errors.rb +23 -1
  25. data/lib/aerogel/core/helpers.rb +1 -1
  26. data/lib/aerogel/core/i18n.rb +134 -0
  27. data/lib/aerogel/core/i18n/number_helper.rb +126 -0
  28. data/lib/aerogel/core/reloader.rb +49 -5
  29. data/lib/aerogel/core/routes.rb +5 -3
  30. data/lib/aerogel/core/routes/namespace.rb +1 -1
  31. data/lib/aerogel/core/version.rb +3 -1
  32. data/locales/core/en.yml +17 -0
  33. data/locales/core/ru.yml +17 -0
  34. data/locales/db/en.yml +25 -0
  35. data/locales/db/ru.yml +24 -0
  36. data/locales/i18n-defaults/en.yml +211 -0
  37. data/locales/i18n-defaults/ru.yml +257 -0
  38. data/rake/console.rake +8 -0
  39. data/views/layouts/application.html.erb +1 -1
  40. data/views/lorem.html.erb +48 -0
  41. metadata +91 -3
  42. 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
@@ -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
@@ -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.set :sessions, true
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
- # set :session_secret, '$aer0G31'
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
@@ -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
- @registered_paths << { path: File.expand_path( path ), type: type }
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
- registered_paths( type ).map do |p|
37
- p[:type].nil? ? File.join( p[:path], type.to_s ) : p[:path]
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.get_resource_list( type, wildcard, environment = nil )
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.get_resource_list( type, wildcard, environment ).reverse
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
@@ -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', '*.rb' ).each do |model_filename|
60
- load model_filename
61
- class_name = File.basename( model_filename, '.rb' ).camelize
62
- self.models << eval(class_name)
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
- Object.send(:remove_const, model.name.to_sym)
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, ->{ Aerogel.get_resource_list( "db/model", "*.rb" ) } do
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
- load_and_process_single_seed! seed_file
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
- included do
7
- include Mongoid::Document
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 self.find!( *args )
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