infopark_cloud_connector 6.8.0.beta.200.891.647580e → 6.8.0.15.a24f5ff
Sign up to get free protection for your applications and to get access to all the features.
- 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
|