lucid_works 0.6.29 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.rvmrc +1 -1
  2. data/Rakefile +25 -0
  3. data/config/locales/en.yml +171 -83
  4. data/lib/lucid_works/associations/has_many.rb +2 -2
  5. data/lib/lucid_works/associations/has_one.rb +1 -1
  6. data/lib/lucid_works/associations/proxy.rb +3 -3
  7. data/lib/lucid_works/associations.rb +2 -2
  8. data/lib/lucid_works/base.rb +21 -48
  9. data/lib/lucid_works/collection/click.rb +17 -0
  10. data/lib/lucid_works/collection/settings.rb +0 -1
  11. data/lib/lucid_works/collection.rb +22 -3
  12. data/lib/lucid_works/crawler.rb +13 -0
  13. data/lib/lucid_works/datasource/history.rb +5 -9
  14. data/lib/lucid_works/datasource/status.rb +8 -11
  15. data/lib/lucid_works/datasource.rb +67 -32
  16. data/lib/lucid_works/datasource_property.rb +18 -0
  17. data/lib/lucid_works/datasource_type.rb +23 -0
  18. data/lib/lucid_works/exceptions.rb +1 -0
  19. data/lib/lucid_works/field.rb +43 -2
  20. data/lib/lucid_works/fieldtype.rb +28 -0
  21. data/lib/lucid_works/gem_version.rb +1 -1
  22. data/lib/lucid_works/jdbcdriver.rb +30 -0
  23. data/lib/lucid_works/role.rb +59 -0
  24. data/lib/lucid_works/schema/attribute.rb +86 -0
  25. data/lib/lucid_works/schema/boolean_attribute.rb +34 -0
  26. data/lib/lucid_works/schema/custom_attribute.rb +15 -0
  27. data/lib/lucid_works/schema/integer_attribute.rb +32 -0
  28. data/lib/lucid_works/schema/iso8601_attribute.rb +31 -0
  29. data/lib/lucid_works/schema/string_attribute.rb +22 -0
  30. data/lib/lucid_works/schema.rb +66 -97
  31. data/lib/lucid_works/server.rb +14 -0
  32. data/lib/lucid_works.rb +12 -0
  33. data/spec/fixtures/fake_file_ds_to_be_deleted/.gitkeep +0 -0
  34. data/spec/fixtures/fake_file_ds_to_be_updated/.gitkeep +0 -0
  35. data/spec/fixtures/fake_file_ds_to_get_index_of/.gitkeep +0 -0
  36. data/spec/fixtures/fake_file_ds_to_get_schedule_of/.gitkeep +0 -0
  37. data/spec/fixtures/fake_file_ds_to_get_status_of/.gitkeep +0 -0
  38. data/spec/fixtures/fake_file_ds_to_mess_with_job_of/.gitkeep +0 -0
  39. data/spec/fixtures/fake_file_ds_to_test_progress/.gitkeep +0 -0
  40. data/spec/lib/lucid_works/associations/has_many_spec.rb +4 -3
  41. data/spec/lib/lucid_works/associations/has_one_spec.rb +4 -3
  42. data/spec/lib/lucid_works/base_spec.rb +110 -62
  43. data/spec/lib/lucid_works/collection/activity/history_spec.rb +1 -1
  44. data/spec/lib/lucid_works/collection_spec.rb +17 -17
  45. data/spec/lib/lucid_works/datasource/history_spec.rb +4 -4
  46. data/spec/lib/lucid_works/datasource/status_spec.rb +7 -7
  47. data/spec/lib/lucid_works/datasource_spec.rb +9 -8
  48. data/spec/lib/lucid_works/field_spec.rb +101 -2
  49. data/spec/lib/lucid_works/fieldtype_spec.rb +156 -0
  50. data/spec/lib/lucid_works/schema/attribute_spec.rb +136 -0
  51. data/spec/lib/lucid_works/schema_spec.rb +53 -27
  52. data/spec/spec_helper.rb +3 -50
  53. data/spec/support/active_model_lint.rb +21 -0
  54. data/spec/support/lucid_works.rb +52 -0
  55. metadata +36 -2
