lux-fw 0.1.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.version +1 -0
- data/bin/cli/am +250 -0
- data/bin/cli/assets +37 -0
- data/bin/cli/console +50 -0
- data/bin/cli/dev +1 -0
- data/bin/cli/eval +15 -0
- data/bin/cli/exceptions +62 -0
- data/bin/cli/generate +82 -0
- data/bin/cli/get +5 -0
- data/bin/cli/nginx +28 -0
- data/bin/cli/production +1 -0
- data/bin/cli/routes +12 -0
- data/bin/cli/server +1 -0
- data/bin/cli/stat +1 -0
- data/bin/forever +65 -0
- data/bin/job_que +39 -0
- data/bin/lux +87 -0
- data/bin/txt/nginx.conf +29 -0
- data/bin/txt/siege-and-puma.txt +3 -0
- data/lib/common/base32.rb +47 -0
- data/lib/common/before_and_after.rb +71 -0
- data/lib/common/class_attributes.rb +66 -0
- data/lib/common/class_method_params.rb +94 -0
- data/lib/common/crypt.rb +66 -0
- data/lib/common/folder_model.rb +50 -0
- data/lib/common/generic_model.rb +62 -0
- data/lib/common/policy.rb +54 -0
- data/lib/common/string_base.rb +49 -0
- data/lib/common/url.rb +171 -0
- data/lib/lux/api/api.rb +150 -0
- data/lib/lux/api/lib/application_api.rb +19 -0
- data/lib/lux/api/lib/doc_builder.rb +18 -0
- data/lib/lux/api/lib/dsl.rb +73 -0
- data/lib/lux/api/lib/model_api.rb +145 -0
- data/lib/lux/api/lib/rescue.rb +18 -0
- data/lib/lux/cache/cache.rb +71 -0
- data/lib/lux/cache/lib/memcached.rb +3 -0
- data/lib/lux/cache/lib/null.rb +23 -0
- data/lib/lux/cache/lib/ram.rb +38 -0
- data/lib/lux/cell/cell.rb +260 -0
- data/lib/lux/config/config.rb +88 -0
- data/lib/lux/controller/controller.rb +185 -0
- data/lib/lux/controller/lib/nav.rb +77 -0
- data/lib/lux/controller/lib/plugs.rb +10 -0
- data/lib/lux/delayed_job/delayed_job.rb +44 -0
- data/lib/lux/delayed_job/lib/memory.rb +14 -0
- data/lib/lux/delayed_job/lib/nsq.rb +3 -0
- data/lib/lux/delayed_job/lib/postgre.rb +6 -0
- data/lib/lux/delayed_job/lib/redis.rb +19 -0
- data/lib/lux/error/error.rb +75 -0
- data/lib/lux/helper/helper.rb +109 -0
- data/lib/lux/html/html.rb +3 -0
- data/lib/lux/html/lib/form.rb +81 -0
- data/lib/lux/html/lib/input.rb +71 -0
- data/lib/lux/html/lib/input_types.rb +277 -0
- data/lib/lux/lux.rb +164 -0
- data/lib/lux/mailer/mailer.rb +73 -0
- data/lib/lux/page/lib/encrypt_params.rb +44 -0
- data/lib/lux/page/lib/flash.rb +49 -0
- data/lib/lux/page/lib/static_file.rb +97 -0
- data/lib/lux/page/page.rb +271 -0
- data/lib/lux/rescue_from/rescue_from.rb +61 -0
- data/lib/lux/template/template.rb +95 -0
- data/lib/lux-fw.rb +48 -0
- data/lib/overload/array.rb +52 -0
- data/lib/overload/blank.rb +62 -0
- data/lib/overload/date.rb +58 -0
- data/lib/overload/file.rb +14 -0
- data/lib/overload/hash.rb +86 -0
- data/lib/overload/hash_wia.rb +282 -0
- data/lib/overload/inflections.rb +199 -0
- data/lib/overload/integer.rb +19 -0
- data/lib/overload/module.rb +10 -0
- data/lib/overload/nil.rb +8 -0
- data/lib/overload/object.rb +77 -0
- data/lib/overload/string.rb +89 -0
- data/lib/overload/string_inflections.rb +7 -0
- data/lib/overload/struct.rb +5 -0
- data/lib/plugins/assets/assets_plug.rb +26 -0
- data/lib/plugins/assets/helper_module_adapter.rb +49 -0
- data/lib/plugins/assets/init.rb +4 -0
- data/lib/plugins/db_helpers/array_and_hstore.rb +64 -0
- data/lib/plugins/db_helpers/arrays_and_tags.rb +23 -0
- data/lib/plugins/db_helpers/before_save.rb +44 -0
- data/lib/plugins/db_helpers/cached_find_by.rb +45 -0
- data/lib/plugins/db_helpers/class_and_instance.rb +120 -0
- data/lib/plugins/db_helpers/dataset_plugin.rb +101 -0
- data/lib/plugins/db_helpers/filter_wrappers.rb +21 -0
- data/lib/plugins/db_helpers/link_plugin.rb +95 -0
- data/lib/plugins/db_helpers/localize_plugin.rb +57 -0
- data/lib/plugins/db_helpers/primary_keys.rb +36 -0
- data/lib/plugins/db_helpers/typero_attributes.rb +69 -0
- data/lib/plugins/db_logger/init.rb +18 -0
- data/lib/plugins/db_logger/lux_response_adapter.rb +9 -0
- data/lib/plugins/paginate/helper.rb +32 -0
- data/lib/plugins/paginate/sequel_adapter.rb +18 -0
- data/lib/vendor/mini_assets/mini_asset/base.rb +167 -0
- data/lib/vendor/mini_assets/mini_asset/css.rb +38 -0
- data/lib/vendor/mini_assets/mini_asset/js.rb +38 -0
- data/lib/vendor/mini_assets/mini_asset.rb +31 -0
- data/lib/vendor/oauth/lib/facebook.rb +35 -0
- data/lib/vendor/oauth/lib/github.rb +37 -0
- data/lib/vendor/oauth/lib/google.rb +41 -0
- data/lib/vendor/oauth/lib/linkedin.rb +41 -0
- data/lib/vendor/oauth/lib/stackexchange.rb +37 -0
- data/lib/vendor/oauth/lib/twitter.rb +41 -0
- data/lib/vendor/oauth/oauth.rb +46 -0
- metadata +334 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rescue from errors
|
4
|
+
#
|
5
|
+
# in some class
|
6
|
+
# Lux::RescueFrom.define(self) -> defines rescue_from method in class
|
7
|
+
#
|
8
|
+
# to add
|
9
|
+
# rescue_from(UnauthorizedError) { ... }
|
10
|
+
#
|
11
|
+
# and to resolve in the end
|
12
|
+
# @@rescue_from_ivar.call { main }
|
13
|
+
|
14
|
+
class Lux::RescueFrom
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def define(klass)
|
18
|
+
ClassAttributes.define klass, :rescue_from_hash
|
19
|
+
|
20
|
+
klass.class_eval %[
|
21
|
+
@@rescue_from_ivar = Lux::RescueFrom.new
|
22
|
+
def self.rescue_from(name, &block)
|
23
|
+
@@rescue_from_ivar.add(name, &block)
|
24
|
+
end
|
25
|
+
]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
###
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@rescues = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def add(name, &block)
|
36
|
+
die ":#{name} is not allowed rescue name, only allowed are :default and :allways" if name.is_symbol? && ![:default, :allways].index(name)
|
37
|
+
@rescues[name.to_s] = block
|
38
|
+
end
|
39
|
+
|
40
|
+
def call
|
41
|
+
begin
|
42
|
+
yield
|
43
|
+
rescue Exception => e
|
44
|
+
raise e unless Lux.page
|
45
|
+
|
46
|
+
return if Lux.page.body && Lux.page.status
|
47
|
+
|
48
|
+
if proc = @rescues[e.class.to_s]
|
49
|
+
proc.call(e.message)
|
50
|
+
elsif @rescues['default'] # catch them all
|
51
|
+
@rescues['default'].call(e.message)
|
52
|
+
else
|
53
|
+
raise e
|
54
|
+
end
|
55
|
+
|
56
|
+
@rescues['allways'].call(e.message) if @rescues['allways']
|
57
|
+
|
58
|
+
Lux.page.status e.class
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Lux::Template
|
4
|
+
@@template_cache = {}
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def render_with_layout template, opts={}, helper=nil
|
8
|
+
new(template, opts, helper).render_with_layout
|
9
|
+
end
|
10
|
+
|
11
|
+
def render_part template, opts={}, helper=nil
|
12
|
+
new(template, opts, helper).render_part
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize template, opts={}, helper=nil
|
17
|
+
template = template.sub(/^[^\w]+/, '')
|
18
|
+
@original_template = template
|
19
|
+
@opts = opts
|
20
|
+
@helper = helper
|
21
|
+
|
22
|
+
mutex = Mutex.new
|
23
|
+
|
24
|
+
if Lux.config(:auto_code_reload) && !Lux.thread[:template_cache]
|
25
|
+
Lux.thread[:template_cache] = true
|
26
|
+
mutex.synchronize { @@template_cache = {} }
|
27
|
+
end
|
28
|
+
|
29
|
+
if ref = @@template_cache[template]
|
30
|
+
@tilt, @template = *ref
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
34
|
+
for dir in ['./app/views']
|
35
|
+
for ext in ['haml', 'erb']
|
36
|
+
next if @template
|
37
|
+
test = "#{dir}/#{template}.#{ext}"
|
38
|
+
@template = test if File.exists?(test)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
unless @template
|
43
|
+
err = caller.reject{ |l| l =~ %r{(/lux/|/gems/)} }.map{ |l| el=l.to_s.split(Lux.root.to_s); el[1] || l }.join("\n")
|
44
|
+
Lux.error %[Lux::Template "#{template}.{erb,haml}" not found\n\n#{err}]
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
|
48
|
+
begin
|
49
|
+
mutex.synchronize do
|
50
|
+
# @tilt = Tilt.new(@template, ugly:true, escape_html: false)
|
51
|
+
@tilt = Tilt.new(@template, escape_html: false)
|
52
|
+
@@template_cache[template] = [@tilt, @template]
|
53
|
+
end
|
54
|
+
rescue
|
55
|
+
Lux.error("#{$!.message}\n\nTemplate: #{@template}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def render_part
|
60
|
+
base_class = @helper ? @helper.to_s : @template.split('/')[3]
|
61
|
+
base_class = nil if base_class.index('.')
|
62
|
+
base_class ||= Module.new
|
63
|
+
|
64
|
+
# global thread safe reference pointer to last temaplte rendered
|
65
|
+
# we nned this for inline template render
|
66
|
+
Lux.thread[:last_template_path] = @template.sub('/app/views','').sub(/\/[^\/]+$/,'').sub(/^\./,'')
|
67
|
+
|
68
|
+
Lux.page.files_in_use.push @template
|
69
|
+
|
70
|
+
helper = Lux::Helper.for(base_class, @opts)
|
71
|
+
data = nil
|
72
|
+
speed = Lux.speed do
|
73
|
+
data = Lux::Error.try %[Lux::Template "#{@template}" render error] do
|
74
|
+
@tilt.render(helper) do
|
75
|
+
yield if block_given?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
Lux.log " #{@template.split('app/views/').last}, #{speed}"
|
81
|
+
|
82
|
+
data
|
83
|
+
end
|
84
|
+
|
85
|
+
def render_with_layout
|
86
|
+
@part_data = render_part
|
87
|
+
layout_path = "#{@original_template.split('/')[0]}/layout"
|
88
|
+
Lux::Template.new(layout_path, @opts).render_part do
|
89
|
+
@part_data
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
data/lib/lux-fw.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Gem.loaded_specs['lux-fw'].runtime_dependencies.each do |dep|
|
2
|
+
# require case dep.name
|
3
|
+
# when 'sequel_pg'; 'sequel'
|
4
|
+
# when 'hamlit-block'; 'hamlit/block'
|
5
|
+
# else dep.name
|
6
|
+
# end
|
7
|
+
# end
|
8
|
+
|
9
|
+
require 'awesome_print'
|
10
|
+
require 'as-duration'
|
11
|
+
require 'colorize'
|
12
|
+
require 'jwt'
|
13
|
+
require 'fast_blank'
|
14
|
+
require 'hamlit'
|
15
|
+
require 'hamlit/block'
|
16
|
+
require 'hashie'
|
17
|
+
require 'rack'
|
18
|
+
require 'sequel'
|
19
|
+
|
20
|
+
require_relative './overload/object'
|
21
|
+
|
22
|
+
die 'Lux error: RACK_ENV is not defined' unless ENV['RACK_ENV']
|
23
|
+
die "Unsupported RACK_ENV [#{ENV['RACK_ENV']}]" unless ['production', 'development', 'test'].index(ENV['RACK_ENV'])
|
24
|
+
|
25
|
+
Encoding.default_internal = Encoding.default_external = 'utf-8'
|
26
|
+
|
27
|
+
Sequel.extension :inflector, :string_date_time
|
28
|
+
Sequel::Model.plugin :after_initialize, :def_dataset_method
|
29
|
+
Sequel.database_timezone = :utc
|
30
|
+
|
31
|
+
# load basic lux libs
|
32
|
+
require_relative './lux/lux'
|
33
|
+
|
34
|
+
# load all lux libs
|
35
|
+
[:overload, :common, :vendor, :lux].each do |f|
|
36
|
+
Lux::Config.require_all Lux.fw_root.join('./lib/%s' % f)
|
37
|
+
end
|
38
|
+
|
39
|
+
# load Tilt parsers
|
40
|
+
Tilt.register Tilt::ERBTemplate, 'erb'
|
41
|
+
Tilt.register Hamlit::Block::Template, 'haml'
|
42
|
+
|
43
|
+
# ensure we are not loading lux in lux folder
|
44
|
+
if Lux.root != Lux.fw_root
|
45
|
+
# create folders if needed
|
46
|
+
['./log', './tmp'].each { |d| `mkdir #{d}` unless Dir.exist?(d) }
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
def to_csv
|
4
|
+
ret = []
|
5
|
+
for row in self
|
6
|
+
add = []
|
7
|
+
for el in row
|
8
|
+
add << '"'+el.to_s.gsub(/\s+/,' ').gsub(/"/,"''")+'"'
|
9
|
+
end
|
10
|
+
ret.push(add.join(';'))
|
11
|
+
end
|
12
|
+
ret.join("\n")
|
13
|
+
end
|
14
|
+
|
15
|
+
def wrap(name, opts={})
|
16
|
+
map{ |el| opts.tag(name, opts) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def last=(what)
|
20
|
+
self[self.length-1] = what
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_sentence(opts={})
|
24
|
+
opts[:words_connector] ||= ', '
|
25
|
+
opts[:two_words_connector] ||= ' and '
|
26
|
+
opts[:last_word_connector] ||= ', and '
|
27
|
+
|
28
|
+
len = self.length
|
29
|
+
|
30
|
+
return '' if len == 0
|
31
|
+
return self[0] if len == 1
|
32
|
+
return self.join(opts[:two_words_connector]) if len == 2
|
33
|
+
|
34
|
+
last_word = self.pop
|
35
|
+
|
36
|
+
self.join(opts[:words_connector]) + opts[:last_word_connector] + last_word
|
37
|
+
end
|
38
|
+
|
39
|
+
# toggle element in array and return true when added
|
40
|
+
def toggle(element)
|
41
|
+
self.uniq!
|
42
|
+
self.compact!
|
43
|
+
if self.include?(element)
|
44
|
+
self.delete(element)
|
45
|
+
false
|
46
|
+
else
|
47
|
+
self.push(element)
|
48
|
+
true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# partialy extracted from
|
2
|
+
# https://github.com/rails/rails/blob/5-0-stable/activesupport/lib/active_support/core_ext/object/blank.rb
|
3
|
+
|
4
|
+
class Object
|
5
|
+
def blank?
|
6
|
+
!self
|
7
|
+
end
|
8
|
+
|
9
|
+
def empty?
|
10
|
+
blank?
|
11
|
+
end
|
12
|
+
|
13
|
+
def present?
|
14
|
+
!blank?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class NilClass
|
19
|
+
def blank?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class FalseClass
|
25
|
+
def blank?
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class TrueClass
|
31
|
+
def blank?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Array
|
37
|
+
def blank?
|
38
|
+
self.length == 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Hash
|
43
|
+
def blank?
|
44
|
+
self.keys.length == 0
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Numeric
|
49
|
+
def blank?
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Time
|
55
|
+
def blank?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class String
|
61
|
+
# gem 'fast_blank'
|
62
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module TimeOptions
|
2
|
+
def short
|
3
|
+
strftime("%Y-%m-%d")
|
4
|
+
end
|
5
|
+
|
6
|
+
def long
|
7
|
+
strftime("%Y-%m-%d %H:%M")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Time
|
12
|
+
include TimeOptions
|
13
|
+
|
14
|
+
class << self
|
15
|
+
|
16
|
+
# humanize_seconds(61) -> 1min 1sec
|
17
|
+
# humanize_seconds(1111) -> 18min 31sec
|
18
|
+
def humanize_seconds(secs)
|
19
|
+
return '-' unless secs
|
20
|
+
secs = secs.to_i
|
21
|
+
[[60, :sec], [60, :min], [24, :hrs], [356, :days], [1000, :years]].map{ |count, name|
|
22
|
+
if secs > 0
|
23
|
+
secs, n = secs.divmod(count)
|
24
|
+
"#{n.to_i}#{name}"
|
25
|
+
end
|
26
|
+
}.compact.reverse.slice(0,2).join(' ')
|
27
|
+
end
|
28
|
+
|
29
|
+
def ago(start_time, end_time=nil)
|
30
|
+
end_time ||= Time.now
|
31
|
+
time_diff = end_time.to_i - start_time.to_i
|
32
|
+
|
33
|
+
in_past = time_diff > 0 ? true : false
|
34
|
+
time_diff = time_diff.abs
|
35
|
+
|
36
|
+
d_minutes = (time_diff / 60).round rescue 0
|
37
|
+
d_hours = (time_diff / (60 * 60)).round rescue 0
|
38
|
+
d_days = (time_diff / (60*60 * 24)).round rescue 0
|
39
|
+
d_months = (time_diff / (60*60*24 * 30)).round rescue 0
|
40
|
+
d_years = (time_diff / (60*60*24*30 * 12)).round rescue 0
|
41
|
+
|
42
|
+
return (in_past ? 'few sec ago' : 'in few seconds') if time_diff < 10
|
43
|
+
return (in_past ? 'less than min ago' : 'in less then a minute') if time_diff < 60
|
44
|
+
|
45
|
+
template = in_past ? '%s ago' : 'in %s'
|
46
|
+
|
47
|
+
return template % d_minutes.pluralize('min') if d_minutes < 60
|
48
|
+
return template % d_hours.pluralize('hour') if d_hours < 24
|
49
|
+
return template % d_days.pluralize('day') if d_days < 31
|
50
|
+
return template % d_months.pluralize('month') if d_months < 12
|
51
|
+
return template % d_years.pluralize('year')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class DateTime
|
57
|
+
include TimeOptions
|
58
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
def h
|
5
|
+
Hashie::Mash.new(self)
|
6
|
+
end
|
7
|
+
|
8
|
+
def h_wia
|
9
|
+
HashWithIndifferentAccess.new(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def tag node=nil, text=nil
|
13
|
+
opts = ''
|
14
|
+
self.each do |k,v|
|
15
|
+
opts += ' '+k.to_s.gsub(/_/,'-')+'="'+v.to_s.gsub(/"/,'"')+'"' if v.present?
|
16
|
+
end
|
17
|
+
|
18
|
+
return opts unless node
|
19
|
+
|
20
|
+
text = yield opts if block_given?
|
21
|
+
text ||= '' unless ['input', 'img', 'meta', 'link', 'hr', 'br'].include?(node.to_s)
|
22
|
+
text ? %{<#{node}#{opts}>#{text}</#{node}>} : %{<#{node}#{opts} />}
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_struct name=nil
|
26
|
+
name ||= ToStructGeneric
|
27
|
+
Struct.new(name, *keys).new(*values)
|
28
|
+
end
|
29
|
+
|
30
|
+
def blank?
|
31
|
+
self.keys.count == 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_query namespace=nil
|
35
|
+
self.keys.sort.map { |k|
|
36
|
+
name = namespace ? "#{namespace}[#{k}]" : k
|
37
|
+
"#{name}=#{CGI::escape(self[k].to_s)}"
|
38
|
+
}.join('&')
|
39
|
+
end
|
40
|
+
|
41
|
+
def pluck *args
|
42
|
+
string_args = args.map(&:to_s)
|
43
|
+
self.select{ |k,v| string_args.index(k.to_s) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def transform_keys
|
47
|
+
return enum_for(:transform_keys) unless block_given?
|
48
|
+
result = self.class.new
|
49
|
+
each_key do |key|
|
50
|
+
result[yield(key)] = self[key]
|
51
|
+
end
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
55
|
+
def transform_keys!
|
56
|
+
return enum_for(:transform_keys!) unless block_given?
|
57
|
+
keys.each do |key|
|
58
|
+
self[yield(key)] = delete(key)
|
59
|
+
end
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def symbolize_keys
|
64
|
+
transform_keys{ |key| key.to_sym rescue key }
|
65
|
+
end
|
66
|
+
|
67
|
+
def symbolize_keys!
|
68
|
+
transform_keys!{ |key| key.to_sym rescue key }
|
69
|
+
end
|
70
|
+
|
71
|
+
def slice *keys
|
72
|
+
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
|
73
|
+
keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def slice! *keys
|
77
|
+
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
|
78
|
+
omit = slice(*self.keys - keys)
|
79
|
+
hash = slice(*keys)
|
80
|
+
hash.default = default
|
81
|
+
hash.default_proc = default_proc if default_proc
|
82
|
+
replace(hash)
|
83
|
+
omit
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|