clevic 0.8.0 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/History.txt +9 -0
  2. data/Manifest.txt +13 -10
  3. data/README.txt +6 -9
  4. data/Rakefile +35 -24
  5. data/TODO +29 -17
  6. data/bin/clevic +84 -37
  7. data/config/hoe.rb +7 -3
  8. data/lib/clevic.rb +2 -4
  9. data/lib/clevic/browser.rb +37 -49
  10. data/lib/clevic/cache_table.rb +55 -165
  11. data/lib/clevic/db_options.rb +32 -21
  12. data/lib/clevic/default_view.rb +66 -0
  13. data/lib/clevic/delegates.rb +51 -67
  14. data/lib/clevic/dirty.rb +101 -0
  15. data/lib/clevic/extensions.rb +24 -38
  16. data/lib/clevic/field.rb +400 -99
  17. data/lib/clevic/item_delegate.rb +32 -33
  18. data/lib/clevic/model_builder.rb +315 -148
  19. data/lib/clevic/order_attribute.rb +53 -0
  20. data/lib/clevic/record.rb +57 -57
  21. data/lib/clevic/search_dialog.rb +71 -67
  22. data/lib/clevic/sql_dialects.rb +33 -0
  23. data/lib/clevic/table_model.rb +73 -120
  24. data/lib/clevic/table_searcher.rb +165 -0
  25. data/lib/clevic/table_view.rb +140 -100
  26. data/lib/clevic/ui/.gitignore +1 -0
  27. data/lib/clevic/ui/browser_ui.rb +55 -56
  28. data/lib/clevic/ui/search_dialog_ui.rb +50 -51
  29. data/lib/clevic/version.rb +2 -2
  30. data/lib/clevic/view.rb +89 -0
  31. data/models/accounts_models.rb +12 -9
  32. data/models/minimal_models.rb +4 -2
  33. data/models/times_models.rb +41 -25
  34. data/models/times_sqlite_models.rb +1 -145
  35. data/models/values_models.rb +15 -16
  36. data/test/test_cache_table.rb +138 -0
  37. data/test/test_helper.rb +131 -0
  38. data/test/test_model_index_extensions.rb +22 -0
  39. data/test/test_order_attribute.rb +62 -0
  40. data/test/test_sql_dialects.rb +77 -0
  41. data/test/test_table_searcher.rb +188 -0
  42. metadata +36 -20
  43. data/bin/import-times +0 -128
  44. data/config/jamis.rb +0 -589
  45. data/env.sh +0 -1
  46. data/lib/active_record/dirty.rb +0 -87
  47. data/lib/clevic/field_builder.rb +0 -42
  48. data/website/index.html +0 -170
  49. data/website/index.txt +0 -17
  50. data/website/screenshot.png +0 -0
  51. data/website/stylesheets/screen.css +0 -131
  52. data/website/template.html.erb +0 -41
