vex 0.2

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 (114) hide show
  1. data/Manifest +112 -0
  2. data/Rakefile +53 -0
  3. data/VERSION +1 -0
  4. data/config/README +2 -0
  5. data/config/dependencies.rb +10 -0
  6. data/config/gem.yml +7 -0
  7. data/init.rb +36 -0
  8. data/lib/nokogiri/nokogiri_ext.rb +96 -0
  9. data/lib/vex.rb +5 -0
  10. data/lib/vex/action_controller.rb +4 -0
  11. data/lib/vex/action_controller/verify_action.rb +97 -0
  12. data/lib/vex/action_controller/whitelisted_actions.rb +45 -0
  13. data/lib/vex/active_record.rb +3 -0
  14. data/lib/vex/active_record/__init__.rb +0 -0
  15. data/lib/vex/active_record/advisory_lock.rb +11 -0
  16. data/lib/vex/active_record/advisory_lock/mysql_adapter.rb +16 -0
  17. data/lib/vex/active_record/advisory_lock/sqlite_adapter.rb +78 -0
  18. data/lib/vex/active_record/belongs_to_many.rb +143 -0
  19. data/lib/vex/active_record/find_by_extension.rb +70 -0
  20. data/lib/vex/active_record/gem.rb +8 -0
  21. data/lib/vex/active_record/lite_table.rb +139 -0
  22. data/lib/vex/active_record/lite_view.rb +140 -0
  23. data/lib/vex/active_record/mass_load.rb +65 -0
  24. data/lib/vex/active_record/mysql_backup.rb +21 -0
  25. data/lib/vex/active_record/plugins/default_value_for/LICENSE.TXT +19 -0
  26. data/lib/vex/active_record/plugins/default_value_for/README.rdoc +421 -0
  27. data/lib/vex/active_record/plugins/default_value_for/Rakefile +6 -0
  28. data/lib/vex/active_record/plugins/default_value_for/init.rb +91 -0
  29. data/lib/vex/active_record/plugins/default_value_for/test.rb +279 -0
  30. data/lib/vex/active_record/plugins/default_value_for/test.sqlite3 +0 -0
  31. data/lib/vex/active_record/random_id.rb +56 -0
  32. data/lib/vex/active_record/resolver.rb +49 -0
  33. data/lib/vex/active_record/serialize_hash.rb +125 -0
  34. data/lib/vex/active_record/to_html.rb +53 -0
  35. data/lib/vex/active_record/validate.rb +76 -0
  36. data/lib/vex/active_record/validation_error_ext.rb +68 -0
  37. data/lib/vex/base.rb +2 -0
  38. data/lib/vex/base/app.rb +75 -0
  39. data/lib/vex/base/array/at_random.rb +17 -0
  40. data/lib/vex/base/array/cross.rb +26 -0
  41. data/lib/vex/base/array/each_batch.rb +32 -0
  42. data/lib/vex/base/array/parallel_map.rb +98 -0
  43. data/lib/vex/base/deprecation.rb +41 -0
  44. data/lib/vex/base/enumerable/deep.rb +95 -0
  45. data/lib/vex/base/enumerable/enumerable_ext.rb +59 -0
  46. data/lib/vex/base/enumerable/progress.rb +71 -0
  47. data/lib/vex/base/filesystem/fast_copy.rb +61 -0
  48. data/lib/vex/base/filesystem/grep.rb +34 -0
  49. data/lib/vex/base/filesystem/lock.rb +43 -0
  50. data/lib/vex/base/filesystem/lock.rb.test.lck +0 -0
  51. data/lib/vex/base/filesystem/lock.rb.test.pid +1 -0
  52. data/lib/vex/base/filesystem/make_dirs.rb +94 -0
  53. data/lib/vex/base/filesystem/parse_filename.rb +36 -0
  54. data/lib/vex/base/filesystem/tmp_file.rb +87 -0
  55. data/lib/vex/base/filesystem/write.rb +43 -0
  56. data/lib/vex/base/hash/compact.rb +38 -0
  57. data/lib/vex/base/hash/cross.rb +117 -0
  58. data/lib/vex/base/hash/easy_access.rb +141 -0
  59. data/lib/vex/base/hash/ensure_keys.rb +18 -0
  60. data/lib/vex/base/hash/extract.rb +71 -0
  61. data/lib/vex/base/hash/extras.rb +62 -0
  62. data/lib/vex/base/hash/inspect.rb +17 -0
  63. data/lib/vex/base/hash/simple_access_methods.rb +74 -0
  64. data/lib/vex/base/invalid_argument/invalid_argument.rb +97 -0
  65. data/lib/vex/base/local_conf.rb +35 -0
  66. data/lib/vex/base/net/http_ext.rb +227 -0
  67. data/lib/vex/base/net/socket_ext.rb +43 -0
  68. data/lib/vex/base/object/insp.rb +123 -0
  69. data/lib/vex/base/object/multiple_attributes.rb +58 -0
  70. data/lib/vex/base/object/singleton_methods.rb +23 -0
  71. data/lib/vex/base/object/with_benchmark.rb +110 -0
  72. data/lib/vex/base/range_array.rb +40 -0
  73. data/lib/vex/base/range_ext.rb +28 -0
  74. data/lib/vex/base/safe_token.rb +156 -0
  75. data/lib/vex/base/string/string_ext.rb +136 -0
  76. data/lib/vex/base/thread/deferred.rb +52 -0
  77. data/lib/vex/base/thread/sleep.rb +11 -0
  78. data/lib/vex/base/time/date_ext.rb +12 -0
  79. data/lib/vex/boot.rb +40 -0
  80. data/lib/vex/boot/array.rb +22 -0
  81. data/lib/vex/boot/blank.rb +41 -0
  82. data/lib/vex/boot/string.rb +60 -0
  83. data/migration/create_request_log.rb +28 -0
  84. data/r.rb +35 -0
  85. data/script/console +19 -0
  86. data/script/rebuild +7 -0
  87. data/tasks/echoe.rake +52 -0
  88. data/tasks/validate_db.rake +14 -0
  89. data/test/ar.rb +30 -0
  90. data/test/auto.rb +31 -0
  91. data/test/base-tests/local_conf.rb +25 -0
  92. data/test/base.rb +2 -0
  93. data/test/boot.rb +3 -0
  94. data/test/config/local.defaults.yml +4 -0
  95. data/test/config/local.yml +8 -0
  96. data/test/test.sqlite3 +0 -0
  97. data/test/test.sqlite3.Class#create.lck +0 -0
  98. data/test/test.sqlite3.Class#create.lck.lck +0 -0
  99. data/test/test.sqlite3.Class#create.lck.pid +1 -0
  100. data/test/test.sqlite3.Class#create.pid +1 -0
  101. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck +0 -0
  102. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.lck +0 -0
  103. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.pid +1 -0
  104. data/test/test.sqlite3.LiteView.make.holders__view_dummy.pid +1 -0
  105. data/test/test.sqlite3.vex.lck +0 -0
  106. data/test/test_helper.rb +49 -0
  107. data/test/tmp/copy.dat +1 -0
  108. data/test/tmp/lock.sqlite3 +0 -0
  109. data/test/tmp/lock.sqlite3.etest.lck +0 -0
  110. data/test/tmp/lock.sqlite3.etest.pid +1 -0
  111. data/test/tmp/somedata.dat +61 -0
  112. data/vex.gemspec +49 -0
  113. data/vex.tmproj +186 -0
  114. metadata +305 -0
