lux-fw 0.2.3 → 0.5.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/bin/README.md +33 -0
- data/bin/build_gem +76 -0
- data/bin/cli/config.rb +44 -0
- data/bin/cli/console.rb +61 -0
- data/bin/cli/dbconsole.rb +8 -0
- data/bin/cli/eval.rb +32 -0
- data/bin/cli/generate.rb +88 -0
- data/bin/cli/get.rb +12 -0
- data/bin/cli/new.rb +22 -0
- data/bin/cli/routes.rb +90 -0
- data/bin/cli/secrets.rb +40 -0
- data/bin/cli/server.rb +24 -0
- data/bin/cli/stats.rb +133 -0
- data/bin/lux +24 -65
- data/lib/common/class_attributes.rb +40 -64
- data/lib/common/class_callbacks.rb +34 -51
- data/lib/common/crypt.rb +10 -8
- data/lib/common/free_struct.rb +42 -0
- data/lib/common/hash_with_indifferent_access.rb +1 -1
- data/lib/common/html_tag_builder.rb +26 -2
- data/lib/common/url.rb +58 -40
- data/lib/lux/application/application.rb +290 -117
- data/lib/lux/application/lib/nav.rb +64 -38
- data/lib/lux/application/lib/render.rb +2 -1
- data/lib/lux/cache/cache.rb +87 -62
- data/lib/lux/cache/lib/{ram.rb → memory.rb} +5 -7
- data/lib/lux/cache/lib/null.rb +6 -8
- data/lib/lux/config/config.rb +109 -52
- data/lib/lux/config/lib/plugin.rb +65 -0
- data/lib/lux/config/lib/secrets.rb +48 -0
- data/lib/lux/controller/controller.rb +241 -0
- data/lib/lux/current/current.rb +33 -47
- data/lib/lux/current/lib/session.rb +72 -0
- data/lib/lux/delayed_job/delayed_job.rb +14 -7
- data/lib/lux/delayed_job/lib/memory.rb +7 -5
- data/lib/lux/delayed_job/lib/redis.rb +1 -1
- data/lib/lux/error/error.rb +164 -62
- data/lib/lux/event_bus/event_bus.rb +27 -0
- data/lib/lux/lux.rb +103 -66
- data/lib/lux/mailer/mailer.rb +23 -25
- data/lib/lux/response/lib/file.rb +81 -0
- data/lib/lux/response/lib/header.rb +14 -1
- data/lib/lux/response/response.rb +64 -56
- data/lib/lux/view/cell.rb +102 -0
- data/lib/lux/{helper → view}/helper.rb +39 -23
- data/lib/lux/view/lib/cell_helpers.rb +29 -0
- data/lib/lux/{helper/helpers/mailer_helper.rb → view/lib/helper_modules.rb} +7 -1
- data/lib/lux/{template/template.rb → view/view.rb} +21 -24
- data/lib/lux-fw.rb +4 -2
- data/lib/overload/array.rb +12 -6
- data/lib/overload/blank.rb +0 -1
- data/lib/overload/dir.rb +18 -0
- data/lib/overload/file.rb +1 -6
- data/lib/overload/hash.rb +56 -13
- data/lib/overload/integer.rb +2 -2
- data/lib/overload/it.rb +4 -4
- data/lib/overload/object.rb +37 -8
- data/lib/overload/{r.rb → raise_variants.rb} +23 -4
- data/lib/overload/string.rb +22 -6
- data/misc/demo/app/cells/demo_cell.rb +12 -0
- data/misc/demo/app/controllers/application_controller.rb +7 -0
- data/misc/demo/app/controllers/main/root_controller.rb +9 -0
- data/misc/demo/app/routes.rb +5 -0
- data/misc/demo/config/application.rb +14 -0
- data/misc/demo/config/assets.rb +6 -0
- data/misc/demo/config/environment.rb +7 -0
- data/misc/puma_auto_tune.rb +43 -0
- data/misc/unicorn.rb +37 -0
- data/{lib/lux → plugins}/api/api.rb +46 -29
- data/plugins/api/lib/attr.rb +31 -0
- data/{lib/lux → plugins}/api/lib/dsl.rb +3 -6
- data/{lib/lux → plugins}/api/lib/error.rb +0 -0
- data/{lib/lux → plugins}/api/lib/model_api.rb +51 -12
- data/{lib/lux → plugins}/api/lib/response.rb +31 -17
- data/{bin/cli/am → plugins/db/auto_migrate/auto_migrate.rb} +18 -35
- data/plugins/db/helpers/array_search.rb +27 -0
- data/plugins/db/helpers/before_save_filters.rb +32 -0
- data/plugins/db/helpers/composite_primary_keys.rb +36 -0
- data/plugins/db/helpers/core.rb +94 -0
- data/plugins/db/helpers/dataset_methods.rb +138 -0
- data/plugins/db/helpers/enums_plugin.rb +52 -0
- data/plugins/db/helpers/find_precache.rb +31 -0
- data/plugins/db/helpers/link_objects.rb +84 -0
- data/plugins/db/helpers/schema_checks.rb +83 -0
- data/plugins/db/helpers/typero_adapter.rb +71 -0
- data/plugins/db/logger/config.rb +22 -0
- data/plugins/db/logger/lux_response_adapter.rb +10 -0
- data/plugins/db/paginate/helper.rb +32 -0
- data/plugins/db/paginate/sequel_adapter.rb +23 -0
- data/plugins/exceptions/simple_exception.rb +64 -0
- data/plugins/favicon/favicon.rb +10 -0
- data/plugins/html/html_form.rb +118 -0
- data/plugins/html/html_input.rb +98 -0
- data/plugins/html/html_menu.rb +79 -0
- data/plugins/html/input_types.rb +346 -0
- data/plugins/js_widgets/js_widgets.rb +15 -0
- data/plugins/oauth/lib/facebook.rb +35 -0
- data/plugins/oauth/lib/github.rb +38 -0
- data/plugins/oauth/lib/google.rb +41 -0
- data/plugins/oauth/lib/linkedin.rb +41 -0
- data/plugins/oauth/lib/stackexchange.rb +41 -0
- data/plugins/oauth/lib/twitter.rb +38 -0
- data/plugins/oauth/oauth.rb +42 -0
- data/{lib/common → plugins/policy}/policy.rb +6 -7
- data/tasks/loader.rb +49 -0
- metadata +151 -49
- data/bin/cli/assets +0 -41
- data/bin/cli/console +0 -51
- data/bin/cli/dev +0 -1
- data/bin/cli/eval +0 -24
- data/bin/cli/exceptions +0 -62
- data/bin/cli/generate +0 -86
- data/bin/cli/get +0 -5
- data/bin/cli/nginx +0 -34
- data/bin/cli/production +0 -1
- data/bin/cli/render +0 -18
- data/bin/cli/routes +0 -14
- data/bin/cli/server +0 -4
- data/bin/cli/stat +0 -1
- data/bin/cli/systemd +0 -36
- data/bin/txt/nginx.conf +0 -46
- data/bin/txt/siege-and-puma.txt +0 -3
- data/lib/common/base32.rb +0 -47
- data/lib/common/dynamic_class.rb +0 -28
- data/lib/common/folder_model.rb +0 -50
- data/lib/common/generic_model.rb +0 -62
- data/lib/lux/application/lib/plugs.rb +0 -10
- data/lib/lux/application/lib/route_test.rb +0 -64
- data/lib/lux/cache/lib/memcached.rb +0 -3
- data/lib/lux/cell/cell.rb +0 -261
- data/lib/lux/current/lib/static_file.rb +0 -103
- data/lib/lux/helper/helpers/application_helper.rb +0 -3
- data/lib/lux/helper/helpers/html_helper.rb +0 -3
- data/lib/overload/auto_loader.rb +0 -27
- data/lib/overload/module.rb +0 -10
- data/lib/overload/string_inflections.rb +0 -8
data/bin/lux
CHANGED
@@ -1,16 +1,26 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
2
3
|
|
3
4
|
if File.exists?('lux-fw.gemspec')
|
4
5
|
puts 'Cant run in lux folder'
|
5
6
|
exit
|
6
7
|
end
|
7
8
|
|
9
|
+
require 'thor'
|
8
10
|
require 'colorize'
|
9
11
|
require 'optparse'
|
10
12
|
require 'awesome_print'
|
11
13
|
require 'dotenv'
|
12
14
|
|
13
|
-
|
15
|
+
Dotenv.load
|
16
|
+
|
17
|
+
LUX_ROOT = File.expand_path '../..', __FILE__
|
18
|
+
|
19
|
+
puts 'Lux (%s, v%s)' % [LUX_ROOT, File.read('%s/.version' % LUX_ROOT)] unless ARGV[0]
|
20
|
+
|
21
|
+
###
|
22
|
+
|
23
|
+
module Cli
|
14
24
|
extend self
|
15
25
|
|
16
26
|
def run what
|
@@ -22,76 +32,25 @@ module LuxCli
|
|
22
32
|
puts text.red
|
23
33
|
exit
|
24
34
|
end
|
35
|
+
|
36
|
+
def info text
|
37
|
+
puts '* %s' % text.magenta
|
38
|
+
end
|
25
39
|
end
|
26
40
|
|
27
|
-
|
41
|
+
###
|
28
42
|
|
29
|
-
|
30
|
-
lux_root = File.expand_path '../..', __FILE__
|
43
|
+
trap("SIGINT") { Cli.die 'ctrl+c exit' }
|
31
44
|
|
32
|
-
|
33
|
-
test_root = `bundle show lux-fw`.chomp
|
34
|
-
lux_root = test_root if test_root.include?('lux')
|
35
|
-
end
|
45
|
+
LuxCli = Class.new Thor
|
36
46
|
|
37
|
-
|
47
|
+
Dir['%s/bin/cli/*.rb' % LUX_ROOT].each { |it| load it }
|
38
48
|
|
39
|
-
|
40
|
-
opts.on("-e", "--environment=val", "RACK_ENV enviroment", String) do |v|
|
41
|
-
v = 'production' if v[0,1] == 'p'
|
42
|
-
v = 'development' if v[0,1] == 'd'
|
43
|
-
ENV['RACK_ENV'] = v if v
|
44
|
-
end
|
45
|
-
opts.on("-p", "--port=val", "port (3000)", String) do |v|
|
46
|
-
@port = v.to_i
|
47
|
-
end
|
48
|
-
opts.on("-f", "--flags=val", "CRSL", String) do |v|
|
49
|
-
@flags = v
|
50
|
-
end
|
51
|
-
end.parse!
|
52
|
-
|
53
|
-
commands = {}
|
54
|
-
commands['am'] = 'auto migrate'
|
55
|
-
commands['assets'] = 'precompile assets and genereate mainifest.json'
|
56
|
-
commands['console'] = 'Lux console'
|
57
|
-
commands['dev'] = 'dev on port 3000 with hot reload on code change'
|
58
|
-
commands['eval'] = 'eval code or file'
|
59
|
-
commands['exceptions'] = 'show stored exceptions, last created first'
|
60
|
-
commands['generate'] = 'generates models and views based on templates'
|
61
|
-
commands['get'] = 'get local URL'
|
62
|
-
commands['nginx'] = 'parse and install config/nginx.conf'
|
63
|
-
commands['production'] = 'run puma in production mode'
|
64
|
-
commands['routes'] = 'list routes'
|
65
|
-
commands['render'] = 'render single page'
|
66
|
-
commands['server'] = 'run puma development server'
|
67
|
-
commands['systemd'] = 'parse and install config/systemd.conf'
|
68
|
-
commands['stat'] = 'goaccess stat to public/goaccess.html'
|
69
|
-
# commands['job_que'] = 'process job que with loaded enviroment'
|
70
|
-
|
71
|
-
command = ARGV.shift
|
72
|
-
|
73
|
-
if command
|
74
|
-
for c in commands
|
75
|
-
command = c[0] if c[0] if c[0].start_with?(command)
|
76
|
-
end
|
49
|
+
LuxCli.start ARGV
|
77
50
|
|
78
|
-
|
79
|
-
path = '%s/bin/cli/%s' % [lux_root, command]
|
80
|
-
load path
|
81
|
-
else
|
82
|
-
LuxCli.die "Can't find command [%s]" % command
|
83
|
-
end
|
84
|
-
else
|
85
|
-
puts "\nCommands:"
|
86
|
-
for c in commands
|
87
|
-
# puts " #{c[0].sub(/(\w)/,'[\\1]').ljust(15)} # #{c[1]}"
|
88
|
-
puts " #{c[0].ljust(15)} # #{c[1]}"
|
89
|
-
end
|
51
|
+
rakes = Dir['./Rakefile*'] + Dir['./rakefile*']
|
90
52
|
|
91
|
-
|
92
|
-
puts '
|
93
|
-
puts '
|
94
|
-
puts ''
|
95
|
-
exit
|
53
|
+
if !ARGV[0] && rakes[0]
|
54
|
+
puts 'Or use one of rake tasks'
|
55
|
+
puts ' ' + `rake -T`.gsub($/, "\n ")
|
96
56
|
end
|
97
|
-
|
@@ -1,75 +1,51 @@
|
|
1
|
-
#
|
1
|
+
# Defines class variable
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
def Object.class_attribute name, default=nil, &block
|
4
|
+
raise ArgumentError.new('name must be symbol') unless name.is_a?(Symbol)
|
5
|
+
|
6
|
+
ivar = "@cattr_#{name}"
|
7
|
+
instance_variable_set ivar, block || default
|
8
|
+
|
9
|
+
define_singleton_method('%s=' % name) { |arg| send(name, arg) }
|
10
|
+
define_singleton_method(name) do |arg=:_undefined|
|
11
|
+
# define and set if argument given
|
12
|
+
if arg != :_undefined
|
13
|
+
instance_variable_set ivar, arg
|
14
|
+
return arg
|
15
|
+
end
|
16
|
+
|
17
|
+
# find value and return
|
18
|
+
ancestors.each do |klass|
|
19
|
+
if klass.instance_variable_defined?(ivar)
|
20
|
+
value = klass.instance_variable_get ivar
|
21
|
+
return value.is_a?(Proc) ? instance_exec(&value) : value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
6
26
|
|
7
27
|
# class A
|
8
|
-
#
|
28
|
+
# class_attribute :layout, 'default'
|
29
|
+
# class_attribute(:time) { Time.now }
|
9
30
|
# end
|
31
|
+
|
10
32
|
# class B < A
|
11
|
-
# layout '
|
33
|
+
# layout 'main'
|
12
34
|
# end
|
35
|
+
|
13
36
|
# class C < B
|
37
|
+
# time '11:55'
|
14
38
|
# end
|
15
|
-
# puts A.layout # default
|
16
|
-
# puts B.layout # l B
|
17
|
-
# puts C.layout # l B
|
18
39
|
|
19
|
-
#
|
20
|
-
#
|
40
|
+
# for func in [:layout, :time]
|
41
|
+
# for klass in [A, B, C]
|
42
|
+
# puts "> %s = %s" % ["#{klass}.#{func}".ljust(8), klass.send(func)]
|
43
|
+
# end
|
21
44
|
# end
|
22
45
|
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
# defines class variable
|
31
|
-
def define klass, name, default=nil, &block
|
32
|
-
raise ArgumentError, 'name must be symbol' unless name.class == Symbol
|
33
|
-
|
34
|
-
default ||= block if block
|
35
|
-
|
36
|
-
::ClassAttributes::CA_DEFAULTS[name] = { 'Object'=>default }
|
37
|
-
|
38
|
-
klass.define_singleton_method('%s=' % name) { |*args| send name, *args}
|
39
|
-
klass.define_singleton_method(name) do |*args|
|
40
|
-
root = ::ClassAttributes::CA_DEFAULTS[name]
|
41
|
-
|
42
|
-
# set and return if argument defined
|
43
|
-
return root[to_s] = args[0] if args.length > 0
|
44
|
-
|
45
|
-
# find value and return
|
46
|
-
ancestors.map(&:to_s).each do |el|
|
47
|
-
value = root[el]
|
48
|
-
if value || el == 'Object'
|
49
|
-
value = instance_exec(&value) if value.is_a?(Proc)
|
50
|
-
return value
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# defines class variable in current lux thread
|
57
|
-
# User.current = @user
|
58
|
-
# def current klass, name
|
59
|
-
# klass.class.send(:define_method, name) do |*args|
|
60
|
-
# Thread.current[:lux] ||= {}
|
61
|
-
# Thread.current[:lux]['%s-%s' % [klass, name]]
|
62
|
-
# end
|
63
|
-
|
64
|
-
# klass.class.send(:define_method, '%s=' % name) do |value|
|
65
|
-
# Thread.current[:lux] ||= {}
|
66
|
-
# Thread.current[:lux]['%s-%s' % [klass, name]] = value
|
67
|
-
# end
|
68
|
-
# end
|
69
|
-
end
|
70
|
-
|
71
|
-
class Object
|
72
|
-
def class_attribute name, default=nil, &block
|
73
|
-
ClassAttributes.define self, name, default, &block
|
74
|
-
end
|
75
|
-
end
|
46
|
+
# # > A.layout = default
|
47
|
+
# # > B.layout = main
|
48
|
+
# # > C.layout = main
|
49
|
+
# # > A.time = 2018-10-28 18:07:33 +0100
|
50
|
+
# # > B.time = 2018-10-28 18:07:33 +0100
|
51
|
+
# # > C.time = 11:55
|
@@ -1,64 +1,47 @@
|
|
1
|
-
#
|
1
|
+
# Rails style callbacks
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# then to execute
|
7
|
-
# instance_object = SomeClass.new
|
8
|
-
# ClassCallbacks.execute(instance_object, :before)
|
9
|
-
#
|
3
|
+
# for controllers, execute from AppController to MainController
|
4
|
+
# class_callback :before
|
10
5
|
# before do
|
11
|
-
#
|
6
|
+
# ...
|
12
7
|
# end
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@@pointers = {}
|
22
|
-
|
23
|
-
def add klass, unique_id, action, method
|
24
|
-
klass = klass.to_s
|
25
|
-
key = Crypt.sha1(unique_id)
|
26
|
-
|
27
|
-
@@pointers[key] = method
|
28
|
-
|
29
|
-
@@methods[klass] ||= {}
|
30
|
-
@@methods[klass][action] ||= []
|
31
|
-
@@methods[klass][action].tap { |it| it.push(key) unless it.include?(key) }
|
8
|
+
# before :method_name
|
9
|
+
# instance = new
|
10
|
+
# instance.class_callback :before,
|
11
|
+
# instance.class_callback :before, arg
|
12
|
+
|
13
|
+
class Object
|
14
|
+
def class_callback name, arg=nil
|
15
|
+
Object.class_callback name, self, arg
|
32
16
|
end
|
33
17
|
|
34
|
-
def
|
35
|
-
|
18
|
+
def self.class_callback name, context=nil, arg=nil
|
19
|
+
ivar = "@ccallbacks_#{name}"
|
36
20
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
next unless actions = @@methods.dig(name, action)
|
21
|
+
unless context
|
22
|
+
define_singleton_method(name) do |method_name=nil, &block|
|
23
|
+
ref = caller[0].split(':in ').first
|
41
24
|
|
42
|
-
|
43
|
-
|
44
|
-
object ? instance_object.send(el, object) : instance_object.send(el)
|
45
|
-
else
|
46
|
-
object ? instance_object.instance_exec(object, &el) : instance_object.instance_exec(&el)
|
47
|
-
end
|
25
|
+
self.instance_variable_set(ivar, {}) unless instance_variable_defined?(ivar)
|
26
|
+
self.instance_variable_get(ivar)[ref] = method_name || block
|
48
27
|
end
|
49
|
-
end
|
50
|
-
end
|
51
28
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
29
|
+
else
|
30
|
+
list = context.respond_to?(:const_missing) ? context.ancestors : context.class.ancestors
|
31
|
+
list = list.slice 0, list.index(Object) if list.index(Object)
|
32
|
+
|
33
|
+
list.reverse.each do |klass|
|
34
|
+
if klass.instance_variable_defined?(ivar)
|
35
|
+
mlist = klass.instance_variable_get(ivar).values
|
36
|
+
mlist.each do |m|
|
37
|
+
if m.is_a?(Symbol)
|
38
|
+
context.send m
|
39
|
+
else
|
40
|
+
context.instance_exec arg, &m
|
41
|
+
end
|
42
|
+
end
|
56
43
|
end
|
57
|
-
|
58
|
-
def self.#{action}(proc=nil, &block)
|
59
|
-
ClassCallbacks.add(self, caller[0], :#{action}, proc || block)
|
60
|
-
end
|
61
|
-
]
|
44
|
+
end
|
62
45
|
end
|
63
46
|
end
|
64
47
|
end
|
data/lib/common/crypt.rb
CHANGED
@@ -15,7 +15,7 @@ module Crypt
|
|
15
15
|
ALGORITHM = 'HS512'
|
16
16
|
|
17
17
|
def secret
|
18
|
-
ENV.fetch('SECRET') {
|
18
|
+
ENV.fetch('SECRET') { Lux.config.secret } || die('Lux.config.secret not set')
|
19
19
|
end
|
20
20
|
|
21
21
|
def base64 str
|
@@ -44,22 +44,24 @@ module Crypt
|
|
44
44
|
|
45
45
|
# Crypt.encrypt('secret')
|
46
46
|
# Crypt.encrypt('secret', ttl:1.hour, password:'pa$$w0rd')
|
47
|
-
def encrypt
|
48
|
-
opts
|
47
|
+
def encrypt data, opts={}
|
48
|
+
opts = opts.to_opts(:ttl, :password)
|
49
|
+
payload = { data:data }
|
50
|
+
payload[:ttl] = Time.now.to_i + opts.ttl.to_i if opts.ttl
|
49
51
|
|
50
|
-
payload = { data:data }
|
51
|
-
payload[:ttl] = Time.now.to_i + opts.ttl if opts.ttl
|
52
52
|
JWT.encode payload, secret+opts.password.to_s, ALGORITHM
|
53
53
|
end
|
54
54
|
|
55
55
|
# Crypt.decrypt('secret')
|
56
56
|
# Crypt.decrypt('secret', password:'pa$$w0rd')
|
57
|
-
def decrypt
|
58
|
-
opts = opts.to_opts
|
57
|
+
def decrypt token, opts={}
|
58
|
+
opts = opts.to_opts(:password, :ttl)
|
59
59
|
|
60
60
|
token_data = JWT.decode token, secret+opts.password.to_s, true, { :algorithm => ALGORITHM }
|
61
61
|
data = token_data[0]
|
62
|
-
|
62
|
+
|
63
|
+
raise "Crypted data expired before #{Time.now.to_i - data['ttl']} seconds" if data['ttl'] && data['ttl'] < Time.now.to_i
|
64
|
+
|
63
65
|
data['data']
|
64
66
|
end
|
65
67
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Convert hash to object with methods
|
2
|
+
# o = FreeStruct.new name: 'a'
|
3
|
+
# o.name -> 'a'
|
4
|
+
# o[:name] -> 'a'
|
5
|
+
# o.name = 'b'
|
6
|
+
# o.name 'b'
|
7
|
+
# o.name -> 'b'
|
8
|
+
# o.name = nil
|
9
|
+
# o.name -> nil
|
10
|
+
# o.title -> raises error
|
11
|
+
|
12
|
+
class FreeStruct
|
13
|
+
def initialize hash
|
14
|
+
@keys = hash.keys
|
15
|
+
|
16
|
+
hash.each do |key, value|
|
17
|
+
ivar = "@#{key}"
|
18
|
+
|
19
|
+
instance_variable_set ivar, value
|
20
|
+
|
21
|
+
define_singleton_method(key) do
|
22
|
+
instance_variable_get ivar
|
23
|
+
end
|
24
|
+
|
25
|
+
define_singleton_method "#{key}=" do |val|
|
26
|
+
instance_variable_set ivar, val
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def [] key
|
32
|
+
send key
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_h
|
36
|
+
@keys.inject({}) do |out, key|
|
37
|
+
out[key] = send(key)
|
38
|
+
out
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -3,6 +3,7 @@
|
|
3
3
|
# n.li do |n|
|
4
4
|
# n.i '.arrow'
|
5
5
|
# n.span num
|
6
|
+
# n.id
|
6
7
|
# end
|
7
8
|
# end
|
8
9
|
# end
|
@@ -17,8 +18,15 @@ class HtmlTagBuilder
|
|
17
18
|
# tag :div, { 'class'=>'iform' } do
|
18
19
|
def tag name=nil, opts={}, data=nil
|
19
20
|
# covert tag.a '.foo.bar' to class names
|
20
|
-
|
21
|
-
|
21
|
+
# covert tag.a '#id' to id names
|
22
|
+
if opts.is_a?(String)
|
23
|
+
case opts[0,1]
|
24
|
+
when '.'
|
25
|
+
opts = { class: opts.sub('.', '').gsub('.', ' ') }
|
26
|
+
when '#'
|
27
|
+
opts = { id: opts.sub('#', '') }
|
28
|
+
end
|
29
|
+
else
|
22
30
|
end
|
23
31
|
|
24
32
|
# fix data and opts unless opts is Hash
|
@@ -50,6 +58,12 @@ class HtmlTagBuilder
|
|
50
58
|
text ||= '' unless ['input', 'img', 'meta', 'link', 'hr', 'br'].include?(node.to_s)
|
51
59
|
text ? %{<#{node}#{opts}>#{text}</#{node}>} : %{<#{node}#{opts} />}
|
52
60
|
end
|
61
|
+
|
62
|
+
# tag.div(class: 'klasa') do -> tag.('klasa') do
|
63
|
+
def call class_name, &block
|
64
|
+
tag(:div, { class: class_name }, &block)
|
65
|
+
end
|
66
|
+
|
53
67
|
end
|
54
68
|
|
55
69
|
###
|
@@ -60,6 +74,16 @@ class HtmlTagBuilder
|
|
60
74
|
@data = []
|
61
75
|
end
|
62
76
|
|
77
|
+
# push data to stack
|
78
|
+
def push data
|
79
|
+
@data.push data
|
80
|
+
end
|
81
|
+
|
82
|
+
# n.div(class: 'klasa') do -> n.('klasa') do
|
83
|
+
def call class_name, &block
|
84
|
+
@data.push self.class.tag(:div, { class: class_name }, &block)
|
85
|
+
end
|
86
|
+
|
63
87
|
# forward to class
|
64
88
|
def method_missing tag_name, *args, &block
|
65
89
|
@data.push self.class.tag(tag_name, args[0], args[1], &block)
|
data/lib/common/url.rb
CHANGED
@@ -30,14 +30,14 @@ class Url
|
|
30
30
|
b.url
|
31
31
|
end
|
32
32
|
|
33
|
-
def qs name, value
|
33
|
+
def qs name, value
|
34
34
|
current.qs(name, value).relative
|
35
35
|
end
|
36
36
|
|
37
37
|
# for search
|
38
38
|
# Url.prepare_qs(:q) -> /foo?bar=1&q=
|
39
39
|
def prepare_qs name
|
40
|
-
url = current.
|
40
|
+
url = current.delete(name).relative
|
41
41
|
url += url.index('?') ? '&' : '?'
|
42
42
|
"#{url}#{name}="
|
43
43
|
end
|
@@ -54,26 +54,28 @@ class Url
|
|
54
54
|
###
|
55
55
|
|
56
56
|
def initialize url
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
url, qs_part = url.split('?', 2)
|
58
|
+
|
59
|
+
@qs = qs_part.to_s.split('&').inject({}) do |qs, el|
|
60
|
+
parts = el.split('=', 2)
|
61
|
+
qs[parts[0]] = Url.unescape parts[1]
|
62
|
+
qs
|
62
63
|
end
|
63
64
|
|
64
|
-
|
65
|
-
|
65
|
+
if url =~ %r{://}
|
66
|
+
@proto, _, @domain, @path = url.split '/', 4
|
67
|
+
|
68
|
+
@proto = @proto.sub(':', '')
|
66
69
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
@domain, @port = @domain.split(':', 2)
|
71
|
+
@port = nil if @port == '80' || @port.blank?
|
72
|
+
|
73
|
+
@domain_parts = @domain.split('.').reverse.map(&:downcase)
|
74
|
+
else
|
75
|
+
@path = url.to_s.sub(%r{^/}, '')
|
76
|
+
end
|
73
77
|
|
74
|
-
@path =
|
75
|
-
@proto = @elms[0].split(':').first.downcase
|
76
|
-
@port = domain_and_port[1] ? domain_and_port[1].to_i : 80
|
78
|
+
@path = '' if @path.blank?
|
77
79
|
end
|
78
80
|
|
79
81
|
def domain what=nil
|
@@ -85,11 +87,12 @@ class Url
|
|
85
87
|
@domain_parts.slice(0,2).reverse.join '.'
|
86
88
|
end
|
87
89
|
|
88
|
-
def subdomain name
|
90
|
+
def subdomain name=nil
|
89
91
|
if name
|
90
92
|
@domain_parts[2] = name
|
91
93
|
return self
|
92
94
|
end
|
95
|
+
|
93
96
|
@domain_parts.drop(2).reverse.join('.').or nil
|
94
97
|
end
|
95
98
|
|
@@ -101,19 +104,17 @@ class Url
|
|
101
104
|
@domain_parts.reverse.join '.'
|
102
105
|
end
|
103
106
|
|
104
|
-
def host_with_port
|
105
|
-
%[#{proto}://#{host}#{port == 80 ? '' : ":#{port}"}]
|
106
|
-
end
|
107
|
-
|
108
107
|
def query
|
109
108
|
@query
|
110
109
|
end
|
111
110
|
|
112
111
|
def path val=nil
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
112
|
+
if val
|
113
|
+
@path = val.sub /^\//, ''
|
114
|
+
return self
|
115
|
+
else
|
116
|
+
'/' + @path
|
117
|
+
end
|
117
118
|
end
|
118
119
|
|
119
120
|
def delete *keys
|
@@ -125,13 +126,13 @@ class Url
|
|
125
126
|
@hash = "##{val}"
|
126
127
|
end
|
127
128
|
|
128
|
-
def qs name, value
|
129
|
-
if value
|
129
|
+
def qs name, value=:_nil
|
130
|
+
if value != :_nil
|
130
131
|
@qs[name.to_s] = value
|
132
|
+
self
|
131
133
|
elsif name
|
132
|
-
@qs
|
134
|
+
@qs[name.to_s]
|
133
135
|
end
|
134
|
-
self
|
135
136
|
end
|
136
137
|
|
137
138
|
def namespace data
|
@@ -141,21 +142,16 @@ class Url
|
|
141
142
|
|
142
143
|
def locale what
|
143
144
|
elms = @path.split('/')
|
145
|
+
|
144
146
|
if elms[0] && Locale.all.index(elms[0].to_s)
|
145
147
|
elms[0] = what
|
146
148
|
else
|
147
149
|
elms.unshift what
|
148
150
|
end
|
151
|
+
|
149
152
|
@path = elms.join('/')
|
150
|
-
self
|
151
|
-
end
|
152
153
|
|
153
|
-
|
154
|
-
ret = []
|
155
|
-
if @qs.keys.length > 0
|
156
|
-
ret.push '?' + @qs.keys.sort.map{ |key| "#{key}=#{Url.escape(@qs[key].to_s)}" }.join('&')
|
157
|
-
end
|
158
|
-
ret.join('')
|
154
|
+
self
|
159
155
|
end
|
160
156
|
|
161
157
|
def url
|
@@ -167,7 +163,29 @@ class Url
|
|
167
163
|
end
|
168
164
|
|
169
165
|
def to_s
|
170
|
-
domain
|
166
|
+
@domain ? url : relative
|
167
|
+
end
|
168
|
+
|
169
|
+
def [] key
|
170
|
+
@qs[key.to_s]
|
171
|
+
end
|
172
|
+
|
173
|
+
def []= key, value
|
174
|
+
@qs[key.to_s] = value
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
|
179
|
+
def qs_val
|
180
|
+
ret = []
|
181
|
+
if @qs.keys.length > 0
|
182
|
+
ret.push '?' + @qs.keys.sort.map{ |key| "#{key}=#{Url.escape(@qs[key].to_s)}" }.join('&')
|
183
|
+
end
|
184
|
+
ret.join('')
|
185
|
+
end
|
186
|
+
|
187
|
+
def host_with_port
|
188
|
+
%[#{proto}://#{host}#{@port.present? ? ":#{@port}" : ''}]
|
171
189
|
end
|
172
190
|
|
173
191
|
end
|