@@ -21,5 +21,19 @@ module LucidWorks
21
21
  def uri
22
22
  @host + @path
23
23
  end
24
+ alias :rest_api_uri :uri
25
+
26
+ def crawler(name)
27
+ crawlers.detect { |c| c.name == name }
28
+ end
29
+
30
+ def solr_uri
31
+ "#{host}/solr/"
32
+ end
33
+
34
+ # Location where raw log files may be retrieved
35
+ def logs_url
36
+ "#{host}/logs/"
37
+ end
24
38
  end
25
39
  end
data/lib/lucid_works.rb CHANGED
@@ -25,11 +25,18 @@ require 'lucid_works/associations/has_many'
25
25
  require 'lucid_works/server'
26
26
  require 'lucid_works/base'
27
27
  require 'lucid_works/schema'
28
+ require 'lucid_works/schema/attribute'
29
+ require 'lucid_works/schema/boolean_attribute'
30
+ require 'lucid_works/schema/custom_attribute'
31
+ require 'lucid_works/schema/integer_attribute'
32
+ require 'lucid_works/schema/iso8601_attribute'
33
+ require 'lucid_works/schema/string_attribute'
28
34
 
29
35
  require 'lucid_works/collection'
30
36
  require 'lucid_works/collection/info'
31
37
  require 'lucid_works/collection/index'
32
38
  require 'lucid_works/collection/settings'
39
+ require 'lucid_works/collection/click'
33
40
  require 'lucid_works/activity'
34
41
  require 'lucid_works/activity/status'
35
42
  require 'lucid_works/activity/history'
@@ -41,7 +48,12 @@ require 'lucid_works/datasource/history'
41
48
  require 'lucid_works/datasource/schedule'
42
49
  require 'lucid_works/datasource/crawldata'
43
50
  require 'lucid_works/datasource/job'
51
+ require 'lucid_works/datasource_type'
52
+ require 'lucid_works/datasource_property'
44
53
  require 'lucid_works/field'
54
+ require 'lucid_works/fieldtype'
55
+ require 'lucid_works/jdbcdriver'
56
+ require 'lucid_works/role'
45
57
  require 'lucid_works/synonym'
46
58
  require 'lucid_works/logs'
47
59
  require 'lucid_works/logs/query'
File without changes
File without changes
@@ -129,22 +129,23 @@ describe LucidWorks::Associations::HasMany do
129
129
  context "when save fails" do
130
130
  before do
131
131
  @mock_target.should_receive(:save).and_return(false)
132
+ @mock_target.stub_chain(:errors, :full_messages) { ['an error'] }
132
133
  end
133
134
 
134
135
  it "should raise an error" do
135
136
  lambda {
136
137
  @owner.targets.create!(:foo => :bar)
137
- }.should raise_error
138
+ }.should raise_error(LucidWorks::RecordInvalid)
138
139
  end
139
140
  end
140
141
  end
141
142
 
142
- context "with options :supports_all => true" do
143
+ context "with options :retrieveable_en_masse => true" do
143
144
  before :all do
144
145
  class ::AllableTarget < LucidWorks::Base
145
146
  end
146
147
  class ::Owner
147
- has_many :allable_targets, :supports_all => true
148
+ has_many :allable_targets, :retrieveable_en_masse => true
148
149
  end
149
150
  end
150
151
 
@@ -109,12 +109,13 @@ describe LucidWorks::Associations::HasOne do
109
109
  context "when save fails" do
110
110
  before do
111
111
  @mock_target.should_receive(:save).and_return(false)
112
+ @mock_target.stub_chain(:errors, :full_messages) { ['an error'] }
112
113
  end
113
114
 
114
115
  it "should raise an error" do
115
116
  lambda {
116
117
  @owner.target.create!(:foo => :bar)
117
- }.should raise_error
118
+ }.should raise_error(LucidWorks::RecordInvalid)
118
119
  end