@@ -0,0 +1,125 @@
1
+ __END__
2
+
3
+ module ActiveRecord::SerializeHash
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base.alias_method_chain :reload, :serialize_hash
7
+ base.before_update :update_serialize_hashes
8
+ end
9
+
10
+ def self.jsonize(data)
11
+ return nil if data.nil?
12
+ return data.to_json unless data.is_a?(Hash)
13
+
14
+ "{" + data.to_a.
15
+ map do |k,v| "#{k.to_json}:#{jsonize(v)}" end.
16
+ sort.
17
+ join(",") +
18
+ "}"
19
+ end
20
+
21
+ def self.unjsonize(data)
22
+ r = data.blank? ? {} : JSON.parse(data)
23
+ r = r.with_indifferent_access if r.respond_to?(:with_indifferent_access)
24
+ r
25
+ end
26
+
27
+ module ClassMethods
28
+ def serialize_hash_attributes
29
+ @serialize_hash_attributes ||= Set.new
30
+ end
31
+
32
+ def serialize_hash(attr)
33
+ serialize_hash_attributes << attr
34
+
35
+ class_eval <<-RUBY
36
+ def #{attr}; @#{attr} ||= ActiveRecord::SerializeHash.unjsonize read_attribute(:#{attr}); end
37
+ def #{attr}=(d); write_attribute(:#{attr}, ActiveRecord::SerializeHash.jsonize(d)); @#{attr} = nil;
38
+ end
39
+ RUBY
40
+ end
41
+
42
+ def hashed_attributes(*syms)
43
+ serialize_hash :hashed_attributes
44
+
45
+ syms.each do |sym|
46
+ define_method(sym) do hashed_attributes[sym] end
47
+ define_method("#{sym}=") do |val| hashed_attributes[sym] = val end
48
+ end
49
+ end
50
+ end
51
+
52
+ def reload_with_serialize_hash
53
+ self.class.serialize_hash_attributes.each do |attr|
54
+ instance_variable_set "@#{attr}", nil
55
+ end
56
+ reload_without_serialize_hash
57
+ end
58
+
59
+ def update_serialize_hashes
60
+ self.class.serialize_hash_attributes.each do |attr|
61
+ next unless val = instance_variable_get("@#{attr}")
62
+ self.send "#{attr}=", val
63
+ end
64
+ end
65
+ end
66
+
67
+ class ActiveRecord::Base
68
+ include ActiveRecord::SerializeHash
69
+ end
70
+
71
+ module ActiveRecord::SerializeHash::Etest
72
+ def test_serialize_hash
73
+ rb = RandomBase.create!
74
+
75
+ assert_equal({}, rb.parameters)
76
+ assert_nil(rb.parameters["test"])
77
+
78
+ rb.parameters[:test] = "bla"
79
+ assert_equal("bla", rb.parameters[:test])
80
+ assert_equal("bla", rb.parameters["test"])
81
+
82
+ rb.parameters["test"] = "lurk"
83
+
84
+ assert_equal("lurk", rb.parameters[:test])
85
+ assert_equal("lurk", rb.parameters["test"])
86
+
87
+ rb.reload
88
+ assert_nil(rb.parameters["test"])
89
+ rb.parameters["test"] = "lurk"
90
+ rb.save!
91
+
92
+ rb.reload
93
+ assert_equal("lurk", rb.parameters[:test])
94
+ assert_equal("lurk", rb.parameters["test"])
95
+
96
+ rb = RandomBase.find(rb.id)
97
+ assert_equal("lurk", rb.parameters[:test])
98
+ assert_equal("lurk", rb.parameters["test"])
99
+ end
100
+
101
+ def test_hashed_attributes
102
+ rb = RandomBase.create!
103
+ rb.ha1 = "ha1"
104
+ assert_equal("ha1", rb.ha1)
105
+
106
+ rb.reload
107
+ assert_equal(nil, rb.ha1)
108
+ rb.ha1 = "ha1"
109
+ rb.save!
110
+ rb.reload
111
+ assert_equal("ha1", rb.ha1)
112
+
113
+ rb = RandomBase.find(rb.id)
114
+ assert_equal("ha1", rb.ha1)
115
+ end
116
+
117
+ def test_reload
118
+ rb = RandomBase.create!
119
+ rb.parameters[:test] = "bla"
120
+
121
+ assert_equal("bla", rb.parameters[:test])
122
+ rb.reload
123
+ assert_nil(rb.parameters["test"])
124
+ end
125
+ end
@@ -0,0 +1,53 @@
1
+ module ActiveRecord::ToHtml
2
+ def to_html(options = {}, &block)
3
+ options = {
4
+ :skip_instruct => true,
5
+ }.update(options)
6
+
7
+ to_xml(options, &block).gsub( /<[^>]+>/ ) do |m|
8
+ if m.starts_with?("</")
9
+ "</div>"
10
+ else
11
+ m =~ /^<(\S+)\s*([^>]*)>$/
12
+ klass, args = $1, $2
13
+ "<div class='#{klass}'#{args.blank? ? "" : " #{args}"}>"
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ class ActiveRecord::Base
20
+ include ActiveRecord::ToHtml
21
+ end
22
+
23
+ module ActiveRecord::ToHtml::Etest
24
+ class Data < ActiveRecord::Base
25
+ end
26
+
27
+ def setup
28
+ Data.lite_table do
29
+ string :name
30
+ string :age
31
+ end
32
+
33
+ Data.create! :name => "name", :age => 2
34
+
35
+ assert_equal(1, Data.count)
36
+ end
37
+
38
+ def teardown
39
+ Data.destroy_all
40
+ end
41
+
42
+ def test_to_html
43
+ html = <<-HTML
44
+ <div class='active-record-to-html-etest-data'>
45
+ <div class='age'>2</div>
46
+ <div class='id' type="integer">25</div>
47
+ <div class='name'>name</div>
48
+ </div>
49
+ HTML
50
+
51
+ assert_equal html, Data.first.to_html
52
+ end
53
+ end
@@ -0,0 +1,76 @@
1
+ module ActiveRecord::Validate
2
+ def self.all(quiet=nil, &block)
3
+ klasses(quiet).inject(0) do |count, klass|
4
+ count += invalid_models(klass, quiet).length
5
+ end
6
+ end
7
+
8
+ def self.purge
9
+ klasses(true).each do |klass|
10
+ invalids = invalid_models(klass, true)
11
+ klass.delete_all [ "id IN (?)", invalids.map(&:id) ] unless invalids.empty?
12
+ end
13
+ end
14
+
15
+
16
+ def self.set_klass_for(opts)
17
+ @klass_for_table ||= {}
18
+ @klass_for_table.update opts.with_indifferent_access
19
+ end
20
+
21
+ private
22
+
23
+ def self.klass_for_table(table)
24
+ @klass_for_table ||= {}
25
+ if klass = @klass_for_table[table]
26
+ klass.constantize
27
+ else
28
+ table.singularize.camelize.constantize?
29
+ end
30
+ end
31
+
32
+ def self.klasses(quiet)
33
+ ActiveRecord::Base.connection.tables.map do |table|
34
+ klass = klass_for_table table
35
+ if !klass
36
+ STDERR.puts "* #{table}: table w/o class" unless quiet
37
+ elsif !klass.respond_to?(:table_name) || klass.table_name != table
38
+ STDERR.puts "Tablename mismatch #{table.inspect} vs #{klass.table_name.inspect}" unless quiet
39
+ else
40
+ klass
41
+ end
42
+ end.compact
43
+ end
44
+
45
+ def self.invalid_models(klass, quiet)
46
+ validate_klass(klass) do |*args|
47
+ msg, force = *args
48
+ STDERR.puts(msg) if force || !quiet
49
+ end
50
+ end
51
+
52
+ def self.validate_klass(klass)
53
+ yield "#{klass}: #{sum=klass.count} models"
54
+
55
+ invalid = []
56
+
57
+ klass.each do |model|
58
+ next if model.valid?
59
+ invalid << model
60
+
61
+ yield "\tInvalid model #{model.class}##{model.id}: #{model.errors.full_messages.join(", ")}"
62
+ end
63
+
64
+ yield "\r#{klass}: checked #{klass.count} models, #{invalid.length} invalid", :force
65
+
66
+ return invalid if invalid.empty?
67
+
68
+ invalid.group_by(&:class).to_a.
69
+ sort_by do |klass, ms| klass.name end.
70
+ each do |klass, ms|
71
+ yield "\t** #{klass}: Invalid models: #{ms.collect(&:id).inspect}"
72
+ end
73
+
74
+ invalid
75
+ end
76
+ end
@@ -0,0 +1,68 @@
1
+
2
+ # better error reporting: this is useful mainly for development cycles, as
3
+ # it adds an error message only once
4
+ module ActiveRecord::Errors::Unique
5
+
6
+ def delete(entry)
7
+ @errors.delete entry.to_s
8
+ end
9
+
10
+ def add(attribute, message = nil, options = {})
11
+ add_with_unique_messages(attribute, message, options)
12
+ end
13
+
14
+ def add_with_unique_messages(error_or_attr, message = nil, options = {})
15
+ if error_or_attr.is_a?(ActiveRecord::Error)
16
+ error, attribute = error_or_attr, error_or_attr.attribute
17
+ else
18
+ attribute = error_or_attr
19
+ error = ActiveRecord::Error.new(@base, attribute, message, options)
20
+ end
21
+
22
+ options[:message] = options.delete(:default) if options.has_key?(:default)
23
+
24
+ @errors[attribute.to_s] ||= []
25
+
26
+ existing = @errors[attribute.to_s].detect do |err|
27
+ err.message == message
28
+ end
29
+
30
+ existing || (@errors[attribute.to_s] << error)
31
+ end
32
+ end
33
+
34
+ class ActiveRecord::Errors
35
+ include Unique
36
+ alias_method_chain :add, :unique_messages
37
+ end
38
+
39
+ module ActiveRecord::Errors::Unique::Etest
40
+ ActiveRecord::Base.connection.create_table :error_models do |t|
41
+ t.integer :value
42
+ end
43
+
44
+ class ErrorModels < ActiveRecord::Base
45
+ end
46
+
47
+ def test_single_adds
48
+ obj = ErrorModels.new
49
+
50
+ obj.errors.add "value", "xxx"
51
+ assert_kind_of(String, obj.errors["value"])
52
+
53
+ obj.errors.add "value", "xxx"
54
+ assert_kind_of(String, obj.errors["value"])
55
+
56
+ obj.errors.add "value", "yyyy"
57
+ assert_equal(%w(xxx yyyy), obj.errors["value"])
58
+
59
+ obj.errors.add "value", "yyyy"
60
+ assert_equal(%w(xxx yyyy), obj.errors["value"])
61
+
62
+ obj.errors.add "value", "xxx"
63
+ assert_equal(%w(xxx yyyy), obj.errors["value"])
64
+
65
+ obj.errors.add "value", "zzz"
66
+ assert_equal(%w(xxx yyyy zzz), obj.errors["value"])
67
+ end
68
+ end
data/lib/vex/base.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "#{File.dirname(__FILE__)}/boot"
2
+ Vex.load_directory "base"
@@ -0,0 +1,75 @@
1
+ module App
2
+ def self.rails?
3
+ defined?(RAILS_ROOT)
4
+ end
5
+
6
+ def self.revision
7
+ @revision ||= begin
8
+ "r#{File.read("#{root}/REVISION")}"
9
+ rescue Errno::ENOENT
10
+ ""
11
+ end
12
+ end
13
+
14
+ def self.env
15
+ if rails?
16
+ RAILS_ENV
17
+ elsif defined?(APP_ENV)
18
+ APP_ENV
19
+ else
20
+ "production"
21
+ end
22
+ end
23
+
24
+ def self.root
25
+ if defined?(RAILS_ROOT)
26
+ RAILS_ROOT
27
+ elsif defined?(APP_ROOT)
28
+ APP_ROOT
29
+ else
30
+ raise "Cannot determine application root"
31
+ end
32
+ end
33
+
34
+ def self.logger
35
+ if rails?
36
+ RAILS_DEFAULT_LOGGER
37
+ else
38
+ require "logger"
39
+
40
+ logdir = "#{root}/log"
41
+ FileUtils.mkdir_p logdir
42
+ Logger.new "#{logdir}/#{env}.log"
43
+ end
44
+ end
45
+
46
+ def self.tmpdir
47
+ @tmpdir ||= begin
48
+ tmpdir = if rails?
49
+ "#{root}/tmp"
50
+ else
51
+ ENV["TMPDIR"]
52
+ end
53
+
54
+ tmpdir = tmpdir.gsub(/\/$/, "")
55
+
56
+ raise "Cannot determine tmpdir setting" if tmpdir.blank?
57
+ tmpdir
58
+ end
59
+ end
60
+
61
+ def self.local_conf
62
+ @local_conf = nil if App.env == "development"
63
+ @local_conf ||= LocalConf.new("local.yml")
64
+ end
65
+ end
66
+
67
+ module App::Etest
68
+ def test_app
69
+ assert_not_nil(App.root)
70
+ end
71
+
72
+ def test_app
73
+ assert_equal("", App.revision)
74
+ end
75
+ end if VEX_TEST == "base"
@@ -0,0 +1,17 @@
1
+ module Array::AtRandom
2
+ def at_random
3
+ self[Kernel.rand(length)] unless empty?
4
+ end
5
+ end
6
+
7
+ Array.send :include, Array::AtRandom
8
+
9
+ module Array::AtRandom::Etest
10
+ def test_at_random
11
+ array = [ 1, 2, 3, 4, 5 ]
12
+ 5.times do
13
+ assert array.include?(array.at_random)
14
+ end
15
+ assert_equal nil, [].at_random
16
+ end
17
+ end if VEX_TEST == "base"
@@ -0,0 +1,26 @@
1
+ module Array::Cross
2
+ def cross(other, &block)
3
+ if !block_given?
4
+ r = []
5
+ cross(other) do |mine, others|
6
+ r << [ mine, others ]
7
+ end
8
+ return r
9
+ else
10
+ each do |obj|
11
+ other.each do |oo| yield obj, oo end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ Array.send :include, Array::Cross
18
+
19
+ module Array::Cross::Etest
20
+ def test_cross
21
+ assert_equal( [[1,1]], [1].cross([1]) )
22
+ assert_equal( [[1,1], [2,1]], [1, 2].cross([1]) )
23
+ assert_equal( [[1,1], [1,3], [2,1], [2,3]], [1, 2].cross([1, 3]) )
24
+ assert_equal( [], [1, 2].cross([]) )
25
+ end
26
+ end if VEX_TEST == "base"