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
@@ -1,3 +1,3 @@
1
1
  module LucidWorks
2
- VERSION = "0.6.29"
2
+ VERSION = "0.7.1"
3
3
  end
@@ -0,0 +1,30 @@
1
+ module LucidWorks
2
+
3
+ # This model is a strange beast.
4
+ # You can DELETE it, but that's about it.
5
+ # GET on the plural resource name returns a list of strings, not hashes
6
+ # so we create these things by hand in Collection
7
+ class Jdbcdriver < Base
8
+ belongs_to :collection
9
+
10
+ schema do
11
+ primary_key :name
12
+ attribute :name
13
+ attribute :file
14
+ end
15
+
16
+ validates_presence_of :name
17
+
18
+ # Dont' let LucidWorks::Base do this as it will try to encode us as JSON
19
+ # In this case we need to let RestClient do it's thing and figure out we should do a multipart post
20
+ def save
21
+ return false unless valid?
22
+ RestClient.post(collection_url, :file => file)
23
+ @persisted = true
24
+ rescue RestClient::Exception => e
25
+ @persisted = false
26
+ attach_errors_to_model(e.response)
27
+ return false
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,59 @@
1
+ module LucidWorks
2
+ class Role < Base
3
+ belongs_to :collection
4
+
5
+ schema do
6
+ attribute :name, :string, :primary_key => true, :omit_during_update => true
7
+ attribute :users, :custom
8
+ attribute :groups#, :custom
9
+ attribute :filters#, :custom
10
+ end
11
+
12
+ def users
13
+ @attributes[:users]
14
+ end
15
+
16
+ def groups
17
+ @attributes[:groups]
18
+ end
19
+
20
+ def filters
21
+ # require 'ruby-debug'; debugger
22
+ @attributes[:filters]
23
+ end
24
+
25
+ def filters_for_text_area
26
+ @attributes[:filters].join("\n")
27
+ end
28
+
29
+ #
30
+ # Accept a comma or space separated list of users, convert to array
31
+ #
32
+ def users=(val)
33
+ @attributes[:users] = string_or_array(val, /[\s,]+/) rescue "Can't interpret #{val.class} as list of users"
34
+ end
35
+
36
+ def groups=(val)
37
+ @attributes[:groups] = string_or_array(val, /[\s,]+/) rescue "Can't interpret #{val.class} as list of groups"
38
+ end
39
+
40
+ def filters=(val)
41
+ @attributes[:filters] = string_or_array(val, /\r+/) rescue "Can't interpret #{val.class} as list of groups"
42
+ # require 'ruby-debug'; debugger
43
+ # @attributes[:filters]
44
+ end
45
+
46
+ private
47
+
48
+ def string_or_array(val, pattern)
49
+ if val.is_a?(String)
50
+ val.split(pattern)
51
+ elsif val.is_a?(Array)
52
+ val
53
+ else
54
+ raise "Don't know how to convert #{val.class} to Array"
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,86 @@
1
+ module LucidWorks
2
+ class Schema
3
+
4
+ class Attribute
5
+ ATTRIBUTES_TYPES = [ :string, :integer, :boolean, :iso8601, :custom ]
6
+ RESERVED_ATTRIBUTE_NAMES = %{ class nil? send caller object_id }
7
+
8
+ attr_reader :schema, :name, :values, :origin
9
+
10
+ class << self
11
+
12
+ def factory(schema, name, type, options={})
13
+ raise "Unknown attribute type: #{type.inspect}" unless ATTRIBUTES_TYPES.include?(type)
14
+ attribute_class = ( "LucidWorks::Schema::" + ("#{type}_attribute".classify) ).constantize
15
+ attribute_class.new(schema, name, options)
16
+ end
17
+
18
+ # Change any characters illegal for an identifier to _
19
+ def sanitize_name(identifier) # :nodoc:
20
+ sane_identifier = identifier.to_s.gsub(/[^\w]/, '_')
21
+ sane_identifier = "_#{sane_identifier}" if RESERVED_ATTRIBUTE_NAMES.include?(sane_identifier)
22
+ sane_identifier.to_sym
23
+ end
24
+ end
25
+
26
+ def initialize(schema, name, options={})
27
+ @schema = schema
28
+ @true_name = name.to_s # External representation. Will be used when sending data back to REST API
29
+ @name = self.class.sanitize_name(name) # Internal representation. A symbol.
30
+ @origin = options[:origin]
31
+ @omit_during_update = options[:omit_during_update]
32
+ @omit_when_blank = options[:omit_when_blank]
33
+ @nil_when_blank = options[:nil_when_blank]
34
+ @values = options[:values]
35
+ end
36
+
37
+ def type
38
+ raise "type() method must be implemented by Attribute subclass"
39
+ end
40
+
41
+ def omit_during_update? ; @omit_during_update end
42
+ def omit_when_blank? ; @omit_when_blank end
43
+ def nil_when_blank? ; @nil_when_blank end
44
+
45
+ def create_accessors_for_attribute(klass) # :nodoc:
46
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
47
+ def #{name} # def foo
48
+ @attributes[:#{name}] # @attributes[:foo]
49
+ end # end
50
+ EOF
51
+ end
52
+
53
+ def encode_and_insert(value, hash, is_update) # :nodoc:
54
+ return if omit_during_update? && is_update
55
+ return if omit_when_blank? && (value.nil? || value == "")
56
+ hash[@true_name.to_s] = encode(value)
57
+ end
58
+
59
+ def human_value(value)
60
+ if values
61
+ # If this attribute was defined with a set of :values,
62
+ # assume we can get translations for those valuesfrom the L10n database.
63
+ l10n_scope = %w{activemodel models} + schema.model.name.underscore.split('/') + [name]
64
+ return I18n.t(value, :scope => l10n_scope, :default => value)
65
+ end
66
+ value.to_s
67
+
68
+ rescue
69
+ value.to_s
70
+ end
71
+
72
+ def to_select
73
+ raise "Can't to_select for attribute #{name} as it has no values" unless values
74
+ values.map do |value|
75
+ [human_value(value), value]
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def encode(value)
82
+ value
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,34 @@
1
+ module LucidWorks
2
+ class Schema
3
+
4
+ class BooleanAttribute < Attribute
5
+
6
+ def type
7
+ :boolean
8
+ end
9
+
10
+ def create_accessors_for_attribute(klass) # :nodoc:
11
+ super
12
+
13
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
14
+ def #{name}? # def foo?
15
+ @attributes[:#{name}] # @attributes[:foo]
16
+ end # end
17
+
18
+ def #{name}=(new_value) # def foo=(new_value)
19
+ begin # begin
20
+ @attributes[:#{name}] = to_bool(new_value) # @attributes[:foo] = to_bool(new_value)
21
+ rescue # rescue
22
+ raise "Expected #{name} to take a boolean"+ # raise "Expected <some_bool> to take a boolean
23
+ " value, but '\#\{new_value}' is ambiguous" # " value, but 'frozbot' is ambiguous"
24
+ end # end
25
+ end # end
26
+ EOF
27
+ end
28
+
29
+ def human_value(value)
30
+ value.to_yesno
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ module LucidWorks
2
+ class Schema
3
+
4
+ class CustomAttribute < Attribute
5
+
6
+ def type
7
+ :custom
8
+ end
9
+
10
+ def create_accessors_for_attribute(klass) # :nodoc:
11
+ # Do nothing. Developer will provide own accessors.
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ module LucidWorks
2
+ class Schema
3
+
4
+ class IntegerAttribute < Attribute
5
+ include ActionView::Helpers::NumberHelper rescue nil
6
+
7
+ def type
8
+ :integer
9
+ end
10
+
11
+ def create_accessors_for_attribute(klass) # :nodoc:
12
+ super
13
+
14
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
15
+ def #{name}=(new_value)
16
+ if new_value.blank? && (self.class.schema[:#{name}].nil_when_blank? ||
17
+ self.class.schema[:#{name}].omit_when_blank?)
18
+ new_value = nil
19
+ else
20
+ new_value = new_value.to_i
21
+ end
22
+ @attributes[:#{name}] = new_value
23
+ end
24
+ EOF
25
+ end
26
+
27
+ def human_value(value)
28
+ number_with_delimiter(value)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module LucidWorks
2
+ class Schema
3
+
4
+ class Iso8601Attribute < Attribute
5
+
6
+ def type
7
+ :iso8601
8
+ end
9
+
10
+ def create_accessors_for_attribute(klass) # :nodoc:
11
+ super
12
+
13
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
14
+ def #{name}=(new_value)
15
+ if new_value.kind_of?(String)
16
+ @attributes[:#{name}] = Time.iso8601(new_value)
17
+ else
18
+ @attributes[:#{name}] = new_value
19
+ end
20
+ end
21
+ EOF
22
+ end
23
+
24
+ private
25
+
26
+ def encode(value)
27
+ value.iso8601 rescue value
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ module LucidWorks
2
+ class Schema
3
+
4
+ class StringAttribute < Attribute
5
+
6
+ def type
7
+ :string
8
+ end
9
+
10
+ def create_accessors_for_attribute(klass) # :nodoc:
11
+ super
12
+
13
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
14
+ def #{name}=(new_value)
15
+ new_value = nil if new_value.blank? && self.class.schema[:#{name}].nil_when_blank?
16
+ @attributes[:#{name}] = new_value
17
+ end
18
+ EOF
19
+ end
20
+ end
21
+ end
22
+ end
@@ -3,7 +3,8 @@ module LucidWorks
3
3
  # Schema is used to delare attributes for a model.
4
4
 
5
5
  class Schema < ActiveSupport::HashWithIndifferentAccess
6
- ATTRIBUTES_TYPES = [ :string, :integer, :boolean, :iso8601, :custom ]
6
+
7
+ attr_reader :model
7
8
 
8
9
  # Initializes the schema, taking a block of schema declarations.
9
10
  # Typically it is called from LucidWorks::Base, e.g.:
@@ -22,11 +23,17 @@ module LucidWorks
22
23
  # end
23
24
  # end
24
25
  #
25
- def initialize
26
+ def initialize(model)
27
+ @model = model
26
28
  @primary_key = :id
27
29
  @dynamic_attributes = true
28
30
  end
29
31
 
32
+ # If this model's primary key is something other than 'id',
33
+ # use the primary_key method it indicate that. e.g.
34
+ #
35
+ # primary_key "name"
36
+
30
37
  def primary_key(key=nil)
31
38
  @primary_key = key.to_sym if key
32
39
  @primary_key
@@ -41,9 +48,62 @@ module LucidWorks
41
48
  @dynamic_attributes = !!on unless on.nil?
42
49
  @dynamic_attributes
43
50
  end
44
-
51
+
45
52
  alias :dynamic_attributes? :dynamic_attributes
46
53
 
54
+ def has_attribute?(name)
55
+ has_key? Attribute.sanitize_name(name)
56
+ end
57
+
58
+ def find_or_create_attribute(name)
59
+ attrname = Attribute.sanitize_name(name)
60
+ attribute = fetch(attrname, nil)
61
+ unless attribute
62
+ if dynamic_attributes?
63
+ attribute = add_attribute(name, :string)
64
+ else
65
+ raise "unknown attribute: \"#{attr}\""
66
+ end
67
+ end
68
+ attribute
69
+ end
70
+
71
+ # Used for classes that have no predefined schema.
72
+ # When the class is retrieved.
73
+ def add_attribute(name, type=:string) # :nodoc:
74
+ raise "Class #{model.name} already has attribute #{name}" if has_attribute?(Attribute.sanitize_name(name))
75
+ attribute = Attribute.factory(self, name, type, :origin => :added_later)
76
+ attribute.create_accessors_for_attribute(model)
77
+ self[attribute.name] = attribute
78
+ end
79
+
80
+ # Create accessors for all attributes defined in the schema.
81
+ def create_accessors_for_attributes(klass) # :nodoc:
82
+ self.values.each do |attr|
83
+ attr.create_accessors_for_attribute(klass)
84
+ end
85
+ end
86
+
87
+ # Reset the schema to the originally defined version (before we added a bunch of attributes during load or create)
88
+ def reset!
89
+ each do |name, attr|
90
+ if attr.origin != :original
91
+ model.class_eval <<-EOF, __FILE__, __LINE__+1
92
+ undef_method(:#{name})
93
+ undef_method(:"#{name}=")
94
+ EOF
95
+ delete(name)
96
+ end
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ ###################################################################################################################
103
+ # The following are private methods, that will be accessed when LucidWorks::Base does an
104
+ # instance_eval in response to a schema(&block) call.
105
+ ###################################################################################################################
106
+
47
107
  # Declare a single attribute.
48
108
  #
49
109
  # Attributes may be of the following types:
@@ -66,9 +126,10 @@ module LucidWorks
66
126
  # [:omit_when_blank => true] When this attribute is blank?, don't send it to the server during save.
67
127
 
68
128
  def attribute(name, type=:string, options={})
69
- raise "Unknown attribute type: #{type.inspect}" unless ATTRIBUTES_TYPES.include?(type)
70
129
  primary_key name if options.delete(:primary_key)
71
- self[name] = options.merge(:type => type)
130
+ options[:origin] = :original
131
+ attr = Attribute.factory(self, name, type, options)
132
+ self[attr.name] = attr
72
133
  end
73
134
 
74
135
  # Specify multiple attributes. Options apply to all attributes, e.g.
@@ -85,97 +146,5 @@ module LucidWorks
85
146
  attribute name, type, options
86
147
  end
87
148
  end
88
-
89
- def has_attribute?(name)
90
- has_key? sanitize_identifier(name)
91
- end
92
-
93
- def attrs_to_omit_during_update
94
- select { |k,v| v['omit_during_update'] == true }.keys
95
- end
96
-
97
- # Used for classes that have no predefined schema.
98
- # When the class is retrieved.
99
- def add_attribute(klass, name, type=:string) # :nodoc:
100
- attr = sanitize_identifier(name)
101
- raise "Class #{klass.name} already has attribute #{attr}" if has_attribute?(attr)
102
- self[attr] = { :type => type }
103
- create_attribute(klass, attr)
104
- end
105
-
106
- # Create accessors for all attributes defined in the schema.
107
- def create_accessors_for_attributes(klass) # :nodoc:
108
- self.keys.each do |attr|
109
- create_attribute(klass, attr)
110
- end
111
- end
112
-
113
- def create_attribute(klass, attribute) # :nodoc:
114
- klass.class_eval <<-EOF, __FILE__, __LINE__+1
115
- def #{attribute} # def foo
116
- @attributes[:#{attribute}] # @attributes[:foo]
117
- end # end
118
- EOF
119
-
120
- case self[attribute][:type]
121
- when :boolean
122
- klass.class_eval <<-EOF, __FILE__, __LINE__+1
123
- def #{attribute}? # def foo?
124
- @attributes[:#{attribute}] # @attributes[:foo]
125
- end # end
126
-
127
- def #{attribute}=(new_value) # def foo=(new_value)
128
- begin # begin
129
- @attributes[:#{attribute}] = to_bool(new_value) # @attributes[:foo] = to_bool(new_value)
130
- rescue # rescue
131
- raise "Expected #{attribute} to take a boolean"+ # raise "Expected <some_bool> to take a boolean
132
- " value, but '\#\{new_value}' is ambiguous" # " value, but 'frozbot' is ambiguous"
133
- end # end
134
- end # end
135
- EOF
136
- when :string
137
- klass.class_eval <<-EOF, __FILE__, __LINE__+1
138
- def #{attribute}=(new_value) # def foo=(new_value)
139
- new_value = nil if new_value.blank? && self.class.schema[:#{attribute}][:nil_when_blank]
140
- @attributes[:#{attribute}] = new_value # @attributes[:foo] = new_value
141
- end # end
142
- EOF
143
- when :integer
144
- klass.class_eval <<-EOF, __FILE__, __LINE__+1
145
- def #{attribute}=(new_value)
146
- if new_value.blank? && (self.class.schema[:#{attribute}][:nil_when_blank] ||
147
- self.class.schema[:#{attribute}][:omit_when_blank])
148
- new_value = nil
149
- else
150
- new_value = new_value.to_i
151
- end
152
- @attributes[:#{attribute}] = new_value
153
- end
154
- EOF
155
- when :iso8601
156
- klass.class_eval <<-EOF, __FILE__, __LINE__+1
157
- def #{attribute}=(new_value)
158
- if new_value.kind_of?(String)
159
- @attributes[:#{attribute}] = Time.iso8601(new_value)
160
- else
161
- @attributes[:#{attribute}] = new_value
162
- end
163
- end
164
- EOF
165
- when :custom
166
- # Do nothing. Developer will provide own accessors.
167
- else
168
- klass.class_eval <<-EOF, __FILE__, __LINE__+1
169
- def #{attribute}=(new_value) # def foo=(new_value)
170
- @attributes[:#{attribute}] = new_value # @attributes[:foo] = new_value
171
- end # end
172
- EOF
173
- end
174
- end
175
-
176
- # Change any characters illegal for an identifier to _
177
- def sanitize_identifier(identifier) # :nodoc:
178
- identifier.to_s.gsub(/[^\w]/, '_').to_sym
179
- end
180
149
  end
181
150
  end