119
120
  end
120
121
  end
@@ -151,12 +152,12 @@ describe LucidWorks::Associations::HasOne do
151
152
  end
152
153
  end
153
154
 
154
- context "with options :supports_all => true" do
155
+ context "with options :retrieveable_en_masse => true" do
155
156
  before :all do
156
157
  class ::TargetWithAll < LucidWorks::Base
157
158
  end
158
159
  class ::Owner
159
- has_one :target_with_all, :supports_all => true
160
+ has_one :target_with_all, :retrieveable_en_masse => true
160
161
  end
161
162
  end
162
163
 
@@ -16,7 +16,7 @@ describe LucidWorks::Base do
16
16
 
17
17
  class Widget < LucidWorks::Base
18
18
  has_one :singleton_widget
19
- has_one :singleton_widget_that_supports_all, :supports_all => true
19
+ has_one :singleton_widget_that_is_retrieveable_en_masse, :retrieveable_en_masse => true
20
20
  end
21
21
 
22
22
  class SingletonWidget < LucidWorks::Base
@@ -35,6 +35,10 @@ describe LucidWorks::Base do
35
35
  end
36
36
  end
37
37
 
38
+ subject { Widget.new(:parent => @server) }
39
+
40
+ it_should_behave_like "ActiveModel"
41
+
38
42
  describe "naming support" do
39
43
  context "for a namespaced model" do
40
44
  class LucidWorks::NamespacedModel < LucidWorks::Base
@@ -308,9 +312,9 @@ describe LucidWorks::Base do
308
312
  mock_singleton1 = double('singleton widget1')
309
313
  mock_singleton2 = double('singleton widget2')
310
314
  mock_singleton3 = double('singleton widget3')
311
- mock_other_widgets_1 = double('other widgets 1', :supports_all? => false)
312
- mock_other_widgets_2 = double('other widgets 2', :supports_all? => false)
313
- mock_other_widgets_3 = double('other widgets 3', :supports_all? => false)
315
+ mock_other_widgets_1 = double('other widgets 1', :retrieveable_en_masse? => false)
316
+ mock_other_widgets_2 = double('other widgets 2', :retrieveable_en_masse? => false)
317
+ mock_other_widgets_3 = double('other widgets 3', :retrieveable_en_masse? => false)
314
318
  SingletonWidget.should_receive(:find).and_return(mock_singleton1, mock_singleton2, mock_singleton3)
315
319
  OtherWidget.should_receive(:find).and_return(mock_other_widgets_1, mock_other_widgets_2, mock_other_widgets_3)
316
320
 
@@ -346,56 +350,13 @@ describe LucidWorks::Base do
346
350
  end
347
351
 
348
352
  context "for a model with a schema" do
349
- before :all do
350
- class WidgetWithBigSchema < LucidWorks::Base
351
- schema do
352
- attribute :astring, :string
353
- attribute :large_number, :integer
354
- attribute :iambool, :boolean
355
- #attribute :when, :iso8601
356
- end
357
- end
358
- class TrueClass
359
- def to_yesno
360
- self ? "yes" : "no"
361
- end
362
- end
363
- end
364
-
365
353
  describe ".human_attribute_value(attribute, value)" do
366
-
367
- context "for an attribute described as :boolean in the schema" do
368
- it "should to_yesno the attribute" do
369
- WidgetWithBigSchema.human_attribute_value(:iambool, true).should == "yes"
370
- end
371
- end
372
-
373
- context "for an attribute described as :integer in the schema" do
374
- before do
375
- # So we can test without actually needing ActionPack
376
- class LucidWorks::Base
377
- def self.number_with_delimiter(x)
378
- x.to_s.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
379
- end
380
- end
381
- end
382
-
383
- it "should number_with_delimeter the attribute" do
384
- WidgetWithBigSchema.human_attribute_value(:large_number, 12345678).should == "12,345,678"
385
- end
386
- end
387
-
388
- context "for an attributed described as :string in the schema" do
389
- it "should just to_s the attribute" do
390
- WidgetWithBigSchema.human_attribute_value(:astring, true).should == "true"
391
- end
354
+ it "should call attribute.human_value with the value" do
355
+ widget = Widget.new(:myattr => 'foo', :parent => @server)
356
+ attr = widget.class.send(:schema)[:myattr]
357
+ attr.should_receive(:human_value).with('foo')
358
+ Widget.human_attribute_value(:myattr, 'foo')
392
359
  end
