slick 0.16.3 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -8
  3. data/.slick +0 -0
  4. data/.travis.yml +3 -5
  5. data/LICENSE +20 -0
  6. data/README.md +3 -32
  7. data/Rakefile +1 -0
  8. data/config.rb +8 -0
  9. data/config.ru +4 -0
  10. data/exe/slick +8 -0
  11. data/lib/slick.rb +50 -3
  12. data/lib/slick/command.rb +29 -0
  13. data/lib/slick/commands/create_database.rb +9 -0
  14. data/lib/slick/commands/drop_database.rb +9 -0
  15. data/lib/slick/commands/init_database.rb +9 -0
  16. data/lib/slick/commands/list_commands.rb +14 -0
  17. data/lib/slick/commands/migrate_database.rb +9 -0
  18. data/lib/slick/commands/reset_database.rb +10 -0
  19. data/lib/slick/commands/start_console.rb +14 -0
  20. data/lib/slick/commands/start_server.rb +14 -0
  21. data/lib/slick/concern.rb +19 -0
  22. data/lib/slick/database.rb +168 -0
  23. data/lib/slick/database/abstract_row.rb +13 -0
  24. data/lib/slick/database/column.rb +64 -0
  25. data/lib/slick/database/migration.rb +36 -0
  26. data/lib/slick/database/migrator.rb +67 -0
  27. data/lib/slick/database/row.rb +127 -0
  28. data/lib/slick/database/table.rb +381 -0
  29. data/lib/slick/database/union.rb +86 -0
  30. data/lib/slick/helper.rb +24 -0
  31. data/lib/slick/helpers.rb +4 -0
  32. data/lib/slick/helpers/dir.rb +6 -0
  33. data/lib/slick/helpers/echo.rb +6 -0
  34. data/lib/slick/helpers/grab.rb +10 -0
  35. data/lib/slick/helpers/html_builder.rb +180 -0
  36. data/lib/slick/helpers/text_builder.rb +22 -0
  37. data/lib/slick/monkey_patches/html_escape.rb +8 -0
  38. data/lib/slick/monkey_patches/html_unescape.rb +8 -0
  39. data/lib/slick/monkey_patches/paramify.rb +11 -0
  40. data/lib/slick/monkey_patches/pluralize.rb +8 -0
  41. data/lib/slick/monkey_patches/require_all.rb +18 -0
  42. data/lib/slick/monkey_patches/singularize.rb +8 -0
  43. data/lib/slick/monkey_patches/url_encode.rb +8 -0
  44. data/lib/slick/monkey_patches/url_escape.rb +8 -0
  45. data/lib/slick/monkey_patches/url_unescape.rb +8 -0
  46. data/lib/slick/project.rb +53 -0
  47. data/lib/slick/project_watcher.rb +36 -0
  48. data/lib/slick/registry.rb +39 -0
  49. data/lib/slick/request.rb +6 -0
  50. data/lib/slick/resource_factories/config.rb +14 -0
  51. data/lib/slick/resource_factories/database.rb +6 -0
  52. data/lib/slick/resource_factories/database_schema_cache.rb +6 -0
  53. data/lib/slick/resource_factories/database_session_cache.rb +6 -0
  54. data/lib/slick/resource_factories/env.rb +14 -0
  55. data/lib/slick/resource_factories/environment.rb +6 -0
  56. data/lib/slick/resource_factories/file.rb +6 -0
  57. data/lib/slick/resource_factories/params.rb +6 -0
  58. data/lib/slick/resource_factories/project.rb +6 -0
  59. data/lib/slick/resource_factories/request.rb +6 -0
  60. data/lib/slick/resource_factories/response.rb +6 -0
  61. data/lib/slick/resource_factories/web.rb +11 -0
  62. data/lib/slick/resource_factory.rb +35 -0
  63. data/lib/slick/resource_provider.rb +51 -0
  64. data/lib/slick/response.rb +14 -0
  65. data/lib/slick/util.rb +72 -0
  66. data/lib/slick/util/inflections.rb +122 -0
  67. data/lib/slick/util/params_hash.rb +38 -0
  68. data/lib/slick/version.rb +1 -1
  69. data/lib/slick/web.rb +4 -0
  70. data/lib/slick/web/dir.rb +92 -0
  71. data/lib/slick/web/file.rb +66 -0
  72. data/lib/slick/web/file_interpreter.rb +24 -0
  73. data/lib/slick/web/file_interpreters/erb.rb +33 -0
  74. data/lib/slick/web/file_interpreters/js.rb +17 -0
  75. data/lib/slick/web/file_interpreters/rb.rb +14 -0
  76. data/lib/slick/web/file_interpreters/sass.rb +30 -0
  77. data/lib/slick/web/node.rb +35 -0
  78. data/lib/slick/workspace.rb +8 -0
  79. data/slick.gemspec +15 -4
  80. data/web/_layout.erb +13 -0
  81. data/web/index.erb +7 -0
  82. data/web/javascripts/index.js +2 -0
  83. data/web/stylesheets/index.scss +2 -0
  84. metadata +127 -11
  85. data/Gemfile.lock +0 -22
  86. data/bin/console +0 -14
  87. data/bin/setup +0 -8
