infopark_cloud_connector 6.8.0.beta.200.891.647580e → 6.8.0.15.a24f5ff
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.
- data/lib/rails_connector/cache_middleware.rb +2 -2
- data/lib/rails_connector/cms_api_search_request.rb +60 -0
- data/lib/rails_connector/cms_backend.rb +27 -0
- data/lib/rails_connector/default_search_request.rb +1 -1
- data/lib/rails_connector/dynamo_cms_backend.rb +121 -0
- data/lib/rails_connector/obj.rb +35 -138
- data/lib/rails_connector/obj_body.rb +2 -2
- data/lib/rails_connector/obj_data.rb +19 -0
- data/lib/rails_connector/obj_data_from_database.rb +126 -0
- data/lib/rails_connector/obj_data_from_hash.rb +20 -0
- data/lib/rails_connector/revision.rb +0 -110
- metadata +24 -18
- data/lib/rails_connector/attribute.rb +0 -20
- data/lib/rails_connector/obj_class.rb +0 -22
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'restclient'
|
3
|
+
|
4
|
+
module RailsConnector
|
5
|
+
|
6
|
+
# This class provides a basic implementation for accessing the search using the cms api.
|
7
|
+
# It can be activated by making it the superclass of SearchRequest.
|
8
|
+
# It should be customized by subclassing.
|
9
|
+
class CmsApiSearchRequest
|
10
|
+
|
11
|
+
# Takes +query_string+ and +options+ for accessing Cms Api Search.
|
12
|
+
#
|
13
|
+
# +options+ is a hash and may include:
|
14
|
+
#
|
15
|
+
# <tt>:limit</tt>:: The maximum number of hits
|
16
|
+
# <tt>:offset</tt>:: The search offset
|
17
|
+
# <tt>:url</tt>:: The URL to the CMS API search
|
18
|
+
# <tt>:login</tt>:: The login for the CMS API search
|
19
|
+
# <tt>:api_key</tt>:: The api_key for the CMS API search
|
20
|
+
def initialize(query_string, options = {})
|
21
|
+
@query_string = query_string
|
22
|
+
@options = Configuration.cms_api_options.merge(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Accesses Cms Api Search using #query and fetches search hits.
|
26
|
+
def fetch_hits
|
27
|
+
hits = JSON.parse(
|
28
|
+
RestClient::Request.execute({
|
29
|
+
:method => :get,
|
30
|
+
:url => url,
|
31
|
+
:user => @options[:login],
|
32
|
+
:password => @options[:api_key],
|
33
|
+
:headers => {
|
34
|
+
:content_type => :json,
|
35
|
+
:accept => :json,
|
36
|
+
:params => {
|
37
|
+
:query => @query_string,
|
38
|
+
:offset => @options[:offset],
|
39
|
+
:limit => @options[:limit],
|
40
|
+
},
|
41
|
+
},
|
42
|
+
})
|
43
|
+
)
|
44
|
+
|
45
|
+
result = SES::SearchResult.new(hits['total'])
|
46
|
+
hits['results'].each do |hit|
|
47
|
+
hard_coded_score = 1
|
48
|
+
result << SES::Hit.new(hit, hard_coded_score, nil)
|
49
|
+
end
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def url
|
56
|
+
"#{@options[:url]}/revisions/#{Revision.current.id}/objs/search"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RailsConnector
|
2
|
+
|
3
|
+
class CmsBackend
|
4
|
+
|
5
|
+
def self.current
|
6
|
+
@current ||= DynamoCmsBackend.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.begin_caching
|
10
|
+
current.begin_caching
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.end_caching
|
14
|
+
current.end_caching
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.find_obj_data_by(revision, index, keys)
|
18
|
+
current.find_obj_data_by(revision, index, keys)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.caching?
|
22
|
+
current.caching?
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module RailsConnector
|
2
|
+
|
3
|
+
class DynamoCmsBackend
|
4
|
+
CACHE_PREFIX = 'revision'
|
5
|
+
|
6
|
+
def begin_caching
|
7
|
+
@editable_cache = Configuration.cache_editable_workspaces ? persistent_cache : Cache.new
|
8
|
+
@read_only_cache = persistent_cache
|
9
|
+
end
|
10
|
+
|
11
|
+
def end_caching
|
12
|
+
@editable_cache = @read_only_cache = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_obj_data_by(revision, index, keys)
|
16
|
+
raw_data =
|
17
|
+
if caching?
|
18
|
+
find_obj_data_from_cache_or_database_by(revision, index, keys)
|
19
|
+
else
|
20
|
+
find_obj_data_from_database_by(revision, index, keys)
|
21
|
+
end
|
22
|
+
|
23
|
+
raw_data.map do |raw_list|
|
24
|
+
raw_list.map do |raw_obj_data|
|
25
|
+
ObjDataFromDatabase.new(raw_obj_data, revision)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def caching?
|
31
|
+
@read_only_cache && @editable_cache
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def persistent_cache
|
37
|
+
Cache.new(:fallback_backend => Rails.cache, :cache_prefix => CACHE_PREFIX)
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_obj_data_from_database_by(revision, index, keys)
|
41
|
+
return [] if keys.blank?
|
42
|
+
instrumenter = ActiveSupport::Notifications.instrumenter
|
43
|
+
instrumenter.instrument(
|
44
|
+
"cms_load.rails_connector", :name => "Obj Load", :index => index, :keys => keys
|
45
|
+
) do
|
46
|
+
keys.map do |key|
|
47
|
+
results = revision.chain.query(index, key)
|
48
|
+
results.values.map { |row| extract_obj_data(row) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_obj_data_from_cache_or_database_by(revision, index, keys)
|
54
|
+
keys_from_database = []
|
55
|
+
# load results from cache
|
56
|
+
results_from_cache = keys.map do |key|
|
57
|
+
cache_for(revision).read(cache_key_for(revision, index, key)).tap do |objs|
|
58
|
+
keys_from_database << key unless objs
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# load cache misses from database and store them in cache
|
63
|
+
results_from_database = find_obj_data_from_database_by(revision, index, keys_from_database)
|
64
|
+
keys_from_database.each_with_index do |key, key_number|
|
65
|
+
store_obj_data_list_in_cache(revision, index, key, results_from_database[key_number])
|
66
|
+
end
|
67
|
+
|
68
|
+
# combine the results
|
69
|
+
results_from_cache.map do |objs_from_cache|
|
70
|
+
objs_from_cache || results_from_database.shift
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
UNIQUE_INDICES = [:id, :path, :permalink].freeze
|
75
|
+
OBJ_PROPERTY_VALUE_TO_RANGE_VALUE_CONVERSIONS = {
|
76
|
+
:path => PathConversion.method(:path_from_list)
|
77
|
+
}.freeze
|
78
|
+
|
79
|
+
def store_obj_data_list_in_cache(revision, index, key, obj_data_list)
|
80
|
+
obj_data_list.each do |obj_data|
|
81
|
+
values = obj_data["values"]
|
82
|
+
UNIQUE_INDICES.each do |unique_index|
|
83
|
+
index_value = values["_#{unique_index}"]
|
84
|
+
if (converter = OBJ_PROPERTY_VALUE_TO_RANGE_VALUE_CONVERSIONS[unique_index])
|
85
|
+
index_value = converter.call(index_value)
|
86
|
+
end
|
87
|
+
store_item_in_cache(revision, unique_index, index_value, [obj_data])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
unless UNIQUE_INDICES.include?(index)
|
91
|
+
store_item_in_cache(revision, index, key, obj_data_list)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def store_item_in_cache(revision, index, key, item)
|
96
|
+
cache_for(revision).write(cache_key_for(revision, index, key), item) if caching?
|
97
|
+
end
|
98
|
+
|
99
|
+
def cache_key_for(revision, index, key)
|
100
|
+
"#{revision.id}/obj/#{index}/#{key}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def extract_obj_data(data)
|
104
|
+
{
|
105
|
+
"values" => data["values"].merge(
|
106
|
+
"_id" => data["obj_id"],
|
107
|
+
"_obj_type" => data["obj_type"],
|
108
|
+
"_obj_class" => data["obj_class_name"]
|
109
|
+
),
|
110
|
+
"rtc_ref" => data["rtc_ref"],
|
111
|
+
"ext_ref" => data["ext_ref"],
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def cache_for(revision)
|
116
|
+
revision.editable ? @editable_cache : @read_only_cache
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
data/lib/rails_connector/obj.rb
CHANGED
@@ -9,7 +9,6 @@ module RailsConnector
|
|
9
9
|
include Kvom::ModelIdentity
|
10
10
|
|
11
11
|
include DateAttribute
|
12
|
-
include StringTagging
|
13
12
|
include SEO
|
14
13
|
include ObjBody
|
15
14
|
|
@@ -19,21 +18,23 @@ module RailsConnector
|
|
19
18
|
# Create a new Obj instance with the given values and attributes.
|
20
19
|
# Normally this method should not be used.
|
21
20
|
# Instead Objs should be loaded from the cms database.
|
22
|
-
def initialize(
|
23
|
-
|
21
|
+
def initialize(obj_data = {})
|
22
|
+
if !obj_data.respond_to?(:value_and_type_of)
|
23
|
+
obj_data = ObjDataFromHash.new(obj_data)
|
24
|
+
end
|
25
|
+
|
26
|
+
update_data(obj_data)
|
24
27
|
end
|
25
28
|
|
26
29
|
# instantiate an Obj instance from obj_data.
|
27
30
|
# May result in an instance of a subclass of Obj according to STI rules.
|
28
31
|
def self.instantiate(obj_data) # :nodoc:
|
29
|
-
obj_class = obj_data
|
30
|
-
Obj.compute_type(obj_class).new(
|
31
|
-
obj_data["values"], obj_data
|
32
|
-
)
|
32
|
+
obj_class = obj_data.value_of("_obj_class")
|
33
|
+
Obj.compute_type(obj_class).new(obj_data)
|
33
34
|
end
|
34
35
|
|
35
36
|
def id
|
36
|
-
|
37
|
+
read_attribute('_id')
|
37
38
|
end
|
38
39
|
|
39
40
|
### FINDERS ####################
|
@@ -105,7 +106,7 @@ module RailsConnector
|
|
105
106
|
# accepts the name of an "obj_by" - view and a list of keys.
|
106
107
|
# returns a list of lists of Objs: a list of Objs for each given keys.
|
107
108
|
def self.find_objs_by(view, keys) # :nodoc:
|
108
|
-
Revision.current
|
109
|
+
CmsBackend.find_obj_data_by(Revision.current, view, keys).map do |list|
|
109
110
|
list.map { |obj_data| Obj.instantiate(obj_data) }
|
110
111
|
end
|
111
112
|
end
|
@@ -163,7 +164,7 @@ module RailsConnector
|
|
163
164
|
end
|
164
165
|
|
165
166
|
def path_list # :nodoc:
|
166
|
-
|
167
|
+
read_attribute('_path') || []
|
167
168
|
end
|
168
169
|
|
169
170
|
# returns the Obj's name, i.e. the last component of the path.
|
@@ -207,7 +208,7 @@ module RailsConnector
|
|
207
208
|
|
208
209
|
# returns the obj's permalink.
|
209
210
|
def permalink
|
210
|
-
|
211
|
+
read_attribute('_permalink')
|
211
212
|
end
|
212
213
|
|
213
214
|
# This method determines the controller that should be invoked when the Obj is requested.
|
@@ -236,12 +237,12 @@ module RailsConnector
|
|
236
237
|
end
|
237
238
|
|
238
239
|
def title
|
239
|
-
|
240
|
+
read_attribute('title')
|
240
241
|
end
|
241
242
|
|
242
243
|
# Returns the type of the object: :document, :publication, :image or :generic
|
243
244
|
def object_type
|
244
|
-
|
245
|
+
read_attribute('_obj_type').to_sym
|
245
246
|
end
|
246
247
|
|
247
248
|
# Returns true if image? or generic?
|
@@ -286,7 +287,7 @@ module RailsConnector
|
|
286
287
|
# (for example a teaser) and will not be delivered by the rails application
|
287
288
|
# as a standalone web page.
|
288
289
|
def suppressed?
|
289
|
-
|
290
|
+
read_attribute('_suppress_export') ? true : false
|
290
291
|
end
|
291
292
|
|
292
293
|
# Returns true if the export of the object is not suppressed and the content is active?
|
@@ -360,7 +361,7 @@ module RailsConnector
|
|
360
361
|
end
|
361
362
|
|
362
363
|
def sort_order # :nodoc:
|
363
|
-
|
364
|
+
read_attribute('_sort_order') == 1 ? "descending" : "ascending"
|
364
365
|
end
|
365
366
|
|
366
367
|
def sort_type1 # :nodoc:
|
@@ -376,15 +377,15 @@ module RailsConnector
|
|
376
377
|
end
|
377
378
|
|
378
379
|
def sort_key1 # :nodoc:
|
379
|
-
|
380
|
+
read_attribute('_sort_key1')
|
380
381
|
end
|
381
382
|
|
382
383
|
def sort_key2 # :nodoc:
|
383
|
-
|
384
|
+
read_attribute('_sort_key2')
|
384
385
|
end
|
385
386
|
|
386
387
|
def sort_key3 # :nodoc:
|
387
|
-
|
388
|
+
read_attribute('_sort_key3')
|
388
389
|
end
|
389
390
|
|
390
391
|
# Returns the Object with the given name next in the hierarchy
|
@@ -440,28 +441,28 @@ module RailsConnector
|
|
440
441
|
# Notice that the ruby class of this Obj instance will NOT change,
|
441
442
|
# even if the obj_class in the database has changed.
|
442
443
|
def reload
|
443
|
-
obj_data = Revision.current
|
444
|
-
update_data(obj_data
|
444
|
+
obj_data = CmsBackend.find_obj_data_by(Revision.current, :id, [id.to_s]).first.first
|
445
|
+
update_data(obj_data)
|
445
446
|
end
|
446
447
|
|
447
448
|
def text_links
|
448
|
-
|
449
|
+
read_attribute('_text_links')
|
449
450
|
end
|
450
451
|
|
451
452
|
def obj_class
|
452
|
-
|
453
|
+
read_attribute('_obj_class')
|
453
454
|
end
|
454
455
|
|
455
456
|
def last_changed
|
456
|
-
|
457
|
+
read_attribute('_last_changed')
|
457
458
|
end
|
458
459
|
|
459
460
|
def valid_from
|
460
|
-
|
461
|
+
read_attribute('_valid_from')
|
461
462
|
end
|
462
463
|
|
463
464
|
def valid_until
|
464
|
-
|
465
|
+
read_attribute('_valid_until')
|
465
466
|
end
|
466
467
|
|
467
468
|
# For a binary Obj, the content_type is equal to the content_type of it's body (i.e. it's data).
|
@@ -496,12 +497,6 @@ module RailsConnector
|
|
496
497
|
end
|
497
498
|
end
|
498
499
|
|
499
|
-
# Returns a list of the names of all custom attributes defined for this Obj as Symbols.
|
500
|
-
# A custom attribute is a user-defined attribute, i.e. one that is not built-in in the CMS.
|
501
|
-
def custom_attribute_names
|
502
|
-
obj_class_instance.attributes.map(&:to_sym)
|
503
|
-
end
|
504
|
-
|
505
500
|
def self.preview_time=(t) # :nodoc:
|
506
501
|
Thread.current[:preview_time] = t
|
507
502
|
end
|
@@ -515,42 +510,27 @@ module RailsConnector
|
|
515
510
|
end
|
516
511
|
|
517
512
|
def has_attribute?(name)
|
518
|
-
|
513
|
+
data_from_cms.has_attribute?(name.to_s)
|
519
514
|
end
|
520
515
|
|
521
516
|
private
|
522
517
|
|
523
|
-
|
524
|
-
ObjClass.by_name(obj_class)
|
525
|
-
end
|
518
|
+
attr_accessor :data_from_cms
|
526
519
|
|
527
|
-
def update_data(
|
528
|
-
|
529
|
-
meta ||= {}
|
530
|
-
@rtc_ref = meta['rtc_ref']
|
531
|
-
@ext_ref = meta['ext_ref']
|
520
|
+
def update_data(data)
|
521
|
+
self.data_from_cms = data
|
532
522
|
@attribute_cache = {}
|
533
523
|
end
|
534
524
|
|
535
525
|
def read_attribute(attribute_name)
|
536
|
-
attribute_type = Attribute.type_of(attribute_name)
|
537
|
-
if type_of(attribute_name) == attribute_type
|
538
|
-
read_attribute_value(attribute_name, attribute_type)
|
539
|
-
else
|
540
|
-
default_attribute_value(attribute_type)
|
541
|
-
end
|
542
|
-
end
|
543
|
-
|
544
|
-
def read_attribute_value(attribute_name, attribute_type = nil)
|
545
526
|
@attribute_cache.fetch(attribute_name) do
|
546
|
-
attribute_type
|
547
|
-
attribute_value = read_raw_attribute_value(attribute_name)
|
527
|
+
(raw_value, attribute_type) = data_from_cms.value_and_type_of(attribute_name)
|
548
528
|
@attribute_cache[attribute_name] =
|
549
|
-
|
529
|
+
prepare_attribute_value(raw_value, attribute_type)
|
550
530
|
end
|
551
531
|
end
|
552
532
|
|
553
|
-
def prepare_attribute_value(
|
533
|
+
def prepare_attribute_value(attribute_value, attribute_type)
|
554
534
|
case attribute_type
|
555
535
|
when :markdown
|
556
536
|
StringTagging.tag_as_markdown(attribute_value, self)
|
@@ -559,64 +539,12 @@ module RailsConnector
|
|
559
539
|
when :date
|
560
540
|
DateAttribute.parse(attribute_value) if attribute_value
|
561
541
|
when :linklist
|
562
|
-
|
563
|
-
LinkList.new(attribute_value && attribute_value.values)
|
564
|
-
else
|
565
|
-
LinkList.new(attribute_value)
|
566
|
-
end
|
542
|
+
LinkList.new(attribute_value)
|
567
543
|
else
|
568
544
|
attribute_value
|
569
545
|
end
|
570
546
|
end
|
571
547
|
|
572
|
-
def default_attribute_value(attribute_type)
|
573
|
-
case attribute_type
|
574
|
-
when :linklist
|
575
|
-
LinkList.new(nil)
|
576
|
-
when :multienum
|
577
|
-
[]
|
578
|
-
else
|
579
|
-
nil
|
580
|
-
end
|
581
|
-
end
|
582
|
-
|
583
|
-
def attributes
|
584
|
-
@attributes ||= @rtc_ref ? attributes_from_rtc : {}
|
585
|
-
end
|
586
|
-
|
587
|
-
def attributes_from_rtc
|
588
|
-
rtc = DictStorage.get(@rtc_ref)
|
589
|
-
if rtc['obj_classes'] && rtc['attributes'] && oc = rtc['obj_classes'][@values['_obj_class']]
|
590
|
-
rtc['attributes'].inject({}) do |attrs, (name, value)|
|
591
|
-
attrs[name] = value if oc['attributes'] && oc['attributes'].include?(name)
|
592
|
-
attrs
|
593
|
-
end
|
594
|
-
else
|
595
|
-
{}
|
596
|
-
end
|
597
|
-
end
|
598
|
-
|
599
|
-
def type_of(key)
|
600
|
-
key = key.to_s
|
601
|
-
case key
|
602
|
-
when "_text_links"
|
603
|
-
:linklist
|
604
|
-
when "_valid_from"
|
605
|
-
:date
|
606
|
-
when "_valid_until"
|
607
|
-
:date
|
608
|
-
when "_last_changed"
|
609
|
-
:date
|
610
|
-
when "title"
|
611
|
-
:html
|
612
|
-
else
|
613
|
-
if attr_def = attributes[key]
|
614
|
-
type = attr_def["type"]
|
615
|
-
type.to_sym if type
|
616
|
-
end
|
617
|
-
end
|
618
|
-
end
|
619
|
-
|
620
548
|
def as_date(value)
|
621
549
|
DateAttribute.parse(value) unless value.nil?
|
622
550
|
end
|
@@ -650,37 +578,7 @@ module RailsConnector
|
|
650
578
|
end
|
651
579
|
|
652
580
|
def converted_sort_type(attribute)
|
653
|
-
|
654
|
-
end
|
655
|
-
|
656
|
-
def converted_sort_key(attribute)
|
657
|
-
key = read_attribute_value(attribute)
|
658
|
-
case key
|
659
|
-
when "_valid_until"
|
660
|
-
"_valid_until"
|
661
|
-
when "_valid_from"
|
662
|
-
"_valid_from"
|
663
|
-
when "_last_changed"
|
664
|
-
"_last_changed"
|
665
|
-
else
|
666
|
-
key
|
667
|
-
end
|
668
|
-
end
|
669
|
-
|
670
|
-
def read_raw_attribute_value(attribute_name)
|
671
|
-
return @values[attribute_name] if @values.key?(attribute_name)
|
672
|
-
if @ext_ref && (attribute_name == "_text_links" || ?_ != attribute_name[0])
|
673
|
-
extend_values_with_dict_storage_values
|
674
|
-
end
|
675
|
-
@values[attribute_name]
|
676
|
-
end
|
677
|
-
|
678
|
-
def extend_values_with_dict_storage_values
|
679
|
-
# may raise Kvom::Storage::NotFound
|
680
|
-
values = DictStorage.get(@ext_ref)
|
681
|
-
@values.reverse_merge!(values)
|
682
|
-
@ext_ref = nil
|
683
|
-
@values
|
581
|
+
read_attribute(attribute) == 1 ? "numeric" : "alphaNumeric"
|
684
582
|
end
|
685
583
|
|
686
584
|
class << self
|
@@ -705,4 +603,3 @@ module RailsConnector
|
|
705
603
|
end
|
706
604
|
|
707
605
|
end
|
708
|
-
|
@@ -7,7 +7,7 @@ module ObjBody
|
|
7
7
|
if binary?
|
8
8
|
nil
|
9
9
|
else
|
10
|
-
StringTagging.tag_as_html(
|
10
|
+
StringTagging.tag_as_html(read_attribute('body'), self)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -52,7 +52,7 @@ module ObjBody
|
|
52
52
|
private
|
53
53
|
|
54
54
|
def find_blob
|
55
|
-
blob_spec =
|
55
|
+
blob_spec = read_attribute('blob')
|
56
56
|
Blob.find(blob_spec["id"], :context => path) if blob_spec
|
57
57
|
end
|
58
58
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#:enddoc:
|
2
|
+
module RailsConnector
|
3
|
+
|
4
|
+
class ObjData
|
5
|
+
def value_of(attribute_name)
|
6
|
+
value_and_type_of(attribute_name).first
|
7
|
+
end
|
8
|
+
|
9
|
+
def value_and_type_of(attribute_name)
|
10
|
+
raise "implement in subclass"
|
11
|
+
end
|
12
|
+
|
13
|
+
def has_attribute?(name)
|
14
|
+
raise "implement in subclass"
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#:enddoc:
|
2
|
+
module RailsConnector
|
3
|
+
|
4
|
+
class ObjDataFromDatabase < ObjData
|
5
|
+
|
6
|
+
def initialize(data, revision)
|
7
|
+
@rtc_ref = data["rtc_ref"]
|
8
|
+
@values = data["values"]
|
9
|
+
@ext_ref = data["ext_ref"]
|
10
|
+
@revision = revision
|
11
|
+
end
|
12
|
+
|
13
|
+
def value_and_type_of(attribute_name)
|
14
|
+
if internal_attribute?(attribute_name)
|
15
|
+
attribute_type = type_of_internal(attribute_name)
|
16
|
+
|
17
|
+
attribute_value = read_value(attribute_name)
|
18
|
+
if attribute_name == '_text_links'
|
19
|
+
attribute_value = attribute_value && attribute_value.values
|
20
|
+
end
|
21
|
+
else
|
22
|
+
attribute_type = current_attribute_type(attribute_name)
|
23
|
+
if legacy_attribute_type(attribute_name) == attribute_type
|
24
|
+
attribute_value = read_value(attribute_name)
|
25
|
+
else
|
26
|
+
attribute_value = default_attribute_value(attribute_type)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
[attribute_value, attribute_type]
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_attribute?(name)
|
34
|
+
obj_class_attributes.include?(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :values, :ext_ref, :rtc_ref, :revision
|
40
|
+
|
41
|
+
def current_attribute_type(name)
|
42
|
+
revision.attributes[name]["type"].to_sym
|
43
|
+
end
|
44
|
+
|
45
|
+
def obj_class_attributes
|
46
|
+
name = values["_obj_class"]
|
47
|
+
if data = revision.obj_classes[name]
|
48
|
+
data["attributes"] || []
|
49
|
+
else
|
50
|
+
raise "Could not find ObjClass with name #{name} in Revision #{revision.id}!"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def read_value(attribute_name)
|
55
|
+
return values[attribute_name] if values.key?(attribute_name)
|
56
|
+
if ext_ref && (attribute_name == "_text_links" || ?_ != attribute_name[0])
|
57
|
+
extend_values_with_dict_storage_values
|
58
|
+
end
|
59
|
+
values[attribute_name]
|
60
|
+
end
|
61
|
+
|
62
|
+
def extend_values_with_dict_storage_values
|
63
|
+
# may raise Kvom::Storage::NotFound
|
64
|
+
ext_values = DictStorage.get(ext_ref)
|
65
|
+
values.reverse_merge!(ext_values)
|
66
|
+
@ext_ref = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
SPECIAL_INTERNAL_ATTRIBUTES = Set.new(%w[title body blob])
|
70
|
+
|
71
|
+
def internal_attribute?(attribute_name)
|
72
|
+
?_ == attribute_name[0] || SPECIAL_INTERNAL_ATTRIBUTES.include?(attribute_name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def type_of_internal(key)
|
76
|
+
case key
|
77
|
+
when "_text_links"
|
78
|
+
:linklist
|
79
|
+
when "_valid_from"
|
80
|
+
:date
|
81
|
+
when "_valid_until"
|
82
|
+
:date
|
83
|
+
when "_last_changed"
|
84
|
+
:date
|
85
|
+
when "title"
|
86
|
+
:html
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def legacy_attribute_type(name)
|
91
|
+
if attr_def = legacy_attributes[name]
|
92
|
+
type = attr_def["type"]
|
93
|
+
type.to_sym if type
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def default_attribute_value(attribute_type)
|
98
|
+
case attribute_type
|
99
|
+
when :linklist
|
100
|
+
[]
|
101
|
+
when :multienum
|
102
|
+
[]
|
103
|
+
else
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def legacy_attributes
|
109
|
+
@attributes ||=
|
110
|
+
begin
|
111
|
+
rtc = DictStorage.get(rtc_ref)
|
112
|
+
if rtc['obj_classes'] && rtc['attributes'] && oc = rtc['obj_classes'][values['_obj_class']]
|
113
|
+
rtc['attributes'].inject({}) do |attrs, (name, value)|
|
114
|
+
attrs[name] = value if oc['attributes'] && oc['attributes'].include?(name)
|
115
|
+
attrs
|
116
|
+
end
|
117
|
+
else
|
118
|
+
{}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#:enddoc:
|
2
|
+
module RailsConnector
|
3
|
+
|
4
|
+
class ObjDataFromHash < ObjData
|
5
|
+
def initialize(hash)
|
6
|
+
@hash = hash
|
7
|
+
end
|
8
|
+
|
9
|
+
def value_and_type_of(attribute_name)
|
10
|
+
[@hash[attribute_name], nil]
|
11
|
+
end
|
12
|
+
|
13
|
+
def has_attribute?(name)
|
14
|
+
@hash.has_key?(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
@@ -2,8 +2,6 @@
|
|
2
2
|
module RailsConnector
|
3
3
|
|
4
4
|
class Revision < CmsBaseModel
|
5
|
-
CACHE_PREFIX = 'revision'
|
6
|
-
|
7
5
|
self.key_prefix = "rev"
|
8
6
|
|
9
7
|
property :generation
|
@@ -34,31 +32,6 @@ module RailsConnector
|
|
34
32
|
find_by_label("published")
|
35
33
|
end
|
36
34
|
|
37
|
-
def self.begin_caching
|
38
|
-
@editable_cache = Configuration.cache_editable_workspaces ? persistent_cache : Cache.new
|
39
|
-
@read_only_cache = persistent_cache
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.end_caching
|
43
|
-
@editable_cache = @read_only_cache = nil
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.caching?
|
47
|
-
@read_only_cache && @editable_cache
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.cache_for(revision)
|
51
|
-
revision.editable ? @editable_cache : @read_only_cache
|
52
|
-
end
|
53
|
-
|
54
|
-
def find_obj_data_by(index, keys)
|
55
|
-
if self.class.caching?
|
56
|
-
find_obj_data_from_cache_or_database_by(index, keys)
|
57
|
-
else
|
58
|
-
find_obj_data_from_database_by(index, keys)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
35
|
def chain
|
63
36
|
@chain ||= Chain.build_for(self, content_cache)
|
64
37
|
end
|
@@ -97,91 +70,8 @@ module RailsConnector
|
|
97
70
|
|
98
71
|
private
|
99
72
|
|
100
|
-
def self.persistent_cache
|
101
|
-
Cache.new(:fallback_backend => Rails.cache, :cache_prefix => CACHE_PREFIX)
|
102
|
-
end
|
103
|
-
|
104
|
-
def find_obj_data_from_database_by(index, keys)
|
105
|
-
return [] if keys.blank?
|
106
|
-
instrumenter = ActiveSupport::Notifications.instrumenter
|
107
|
-
instrumenter.instrument(
|
108
|
-
"cms_load.rails_connector", :name => "Obj Load", :index => index, :keys => keys
|
109
|
-
) do
|
110
|
-
keys.map do |key|
|
111
|
-
results = chain.query(index, key)
|
112
|
-
results.values.map { |row| extract_obj_data(row) }
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def find_obj_data_from_cache_or_database_by(index, keys)
|
118
|
-
keys_from_database = []
|
119
|
-
# load results from cache
|
120
|
-
results_from_cache = keys.map do |key|
|
121
|
-
cache.read(cache_key_for(index, key)).tap do |objs|
|
122
|
-
keys_from_database << key unless objs
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# load cache misses from database and store them in cache
|
127
|
-
results_from_database = find_obj_data_from_database_by(index, keys_from_database)
|
128
|
-
keys_from_database.each_with_index do |key, key_number|
|
129
|
-
store_obj_data_list_in_cache(index, key, results_from_database[key_number])
|
130
|
-
end
|
131
|
-
|
132
|
-
# combine the results
|
133
|
-
results_from_cache.map do |objs_from_cache|
|
134
|
-
objs_from_cache || results_from_database.shift
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
UNIQUE_INDICES = [:id, :path, :permalink].freeze
|
139
|
-
OBJ_PROPERTY_VALUE_TO_RANGE_VALUE_CONVERSIONS = {
|
140
|
-
:path => PathConversion.method(:path_from_list)
|
141
|
-
}.freeze
|
142
|
-
|
143
|
-
def store_obj_data_list_in_cache(index, key, obj_data_list)
|
144
|
-
obj_data_list.each do |obj_data|
|
145
|
-
values = obj_data["values"]
|
146
|
-
UNIQUE_INDICES.each do |unique_index|
|
147
|
-
index_value = values["_#{unique_index}"]
|
148
|
-
if (converter = OBJ_PROPERTY_VALUE_TO_RANGE_VALUE_CONVERSIONS[unique_index])
|
149
|
-
index_value = converter.call(index_value)
|
150
|
-
end
|
151
|
-
store_item_in_cache(unique_index, index_value, [obj_data])
|
152
|
-
end
|
153
|
-
end
|
154
|
-
unless UNIQUE_INDICES.include?(index)
|
155
|
-
store_item_in_cache(index, key, obj_data_list)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def store_item_in_cache(index, key, item)
|
160
|
-
cache.write(cache_key_for(index, key), item) if self.class.caching?
|
161
|
-
end
|
162
|
-
|
163
|
-
def cache_key_for(index, key)
|
164
|
-
"#{id}/obj/#{index}/#{key}"
|
165
|
-
end
|
166
|
-
|
167
|
-
def extract_obj_data(data)
|
168
|
-
{
|
169
|
-
"values" => data["values"].merge(
|
170
|
-
"_id" => data["obj_id"],
|
171
|
-
"_obj_type" => data["obj_type"],
|
172
|
-
"_obj_class" => data["obj_class_name"]
|
173
|
-
),
|
174
|
-
"rtc_ref" => data["rtc_ref"],
|
175
|
-
"ext_ref" => data["ext_ref"],
|
176
|
-
}
|
177
|
-
end
|
178
|
-
|
179
73
|
def rtc
|
180
74
|
@rtc ||= DictStorage.get(read_attribute("rtc_ref"))
|
181
75
|
end
|
182
|
-
|
183
|
-
def cache
|
184
|
-
self.class.cache_for(self)
|
185
|
-
end
|
186
76
|
end
|
187
77
|
end
|
metadata
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: infopark_cloud_connector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: -
|
5
|
-
prerelease:
|
4
|
+
hash: -358797853
|
5
|
+
prerelease: 9
|
6
6
|
segments:
|
7
7
|
- 6
|
8
8
|
- 8
|
9
9
|
- 0
|
10
|
-
-
|
11
|
-
-
|
12
|
-
-
|
13
|
-
-
|
14
|
-
-
|
15
|
-
|
10
|
+
- 15
|
11
|
+
- a
|
12
|
+
- 24
|
13
|
+
- f
|
14
|
+
- 5
|
15
|
+
- ff
|
16
|
+
version: 6.8.0.15.a24f5ff
|
16
17
|
platform: ruby
|
17
18
|
authors:
|
18
19
|
- Infopark AG
|
@@ -20,7 +21,7 @@ autorequire:
|
|
20
21
|
bindir: bin
|
21
22
|
cert_chain: []
|
22
23
|
|
23
|
-
date: 2012-
|
24
|
+
date: 2012-09-13 00:00:00 +02:00
|
24
25
|
default_executable:
|
25
26
|
dependencies:
|
26
27
|
- !ruby/object:Gem::Dependency
|
@@ -60,17 +61,18 @@ dependencies:
|
|
60
61
|
requirements:
|
61
62
|
- - "="
|
62
63
|
- !ruby/object:Gem::Version
|
63
|
-
hash: -
|
64
|
+
hash: -358797853
|
64
65
|
segments:
|
65
66
|
- 6
|
66
67
|
- 8
|
67
68
|
- 0
|
68
|
-
-
|
69
|
-
-
|
70
|
-
-
|
71
|
-
-
|
72
|
-
-
|
73
|
-
|
69
|
+
- 15
|
70
|
+
- a
|
71
|
+
- 24
|
72
|
+
- f
|
73
|
+
- 5
|
74
|
+
- ff
|
75
|
+
version: 6.8.0.15.a24f5ff
|
74
76
|
version_requirements: *id003
|
75
77
|
name: kvom
|
76
78
|
prerelease: false
|
@@ -85,17 +87,19 @@ extra_rdoc_files: []
|
|
85
87
|
|
86
88
|
files:
|
87
89
|
- lib/infopark_cloud_connector.rb
|
88
|
-
- lib/rails_connector/attribute.rb
|
89
90
|
- lib/rails_connector/blob.rb
|
90
91
|
- lib/rails_connector/cache.rb
|
91
92
|
- lib/rails_connector/cache_middleware.rb
|
92
93
|
- lib/rails_connector/chain.rb
|
94
|
+
- lib/rails_connector/cms_api_search_request.rb
|
95
|
+
- lib/rails_connector/cms_backend.rb
|
93
96
|
- lib/rails_connector/cms_base_model.rb
|
94
97
|
- lib/rails_connector/content_cache.rb
|
95
98
|
- lib/rails_connector/controller_runtime.rb
|
96
99
|
- lib/rails_connector/date_attribute.rb
|
97
100
|
- lib/rails_connector/default_search_request.rb
|
98
101
|
- lib/rails_connector/dict_storage.rb
|
102
|
+
- lib/rails_connector/dynamo_cms_backend.rb
|
99
103
|
- lib/rails_connector/elasticsearch_request.rb
|
100
104
|
- lib/rails_connector/errors.rb
|
101
105
|
- lib/rails_connector/link.rb
|
@@ -103,7 +107,9 @@ files:
|
|
103
107
|
- lib/rails_connector/named_link.rb
|
104
108
|
- lib/rails_connector/obj.rb
|
105
109
|
- lib/rails_connector/obj_body.rb
|
106
|
-
- lib/rails_connector/
|
110
|
+
- lib/rails_connector/obj_data.rb
|
111
|
+
- lib/rails_connector/obj_data_from_database.rb
|
112
|
+
- lib/rails_connector/obj_data_from_hash.rb
|
107
113
|
- lib/rails_connector/path_conversion.rb
|
108
114
|
- lib/rails_connector/permission.rb
|
109
115
|
- lib/rails_connector/rack_middlewares.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
#:enddoc:
|
2
|
-
module RailsConnector
|
3
|
-
class Attribute
|
4
|
-
attr_reader :name, :type
|
5
|
-
|
6
|
-
def initialize(data)
|
7
|
-
@name, @type = data['name'], data['type'].to_sym
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.by_name(name)
|
11
|
-
data = Revision.current.attributes[name.to_s]
|
12
|
-
new(data) if data
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.type_of(name)
|
16
|
-
attribute = by_name(name)
|
17
|
-
attribute.type if attribute
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
#:enddoc:
|
2
|
-
module RailsConnector
|
3
|
-
class ObjClass
|
4
|
-
attr_reader :name, :attributes
|
5
|
-
|
6
|
-
def initialize(data)
|
7
|
-
@name, @attributes = data['name'], data['attributes'] || []
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.by_name(name)
|
11
|
-
if data = Revision.current.obj_classes[name.to_s]
|
12
|
-
new(data)
|
13
|
-
else
|
14
|
-
raise ResourceNotFound, "Could not find #{self} with name #{name}"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def has_attribute?(attribute_name)
|
19
|
-
@attributes.include?(attribute_name.to_s)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|