393
-
394
- #context "for an attribute described as :iso8601 in the schema" do
395
- # it "should convert it to localtime to_s(:short)" do
396
- # @widget.human_attribute_value(:when).should == "19 Mar 10:40"
397
- # end
398
- #end
399
360
  end
400
361
 
401
362
  describe ".to_select(attribute)" do
@@ -641,12 +602,66 @@ describe LucidWorks::Base do
641
602
  end
642
603
 
643
604
  describe "#destroy" do
644
- it "should call RestClient.delete with the appropriate URL" do
645
- widget = Widget.new(:parent => @server)
646
- widget.id = 27
647
- RestClient.should_receive(:delete).with("#{@fake_server_uri}/widgets/27", {})
648
- widget.destroy
605
+ before do
606
+ @widget = Widget.new(:parent => @server)
607
+ @widget.id = 27
608
+ end
609
+
610
+ context "when successfull" do
611
+ it "should call RestClient.delete with the appropriate URL, and return true" do
612
+ RestClient.should_receive(:delete).with("#{@fake_server_uri}/widgets/27", {}).and_return("")
613
+ result = @widget.destroy
614
+ result.should be_true
615
+ end
616
+ end
617
+
618
+ describe "exceptions" do
619
+ context "when it recevies a 409 response" do
620
+ before do
621
+ RestClient.stub(:delete) {
622
+ e = RestClient::Conflict.new
623
+ e.response = "{\"errors\":[{\"message\":\"Field Type currently in use: text_en\"," +
624
+ "\"code\":\"error.invalid.value\",\"key\":\"name\"}]," +
625
+ "\"http_status_name\":\"Conflict\",\"http_status_code\":409}"
626
+ raise e
627
+ }
628
+ end
629
+
630
+ it "should attach errors to the model" do
631
+ @widget.destroy
632
+ @widget.errors.should == {:name => ["Field Type currently in use: text_en"]}
633
+ end
634
+
635
+ it "should return false" do
636
+ result = @widget.destroy
637
+ result.should be_false
638
+ end
639
+ end
640
+
641
+ context "when it receives an unexpected RestClient exception" do
642
+ before do
643
+ RestClient.stub(:delete) { raise RestClient::UnprocessableEntity.new }
644
+ end
645
+
646
+ it "should re-raise the exception" do
647
+ exception = nil
648
+ lambda {
649
+ @widget.destroy
650
+ }.should raise_error(RestClient::UnprocessableEntity)
651
+ end
652
+
653
+ it "should augment the error message" do
654
+ exception = nil
655
+ begin
656
+ @widget.destroy
657
+ rescue Exception => e
658
+ exception = e
659
+ end
660
+ e.message.should =~ /^Unprocessable Entity while performing delete http:\/\/127\.0\.0\.1:123456\/api\/widgets\/27/
661
+ end
662
+ end
649
663
  end
664
+
650
665
  end
651
666
 
652
667
  describe "#human_attribute_value" do
@@ -726,7 +741,8 @@ describe LucidWorks::Base do
726
741
 
727
742
  it "should add attributes to the schema as it loads them" do
728
743
  model = ModelWithDynamicAttrs.new(:parent => @server)
729
- model.class.schema.should_receive(:add_attribute).with(ModelWithDynamicAttrs, :foo, :string)
744
+ mock_attribute = mock('Attribute', :name => 'foo')
745
+ model.class.schema.should_receive(:add_attribute).with(:foo, :string).and_return(mock_attribute)
730
746
  model.stub(:foo=)
731
747
  model.send(:load_attributes, {:foo => 'bar'})