@@ -0,0 +1,53 @@
1
+
2
+
3
+ class Slick::Project
4
+
5
+ attr_reader :root_path, :load_paths, :name, :lib_names
6
+
7
+ def initialize
8
+ @root_path = find_root_path(Dir.pwd)
9
+ @load_paths = $LOAD_PATH.map{|load_path| find_root_path(load_path) }.compact
10
+ if @root_path
11
+ @name = gem_name(@root_path)
12
+ @load_paths.unshift(@root_path) unless @load_paths.include?(@root_path)
13
+ end
14
+
15
+ @lib_names = @load_paths.map{|load_path| gem_name(load_path) }
16
+ end
17
+
18
+ def exist?
19
+ !@name.nil?
20
+ end
21
+
22
+ private
23
+
24
+ def find_file_path(path, pattern)
25
+ current_path = path
26
+ while true
27
+ Dir.open(current_path).each do |item|
28
+ candidate_file_path = "#{current_path}/#{item}"
29
+ return candidate_file_path if File.file?(candidate_file_path) && item.match(pattern)
30
+ end
31
+ if matches = current_path.match(/\A(.*)\/([^\/]+)\z/)
32
+ current_path = matches[1]
33
+ current_path = '/' if current_path == ''
34
+ else
35
+ break
36
+ end
37
+ end
38
+ nil
39
+ end
40
+
41
+ def find_root_path(path)
42
+ out = find_file_path(path, /\A\.slick\z/)
43
+ out.sub!(/\.slick\z/, '').sub!(/\A(.+)\/\z/, '\1') if out
44
+ out
45
+ end
46
+
47
+ def gem_name(path)
48
+ out = find_file_path(path, /\A[^\/]+\.gemspec\z/)
49
+ out.sub!(/\A.*\//, '').sub!(/\.gemspec\z/, '\1') if out
50
+ out
51
+ end
52
+
53
+ end
@@ -0,0 +1,36 @@
1
+
2
+ require "slick/helpers"
3
+
4
+ class Slick::ProjectWatcher
5
+
6
+ def self.watch
7
+ self.new.watch
8
+ end
9
+
10
+ include Slick::Helpers
11
+
12
+ def watch
13
+ last_modified_times = {}
14
+
15
+ while true
16
+ is_change = false
17
+
18
+ Dir.glob("#{project.root_path}/**/*").each do |file|
19
+ last_modified_time = File.mtime(file)
20
+ if last_modified_times[file] != last_modified_time
21
+ is_change = true
22
+ end
23
+ last_modified_times[file] = last_modified_time
24
+ end
25
+
26
+ if is_change
27
+ Process.kill('KILL', @child_process_pid) if @child_process_pid
28
+ @child_process_pid = Process.fork
29
+ break if !@child_process_pid
30
+
31
+ end
32
+ end
33
+ end
34
+
35
+
36
+ end
@@ -0,0 +1,39 @@
1
+
2
+ module Slick::Registry
3
+
4
+ attr_reader :name
5
+
6
+ def registered?
7
+ registered_classes.values.include? self
8
+ end
9
+
10
+ def registered_classes
11
+ @registered_classes ||= superclass.respond_to?(:registered_classes) ? superclass.registered_classes : {}
12
+ end
13
+
14
+ def register(name, *args, &block)
15
+ raise "Class has already been registered" if registered?
16
+ name = name.to_s
17
+ instance_eval{ @name = name }
18
+ registered_classes[name] = self
19
+ self
20
+ end
21
+
22
+ def for(name, options = {})
23
+ name = name.to_s
24
+ registered_classes[name] || begin
25
+ klass = Class.new(self)
26
+ if options.paramify.register_if_not_exists == 'true'
27
+ klass.register(name, options)
28
+ else
29
+ klass.instance_eval{ @name = name }
30
+ end
31
+ klass
32
+ end
33
+ end
34
+
35
+ def create(name, *args, &block)
36
+ self.for(name).new(*args, &block)
37
+ end
38
+
39
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "rack"
3
+
4
+ class Slick::Request < Rack::Request
5
+
6
+ end
@@ -0,0 +1,14 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "config", :shared => true }.define_method "create" do
5
+ if project.exist?
6
+ config_file_path = "#{project.root_path}/config.rb"
7
+ Slick::Workspace.new.instance_eval(
8
+ File.read(config_file_path),
9
+ config_file_path
10
+ ).paramify
11
+ else
12
+ {}.paramify
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "database" }.define_method "create" do
5
+ Slick::Database.new(config.database)
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "database_schema_cache", :shared => true }.define_method "create" do
5
+ {}
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "database_session_cache" }.define_method "create" do
5
+ {}
6
+ end
@@ -0,0 +1,14 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "env" }.define_method "create" do
5
+ {
6
+ "REQUEST_METHOD" => "GET",
7
+ "SCRIPT_NAME" => "",
8
+ "PATH_INFO" => "/",
9
+ "QUERY_STRING" => "",
10
+ "SERVER_NAME" => "localhost",
11
+ "SERVER_PORT" => "80",
12
+ "rack.input" => ""
13
+ }
14
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "environment", :shared => true }.define_method "create" do
5
+ ENV["RACK_ENV"] || "development"
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "file" }.define_method "create" do
5
+ web.find_file("/")
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "params" }.define_method "create" do
5
+ request.params.paramify
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "project", :shared => true }.define_method "create" do
5
+ Slick::Project.new
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "request" }.define_method "create" do
5
+ Slick::Request.new(env)
6
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "response" }.define_method "create" do
5
+ Slick::Response[200, {"Content-Type" => "text/html"}, []]
6
+ end
@@ -0,0 +1,11 @@
1
+
2
+ require "slick/resource_factory"
3
+
4
+ Class.new(Slick::ResourceFactory){ register "web", :shared => true }.define_method "create" do
5
+ out = Slick::Web::Dir.new
6
+ project.load_paths.reverse.each do |load_path|
7
+ web_dir_path = "#{load_path}/web"
8
+ out.merge_dir(web_dir_path) if File.directory?(web_dir_path)
9
+ end
10
+ out
11
+ end
@@ -0,0 +1,35 @@
1
+
2
+ require "slick/registry"
3
+ require "slick/helper"
4
+ require "slick/helpers"
5
+
6
+
7
+ class Slick::ResourceFactory
8
+
9
+ class << self
10
+
11
+ include Slick::Registry
12
+
13
+ def register(name, options = {})
14
+ super(name)
15
+
16
+ @shared = options.paramify.shared == "true"
17
+
18
+ Class.new(Slick::Helper){ register name }.define_method "call" do
19
+ ::Slick.resource_provider[self.class.name]
20
+ end
21
+ end
22
+
23
+ def shared?
24
+ @shared
25
+ end
26
+
27
+ end
28
+
29
+ include Slick::Helpers
30
+
31
+ def create
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,51 @@
1
+
2
+
3
+ class Slick::ResourceProvider
4
+
5
+ attr_reader :shared_resources
6
+
7
+ def initialize
8
+ @shared_resources = {}
9
+ @mutex = Mutex.new
10
+ end
11
+
12
+ def thread_resources
13
+ Thread.current["SLICK_RESOURCES"] ||= {}
14
+ end
15
+
16
+ def [](name)
17
+ name = name.to_s
18
+
19
+ return thread_resources[name] if !thread_resources[name].nil?
20
+ return shared_resources[name] if !shared_resources[name].nil?
21
+
22
+ resource_factory = Slick::ResourceFactory.create(name)
23
+
24
+ if resource_factory.class.shared?
25
+ @mutex.synchronize { shared_resources[name] ||= resource_factory.create }
26
+ shared_resources[name]
27
+ else
28
+ thread_resources[name] = resource_factory.create
29
+ thread_resources[name]
30
+ end
31
+ end
32
+
33
+ def []=(name, value)
34
+ thread_resources[name.to_s] = value
35
+ self
36
+ end
37
+
38
+ def reset(shared = false, thread = true, &block)
39
+ previous_shared_resources = shared_resources
40
+ previous_thread_resources = thread_resources
41
+ @mutex.syncronize { @shared_resources = {} } if shared
42
+ Thread.current["SLICK_RESOURCES"] = {} if thread
43
+ if block
44
+ out = block.call
45
+ @mutex.synchronize { @shared_resources = previous_shared_resources } if shared
46
+ Thread.current["SLICK_RESOURCES"] = previous_thread_resources if thread
47
+ out
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,14 @@
1
+
2
+ require "rack"
3
+
4
+ class Slick::Response < Rack::Response
5
+
6
+ def to_s
7
+ body.join
8
+ end
9
+
10
+ def inspect
11
+ to_s
12
+ end
13
+
14
+ end
@@ -0,0 +1,72 @@
1
+
2
+ require 'cgi'
3
+
4
+ module Slick::Util
5
+
6
+ class << self
7
+
8
+ def pluralize(word)
9
+ word = word.to_s
10
+ Inflections.pluralize_rules.each do |rule|
11
+ pattern, replacement = rule
12
+ return word.sub(pattern, replacement) if word.match?(pattern)
13
+ end
14
+ end
15
+
16
+ def singularize(word)
17
+ word = word.to_s
18
+ Inflections.singularize_rules.each do |rule|
19
+ pattern, replacement = rule
20
+ return word.sub(pattern, replacement) if word.match?(pattern)
21
+ end
22
+ end
23
+
24
+ def html_escape(stringable)
25
+ CGI::escapeHTML(stringable.to_s)
26
+ end
27
+
28
+ def html_unescape(stringable)
29
+ CGI::unescapeHTML(stringable.to_s)
30
+ end
31
+
32
+ def url_escape(stringable)
33
+ CGI::escape(stringable.to_s)
34
+ end
35
+
36
+ def url_unescape(stringable)
37
+ CGI::unescape(stringable.to_s)
38
+ end
39
+
40
+ def paramify(hashable)
41
+ if hashable.kind_of?(Hash)
42
+ out = ParamsHash.new
43
+ hashable.each{|name, value| out[name] = paramify(value)}
44
+ out
45
+ elsif hashable.kind_of?(Array)
46
+ out = ParamsHash.new
47
+ hashable.each_with_index{|value, index| out[index] = paramify(value)}
48
+ out
49
+ else
50
+ return hashable
51
+ end
52
+ end
53
+
54
+ def url_encode(hashable, path = [], out = [])
55
+ hashable = paramify(hashable) if !hashable.kind_of?(ParamsHash)
56
+ if hashable.kind_of?(ParamsHash)
57
+ hashable.each do |name, value|
58
+ path.push(name)
59
+ url_encode(value, path, out)
60
+ path.pop
61
+ end
62
+ return out.join('&') if path.count == 0
63
+ elsif path.count == 0
64
+ return url_escape(hashable)
65
+ else
66
+ out << "#{url_escape(path.first)}#{path[1..path.length].map{|name| "[#{url_escape(name)}]"}.join}=#{url_escape(hashable)}"
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,122 @@
1
+
2
+ module Slick::Util::Inflections
3
+
4
+ instance_eval do
5
+ @pluralize_rules = []
6
+ @singularize_rules = []
7
+ end
8
+
9
+ class << self
10
+
11
+ attr_accessor :pluralize_rules
12
+ attr_accessor :singularize_rules
13
+
14
+ def plural(*args)
15
+ pluralize_rules.prepend(args)
16
+ end
17
+
18
+ def singular(*args)
19
+ singularize_rules.prepend(args)
20
+ end
21
+
22
+ def irregular(singular, plural)
23
+ s0 = singular[0]
24
+ srest = singular[1..-1]
25
+
26
+ p0 = plural[0]
27
+ prest = plural[1..-1]
28
+
29
+ if s0.upcase == p0.upcase
30
+ plural(/(#{s0})#{srest}$/i, '\1' + prest)
31
+ plural(/(#{p0})#{prest}$/i, '\1' + prest)
32
+
33
+ singular(/(#{s0})#{srest}$/i, '\1' + srest)
34
+ singular(/(#{p0})#{prest}$/i, '\1' + srest)
35
+ else
36
+ plural(/#{s0.upcase}(?i)#{srest}$/, p0.upcase + prest)
37
+ plural(/#{s0.downcase}(?i)#{srest}$/, p0.downcase + prest)
38
+ plural(/#{p0.upcase}(?i)#{prest}$/, p0.upcase + prest)
39
+ plural(/#{p0.downcase}(?i)#{prest}$/, p0.downcase + prest)
40
+
41
+ singular(/#{s0.upcase}(?i)#{srest}$/, s0.upcase + srest)
42
+ singular(/#{s0.downcase}(?i)#{srest}$/, s0.downcase + srest)
43
+ singular(/#{p0.upcase}(?i)#{prest}$/, s0.upcase + srest)
44
+ singular(/#{p0.downcase}(?i)#{prest}$/, s0.downcase + srest)
45
+ end
46
+ end
47
+
48
+ def uncountable(singular_and_plural)
49
+ irregular(singular_and_plural, singular_and_plural)
50
+ end
51
+
52
+ end
53
+
54
+ plural(/$/, "s")
55
+ plural(/s$/i, "s")
56
+ plural(/^(ax|test)is$/i, '\1es')
57
+ plural(/(octop|vir)us$/i, '\1i')
58
+ plural(/(octop|vir)i$/i, '\1i')
59
+ plural(/(alias|status)$/i, '\1es')
60
+ plural(/(bu)s$/i, '\1ses')
61
+ plural(/(buffal|tomat)o$/i, '\1oes')
62
+ plural(/([ti])um$/i, '\1a')
63
+ plural(/([ti])a$/i, '\1a')
64
+ plural(/sis$/i, "ses")
65
+ plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
66
+ plural(/(hive)$/i, '\1s')
67
+ plural(/([^aeiouy]|qu)y$/i, '\1ies')
68
+ plural(/(x|ch|ss|sh)$/i, '\1es')
69
+ plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
70
+ plural(/^(m|l)ouse$/i, '\1ice')
71
+ plural(/^(m|l)ice$/i, '\1ice')
72
+ plural(/^(ox)$/i, '\1en')
73
+ plural(/^(oxen)$/i, '\1')
74
+ plural(/(quiz)$/i, '\1zes')
75
+
76
+ singular(/s$/i, "")
77
+ singular(/(ss)$/i, '\1')
78
+ singular(/(n)ews$/i, '\1ews')
79
+ singular(/([ti])a$/i, '\1um')
80
+ singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1sis')
81
+ singular(/(^analy)(sis|ses)$/i, '\1sis')
82
+ singular(/([^f])ves$/i, '\1fe')
83
+ singular(/(hive)s$/i, '\1')
84
+ singular(/(tive)s$/i, '\1')
85
+ singular(/([lr])ves$/i, '\1f')
86
+ singular(/([^aeiouy]|qu)ies$/i, '\1y')
87
+ singular(/(s)eries$/i, '\1eries')
88
+ singular(/(m)ovies$/i, '\1ovie')
89
+ singular(/(x|ch|ss|sh)es$/i, '\1')
90
+ singular(/^(m|l)ice$/i, '\1ouse')
91
+ singular(/(bus)(es)?$/i, '\1')
92
+ singular(/(o)es$/i, '\1')
93
+ singular(/(shoe)s$/i, '\1')
94
+ singular(/(cris|test)(is|es)$/i, '\1is')
95
+ singular(/^(a)x[ie]s$/i, '\1xis')
96
+ singular(/(octop|vir)(us|i)$/i, '\1us')
97
+ singular(/(alias|status)(es)?$/i, '\1')
98
+ singular(/^(ox)en/i, '\1')
99
+ singular(/(vert|ind)ices$/i, '\1ex')
100
+ singular(/(matr)ices$/i, '\1ix')
101
+ singular(/(quiz)zes$/i, '\1')
102
+ singular(/(database)s$/i, '\1')
103
+
104
+ irregular("person", "people")
105
+ irregular("man", "men")
106
+ irregular("child", "children")
107
+ irregular("sex", "sexes")
108
+ irregular("move", "moves")
109
+ irregular("zombie", "zombies")
110
+
111
+ uncountable "equipment"
112
+ uncountable "information"
113
+ uncountable "rice"
114
+ uncountable "money"
115
+ uncountable "species"
116
+ uncountable "series"
117
+ uncountable "fish"
118
+ uncountable "sheep"
119
+ uncountable "jeans"
120
+ uncountable "police"
121
+
122
+ end