clevic 0.8.0 → 0.11.1

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 (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