732
748
  end
@@ -771,7 +787,7 @@ describe LucidWorks::Base do
771
787
  class ModelToBeEncoded < LucidWorks::Base
772
788
  schema do
773
789
  attribute :time, :iso8601
774
- attribute :blanktime, :iso8601, :omit_when_blank => true
790
+ attribute :blankish, :string, :omit_when_blank => true
775
791
  end
776
792
  end
777
793
  end
@@ -785,9 +801,41 @@ describe LucidWorks::Base do
785
801
  end
786
802
 
787
803
  describe "for a model with an attr with option :omit_when_blank" do
788
- it "should not encode the attribute" do
789
- model = ModelToBeEncoded.new(:parent => @server, :time => 123, :blanktime => nil)
790
- model.send(:encode).should == '{"time":123}'
804
+
805
+ context "when the attr is nil" do
806
+ before do
807
+ @model = ModelToBeEncoded.new(:parent => @server, :time => 123, :blankish => nil)
808
+ end
809
+ it "should not encode the attribute" do
810
+ @model.send(:encode).should == '{"time":123}'
811
+ end
812
+ end
813
+
814
+ context "when the attr is an empty string" do
815
+ before do
816
+ @model = ModelToBeEncoded.new(:parent => @server, :time => 123, :blankish => "")
817
+ end
818
+ it "should not encode the attribute" do
819
+ @model.send(:encode).should == '{"time":123}'
820
+ end
821
+ end
822
+
823
+ context "when the attr is an empty Array" do
824
+ before do
825
+ @model = ModelToBeEncoded.new(:parent => @server, :time => 123, :blankish => [])
826
+ end
827
+ it "SHOULD encode the attribute" do
828
+ @model.send(:encode).should == '{"time":123,"blankish":[]}'
829
+ end
830
+ end
831
+
832
+ context "when the attr is an empty Hash" do
833
+ before do
834
+ @model = ModelToBeEncoded.new(:parent => @server, :time => 123, :blankish => {})
835
+ end
836
+ it "should not encode the attribute" do
837
+ @model.send(:encode).should == '{"time":123,"blankish":{}}'
838
+ end
791
839
  end
792
840
  end
793
841
  end
@@ -20,7 +20,7 @@ describe LucidWorks::Activity::History do
20
20
  histories.count.should == 1
21
21
  end
22
22
 
23
- it "should subtract crawlStarted form crawlStopped and return the difference in seconds" do
23
+ it "should subtract crawl_started form crawl_stopped and return the difference in seconds" do
24
24
  include ActiveSupport::Duration
25
25
 
26
26
  history = LucidWorks::Activity::History.new(:parent => @activity)
@@ -56,20 +56,20 @@ describe LucidWorks::Collection do
56
56
  end
57
57
  end
58
58
 
59
- context "with a reserved name" do
60
- before do
61
- logs = @server.collection(LucidWorks::Collection::LOGS_COLLECTION_NAME) rescue nil
62
- logs.destroy if logs
63
- @name = LucidWorks::Collection::LOGS_COLLECTION_NAME
64
- end
65
-
66
- it "should not create" do
67
- c = LucidWorks::Collection.create(:name => @name, :parent => @server)
68
- c.should_not be_persisted
69
- c.errors.should_not be_empty
70
- c.errors[:name].should include "is reserved"
71
- end
72
- end
59
+ #context "with a reserved name" do
60
+ # before do
61
+ # logs = @server.collection(LucidWorks::Collection::LOGS_COLLECTION_NAME) rescue nil
62
+ # logs.destroy if logs
63
+ # @name = LucidWorks::Collection::LOGS_COLLECTION_NAME
64
+ # end
65
+ #
66
+ # it "should not create" do
67
+ # c = LucidWorks::Collection.create(:name => @name, :parent => @server)
68
+ # c.should_not be_persisted
69
+ # c.errors.should_not be_empty
70
+ # c.errors[:name].should include "is reserved"
71
+ # end
72
+ #end
73
73
  end
