aerogel-core 1.3.0 → 1.4.10

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