lucid_works 0.6.29 → 0.7.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 (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)