vex 0.2

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