@@ -0,0 +1,131 @@
1
+ require 'test/unit'
2
+ require 'shoulda'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/clevic'
5
+
6
+ require 'activerecord'
7
+ require 'sqlite3'
8
+ require 'faker'
9
+ require 'generator'
10
+
11
+
12
+ class Flight < ActiveRecord::Base
13
+ has_many :passengers
14
+ end
15
+
16
+ class Passenger < ActiveRecord::Base
17
+ belongs_to :flight
18
+ end
19
+
20
+ class CreateFlights < ActiveRecord::Migration
21
+ def self.up
22
+ create_table :flights do |t|
23
+ t.string :number
24
+ t.string :airline
25
+ t.string :destination
26
+ end
27
+ Flight.reset_column_information
28
+ Flight.create :number => 'EK211'
29
+ Flight.create :number => 'EK088'
30
+ Flight.create :number => 'EK761'
31
+ Flight.create :number => 'BA264'
32
+ end
33
+
34
+ def self.down
35
+ Flight.delete_all
36
+ end
37
+ end
38
+
39
+ class CreatePassengers < ActiveRecord::Migration
40
+ def self.up
41
+ create_table :passengers do |t|
42
+ t.string :name
43
+ t.string :nationality
44
+ t.integer :flight_id
45
+ t.integer :row
46
+ t.string :seat
47
+ end
48
+ Passenger.reset_column_information
49
+ end
50
+
51
+ def self.down
52
+ Passenger.delete_all
53
+ end
54
+ end
55
+
56
+ # Convenience class to create a test DB
57
+ class OneBase
58
+ attr_reader :db_name, :adapter
59
+
60
+ def initialize
61
+ @db_name = 'test_cache_table.sqlite3'
62
+
63
+ if File.exists? @db_name
64
+ p 'remove old db'
65
+ File.unlink @db_name
66
+ end
67
+
68
+ @adapter = :sqlite3
69
+ @db = SQLite3::Database.new( @db_name )
70
+ @db_options = Clevic::DbOptions.connect do |dbo|
71
+ dbo.database @db_name
72
+ dbo.adapter @adapter
73
+ end
74
+ end
75
+
76
+ def feenesh
77
+ File.unlink @db_name
78
+ end
79
+ end
80
+
81
+ # Allow running of startup and shutdown things before
82
+ # an entire suite, instead of just one per test
83
+ class SuiteWrapper < Test::Unit::TestSuite
84
+ attr_accessor :tests
85
+
86
+ def initialize( name, test_case )
87
+ super( name )
88
+ @test_case = test_case
89
+ end
90
+
91
+ def startup
92
+ @onebase = OneBase.new
93
+ ActiveRecord::Migration.verbose = false
94
+ CreateFlights.up
95
+ CreatePassengers.up
96
+ end
97
+
98
+ def shutdown
99
+ CreatePassengers.down
100
+ CreateFlights.down
101
+ @onebase.feenesh
102
+ end
103
+
104
+ def run( *args )
105
+ startup
106
+ @test_case.startup if @test_case.respond_to? :startup
107
+ retval = super
108
+ @test_case.shutdown if @test_case.respond_to? :shutdown
109
+ shutdown
110
+ retval
111
+ end
112
+ end
113
+
114
+ module Test
115
+ module Unit
116
+ class TestCase
117
+ unless respond_to? :old_suite
118
+ class << self
119
+ alias_method :old_suite, :suite
120
+ end
121
+
122
+ def self.suite
123
+ os = old_suite
124
+ sw = SuiteWrapper.new( os.name, self )
125
+ sw.tests = os.tests
126
+ sw
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class TestModelIndex < Test::Unit::TestCase
4
+ def self.startup
5
+ end
6
+
7
+ def self.shutdown
8
+ end
9
+
10
+ def setup
11
+ end
12
+
13
+ def teardown
14
+ end
15
+
16
+ should_eventually 'test something'
17
+
18
+ should 'be true' do
19
+ assert true
20
+ end
21
+
22
+ end
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'clevic/order_attribute.rb'
3
+
4
+ class Dummy < ActiveRecord::Base
5
+ end
6
+
7
+ # need to set up a test DB, and test data for this
8
+ class TestOrderAttribute < Test::Unit::TestCase
9
+ def setup
10
+ end
11
+
12
+ def teardown
13
+ end
14
+
15
+ def test_reverse
16
+ oa = OrderAttribute.new Dummy, 'id'
17
+ assert_equal :asc, oa.reverse( :desc )
18
+ assert_equal :desc, oa.reverse( :asc )
19
+ assert_raise( RuntimeError ) { oa.reverse( :something_wrong ) }
20
+ end
21
+
22
+ # Test that initialisation was OK
23
+ def test_equal
24
+ oa1 = OrderAttribute.new Dummy, 'id'
25
+ oa2 = OrderAttribute.new Dummy, 'id'
26
+ assert_equal oa1, oa2
27
+ assert_equal oa1.to_sql, 'dummies.id asc'
28
+ assert_equal oa1.to_reverse_sql, 'dummies.id desc'
29
+ assert_equal oa1.attribute.to_sym, oa1.to_sym
30
+
31
+ assert_equal oa2.to_sql, 'dummies.id asc'
32
+ assert_equal oa2.to_reverse_sql, 'dummies.id desc'
33
+ end
34
+
35
+ def test_parse_default
36
+ oa_asc = OrderAttribute.new Dummy, "name"
37
+ assert_equal 'name', oa_asc.attribute
38
+ assert_equal :asc, oa_asc.direction
39
+ end
40
+
41
+ def test_parse_desc
42
+ oa_desc = OrderAttribute.new Dummy, "name desc"
43
+ assert_equal 'name', oa_desc.attribute
44
+ assert_equal 'name', oa_desc.to_s
45
+ assert_equal :desc, oa_desc.direction
46
+ assert_equal oa_desc.to_sql, 'dummies.name desc'
47
+ assert_equal 'dummies.name asc', oa_desc.to_reverse_sql
48
+
49
+ oa_desc = OrderAttribute.new Dummy, "dummies.name desc"
50
+ assert_equal 'name', oa_desc.attribute
51
+ assert_equal :desc, oa_desc.direction
52
+ assert_equal oa_desc.to_sql, 'dummies.name desc'
53
+ end
54
+
55
+ def test_parse_table
56
+ oa_with_table = OrderAttribute.new Dummy, 'dummies.name asc'
57
+ assert_equal 'name', oa_with_table.attribute
58
+ assert_equal :asc, oa_with_table.direction
59
+ assert_equal oa_with_table.to_sql, 'dummies.name asc'
60
+ end
61
+
62
+ end
@@ -0,0 +1,77 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require 'clevic/sql_dialects.rb'
3
+
4
+ # TODO should probably connect to real DB drivers to do this
5
+
6
+ class MockPostgreSQL
7
+ include Clevic::SqlDialects
8
+ def adapter_name
9
+ 'PostgreSQL'
10
+ end
11
+
12
+ def connection
13
+ self
14
+ end
15
+
16
+ end
17
+
18
+ class MockOther
19
+ include Clevic::SqlDialects
20
+ def adapter_name
21
+ 'Something else entirely'
22
+ end
23
+
24
+ def connection
25
+ self
26
+ end
27
+
28
+ def quoted_true; "'t'"; end
29
+ def quoted_false; "'f'"; end
30
+ end
31
+
32
+ class TestSqlDialects < Test::Unit::TestCase
33
+ def self.startup
34
+ end
35
+
36
+ def self.shutdown
37
+ end
38
+
39
+ def setup
40
+ end
41
+
42
+ context MockPostgreSQL.name do
43
+ setup do
44
+ @dialect = MockPostgreSQL.new
45
+ end
46
+
47
+ should 'return ilike' do
48
+ assert_equal 'ilike', @dialect.like_operator
49
+ end
50
+
51
+ should "return true" do
52
+ assert_equal "true", @dialect.sql_boolean( true )
53
+ end
54
+
55
+ should "return false" do
56
+ assert_equal "false", @dialect.sql_boolean( false )
57
+ end
58
+ end
59
+
60
+ context MockOther.name do
61
+ setup do
62
+ @dialect = MockOther.new
63
+ end
64
+
65
+ should 'return like' do
66
+ assert_equal 'like', @dialect.like_operator
67
+ end
68
+
69
+ should "return 't'" do
70
+ assert_equal "'t'", @dialect.sql_boolean( true )
71
+ end
72
+
73
+ should "return 'f'" do
74
+ assert_equal "'f'", @dialect.sql_boolean( false )
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,188 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require 'clevic/table_searcher.rb'
3
+
4
+ class CreateFakePassengers < ActiveRecord::Migration
5
+ MAX_PASSENGERS = 100
6
+ NATIONALITIES = %w{Canada USA Britain UAE}
7
+
8
+ def self.up
9
+ 1.upto( MAX_PASSENGERS ) do |i|
10
+ Passenger.create :name => Faker::Name.name, :flight => Flight.find(:all)[i%4], :nationality => NATIONALITIES[i%4], :row => i, :seat => %w{A B C D}[i % 4]
11
+ end
12
+ end
13
+
14
+ def self.down
15
+ Passenger.delete_all
16
+ end
17
+ end
18
+
19
+ class MockSearchCriteria
20
+
21
+ def initialize( &block )
22
+ @direction = :forwards
23
+ @from_start = false
24
+ @whole_words = false
25
+ self.instance_eval( &block ) if block_given?
26
+ end
27
+
28
+ attr_accessor :direction, :search_text
29
+ attr_writer :whole_words, :from_start
30
+ def whole_words?; @whole_words; end
31
+ def from_start?; @from_start; end
32
+ end
33
+
34
+ class TestTableSearcher < Test::Unit::TestCase
35
+ def self.startup
36
+ CreateFakePassengers.up
37
+ end
38
+
39
+ def self.shutdown
40
+ CreateFakePassengers.down
41
+ end
42
+
43
+ def setup
44
+ @simple_search_criteria = MockSearchCriteria.new
45
+ @id_order_attribute = OrderAttribute.new( Passenger, 'id' )
46
+
47
+ @name_field = Clevic::Field.new( :name, Passenger, {} )
48
+ @nationality_field = Clevic::Field.new( :nationality, Passenger, {} )
49
+ @all_passengers = Passenger.find( :all, :conditions => [ 'flight_id = ?', Flight.find(:first).id ], :order => :id )
50
+ end
51
+
52
+ context 'on initialisation' do
53
+ should "have a matching field attribute on construction" do
54
+ ts = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @name_field )
55
+ assert_equal @name_field.attribute, ts.field.attribute
56
+ end
57
+
58
+ should "throw an exception when called with no order attributes" do
59
+ assert_raise( RuntimeError ) do
60
+ Clevic::TableSearcher.new( Passenger, nil, @simple_search_criteria, @name_field )
61
+ end
62
+ end
63
+
64
+ should "throw an exception when called with an empty collection of order attributes" do
65
+ assert_raise( RuntimeError ) do
66
+ Clevic::TableSearcher.new( Passenger, [], @simple_search_criteria, @name_field )
67
+ end
68
+ end
69
+
70
+ should "throw an exception when called with no field" do
71
+ assert_raise( RuntimeError ) do
72
+ Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, nil )
73
+ end
74
+ end
75
+
76
+ should 'throw an exception for an unknown direction' do
77
+ @simple_search_criteria.direction = :other
78
+ assert_raise( RuntimeError ) do
79
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @nationality_field )
80
+ end
81
+ end
82
+ end
83
+
84
+ context "searching" do
85
+ setup do
86
+ @simple_search_criteria.search_text = CreateFakePassengers::NATIONALITIES[0]
87
+ @passenger_generator = Generator.new( @all_passengers )
88
+ end
89
+
90
+ should "have #{CreateFakePassengers::MAX_PASSENGERS} passengers" do
91
+ assert_equal CreateFakePassengers::MAX_PASSENGERS, Passenger.count
92
+ end
93
+
94
+ should_eventually "do more granular testing"
95
+
96
+ should "find the first record" do
97
+ @simple_search_criteria.from_start = true
98
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @nationality_field )
99
+ assert_equal @all_passengers.first, table_searcher.search
100
+ end
101
+
102
+ should "backwards-find the last record" do
103
+ @simple_search_criteria.from_start = true
104
+ @simple_search_criteria.direction = :backwards
105
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @nationality_field )
106
+ assert_equal @all_passengers.last, table_searcher.search
107
+ end
108
+
109
+ should "backwards-find the next-to-last record" do
110
+ # find the last record
111
+ @simple_search_criteria.from_start = true
112
+ @simple_search_criteria.direction = :backwards
113
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @nationality_field )
114
+ last = table_searcher.search
115
+
116
+ # now find the previous record
117
+ @simple_search_criteria.from_start = false
118
+ assert_equal @all_passengers[-2], table_searcher.search( last )
119
+ end
120
+
121
+ should "find next records" do
122
+ @simple_search_criteria.from_start = false
123
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @nationality_field )
124
+
125
+ # fetch records one by one, starting from the one after the first one, and compare them
126
+ while next_entity = table_searcher.search( @passenger_generator.next )
127
+ passenger = @passenger_generator.next
128
+
129
+ assert_equal next_entity, passenger
130
+ assert_not_equal @all_passengers.first, passenger
131
+
132
+ last_entity = next_entity
133
+ end
134
+ end
135
+ end
136
+
137
+ context 'search for related field value' do
138
+ should 'raise an exception for no display value' do
139
+ @simple_search_criteria.from_start = true
140
+ @simple_search_criteria.search_text = Flight.find(:first).number
141
+ flight_field = Clevic::Field.new( :flight, Passenger, {} )
142
+ assert_nil flight_field.path
143
+ assert_raise RuntimeError do
144
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, flight_field )
145
+ table_searcher.search
146
+ end
147
+ end
148
+
149
+ should 'find a record' do
150
+ @simple_search_criteria.from_start = true
151
+ @simple_search_criteria.search_text = Flight.find(:first).number
152
+ flight_field = Clevic::Field.new( :flight, Passenger, { :display => 'number' } )
153
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, flight_field )
154
+ assert_equal @all_passengers.first, table_searcher.search
155
+ end
156
+ end
157
+
158
+ context 'whole words' do
159
+ setup do
160
+ @simple_search_criteria.from_start = true
161
+ @simple_search_criteria.search_text = CreateFakePassengers::NATIONALITIES[0][0..-3]
162
+ @should_find = Passenger.find :all, :conditions => "nationality like '%#{@simple_search_criteria.search_text}%'", :order => :id
163
+ end
164
+
165
+ should 'find a full value with a partial search string' do
166
+ @simple_search_criteria.whole_words = false
167
+ @simple_search_criteria.from_start = true
168
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @nationality_field )
169
+ g = Generator.new @should_find
170
+ last_entity = nil
171
+ while next_entity = table_searcher.search( last_entity )
172
+ assert_equal next_entity, g.next
173
+ last_entity = next_entity
174
+ @simple_search_criteria.from_start = false
175
+ end
176
+ end
177
+
178
+ should 'not find any values with a partial search string and whole_words enabled' do
179
+ @simple_search_criteria.whole_words = true
180
+ @simple_search_criteria.from_start = true
181
+ table_searcher = Clevic::TableSearcher.new( Passenger, [@id_order_attribute], @simple_search_criteria, @nationality_field )
182
+ assert_nil table_searcher.search
183
+ end
184
+ end
185
+
186
+ should_eventually 'work for Array'
187
+
188
+ end