74
74
 
75
75
  describe ".find" do
@@ -284,7 +284,7 @@ describe LucidWorks::Collection do
284
284
  begin
285
285
  sleep 1
286
286
  status = @ds1.status!
287
- end while status.crawlState != 'FINISHED'
287
+ end while status.crawl_state != 'FINISHED'
288
288
  end
289
289
  rescue Timeout::Error
290
290
  raise "Timed out waiting for collection #{@collection.name} datasource #{@ds1.name} crawl to complete"
@@ -338,10 +338,10 @@ describe LucidWorks::Collection do
338
338
  datasources = @collection.datasources(:include => [:histories, :status])
339
339
  datasource = datasources.detect { |ds| ds.id == @ds1.id }
340
340
  datasource.histories.first.should be_a(LucidWorks::Datasource::History)
341
- datasource.histories.first.crawlState.should == "FINISHED"
341
+ datasource.histories.first.crawl_state.should == "FINISHED"
342
342
  status = datasource.status
343
343
  status.should be_a(LucidWorks::Datasource::Status)
344
- status.crawlState.should == 'FINISHED'
344
+ status.crawl_state.should == 'FINISHED'
345
345
  end
346
346
  end
347
347
  end
@@ -13,7 +13,7 @@ describe LucidWorks::Datasource::History do
13
13
  it "should sum counds of Updated, New and Unchanged" do
14
14
  # History doesn't actually descend drectly from server, but for this test that doesn't matter
15
15
  RestClient.should_receive(:get).
16
- with("#{@fake_server_uri}/history").and_return('[{"numUpdated":11,"numNew":22,"numUnchanged":33}]')
16
+ with("#{@fake_server_uri}/history").and_return('[{"num_updated":11,"num_new":22,"num_unchanged":33}]')
17
17
  histories = LucidWorks::Datasource::History.all(:parent => @fake_server)
18
18
  histories.first.doc_count.should == 66
19
19
  end
@@ -21,7 +21,7 @@ describe LucidWorks::Datasource::History do
21
21
 
22
22
  describe "#crawl_stopped" do
23
23
  it "should convert to a Time with the correct value" do
24
- history = LucidWorks::Datasource::History.new(:parent => @fake_server, :crawlStopped => "2011-03-25T21:20:52+0000")
24
+ history = LucidWorks::Datasource::History.new(:parent => @fake_server, :crawl_stopped => "2011-03-25T21:20:52+0000")
25
25
  history.crawl_stopped.should be_a(Time)
26
26
  # Time.iso8601("2011-03-25T21:20:52+0000").to_yaml # => "--- 2011-03-25 21:20:52 Z\n"
27
27
  history.crawl_stopped.should == YAML.load("--- 2011-03-25 21:20:52 Z")
@@ -30,7 +30,7 @@ describe LucidWorks::Datasource::History do
30
30
 
31
31
  describe "#crawl_started" do
32
32
  it "should convert to a Time with the correct value" do
33
- history = LucidWorks::Datasource::History.new(:parent => @fake_server, :crawlStarted => "2011-03-25T21:20:52+0000")
33
+ history = LucidWorks::Datasource::History.new(:parent => @fake_server, :crawl_started => "2011-03-25T21:20:52+0000")
34
34
  history.crawl_started.should be_a(Time)
35
35
  # Time.iso8601("2011-03-25T21:20:52+0000").to_yaml # => "--- 2011-03-25 21:20:52 Z\n"
36
36
  history.crawl_started.should == YAML.load("--- 2011-03-25 21:20:52 Z")
@@ -38,7 +38,7 @@ describe LucidWorks::Datasource::History do
38
38
  end
39
39
 
40
40
  describe "#duration" do
41
- it "should subtract crawlStarted form crawlStopped and return the difference in seconds" do
41
+ it "should subtract crawl_started form crawl_stopped and return the difference in seconds" do
42
42
  include ActiveSupport::Duration
43
43
 
44
44
  history = LucidWorks::Datasource::History.new(:parent => @fake_server)