daengine 0.5.13 → 0.6

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +5 -0
  3. data/app/controllers/digital_assets_controller.rb +29 -46
  4. data/app/helpers/digital_assets_helper.rb +11 -2
  5. data/app/models/content_service_resource.rb +15 -15
  6. data/app/models/digital_asset.rb +83 -94
  7. data/app/models/teamsite_digital_asset_shim.rb +253 -0
  8. data/app/service/digital_asset_lookup_service.rb +47 -47
  9. data/bin/process_assets +6 -7
  10. data/bin/process_availability +7 -8
  11. data/bin/process_taxonomy +7 -8
  12. data/config/routes.rb +7 -7
  13. data/lib/daengine.rb +1 -13
  14. data/lib/daengine/content_service_processor.rb +24 -24
  15. data/lib/daengine/digital_asset_processor.rb +4 -0
  16. data/lib/daengine/teamsite_metadata_parser.rb +3 -2
  17. data/lib/daengine/version.rb +1 -1
  18. data/lib/tasks/daengine_tasks.rake +0 -9
  19. data/spec/acceptance/digital_assets_spec.rb +116 -0
  20. data/spec/controllers/digital_assets_controller_spec.rb +14 -99
  21. data/spec/dummy/config/environments/test.rb +1 -1
  22. data/spec/dummy/log/development.log +0 -0
  23. data/spec/dummy/log/test.log +8802 -0
  24. data/spec/factories.rb +8 -32
  25. data/spec/lib/content_service_processor_spec.rb +30 -30
  26. data/spec/lib/teamsite_metadata_parser_spec.rb +26 -19
  27. data/spec/mock_data/bulk-ssc_deploy.xml +900 -900
  28. data/spec/mock_data/daengine.yml +1 -1
  29. data/spec/mock_data/digitalAssets/GK-66261382-96be-4a92-839a-73467e89e1b4.txt +289 -289
  30. data/spec/mock_data/digitalAssets/TEST_FINRA_DOC.doc +0 -0
  31. data/spec/mock_data/digitalAssets/m_gyt-709d8ae1-31f1-46ea-b448-33f43dd5140f.html +1008 -1008
  32. data/spec/mock_data/selective_new_package.xml +55 -2
  33. data/spec/mock_data/taxonomy/taxonomyengine.yml +1 -1
  34. data/spec/models/digital_asset_spec.rb +23 -28
  35. data/spec/service/digital_asset_lookup_service_spec.rb +75 -79
  36. data/spec/spec_helper.rb +18 -1
  37. metadata +23 -7
  38. data/lib/daengine/digital_asset_extension_processor.rb +0 -28
  39. data/spec/lib/digital_asset_extension_processor_spec.rb +0 -32
  40. data/spec/mock_data/merrill_lynch_extension.json +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ebcd4cba573731d63a838c277fbfe4c1c215e41b
4
- data.tar.gz: 74a976fc90d02603798519425d07b5111cc65b77
3
+ metadata.gz: fa5de682d42dc3019a48e76744f587b5069cc9e3
4
+ data.tar.gz: 7faca1c4e9ae36521292defd53daf425ec6663c8
5
5
  SHA512:
6
- metadata.gz: c1b087c4e52e0ae3664e50c020cd313b1fe116f4195e7a3b7fbbe52b77c93730c008a76aa129b14fe9d5d4c86ebf556db84e63d36bd9785390bc4d25d9cf81fa
7
- data.tar.gz: 4d71a5b4bb3156dadfed0b4e4c97e21679f1017efa69c7cecb6d35fd619fc2495aaeeb125e185ad30d669cedc1dec88b0b765786b5fef4ee9307168091f08c14
6
+ metadata.gz: 48d2ae730ab81c8680fe78a1de0ca08a509309b43bf24f5b00b1b3a79ce2cad2c781b19a82df2a304e916d514a5354c22ba7c2920a6c1c00a2f5badb7217e445
7
+ data.tar.gz: 7e9e48c77c9dda6ae586a69a2f63968cebf3c30886997c4be0e83590b8e2f1a3f0a8539f9801c30ec2c1dc8a49ef6566265b31de4ea9dca27603a4f284e37dba
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ rescue LoadError
11
11
  require 'rake/rdoctask'
12
12
  RDoc::Task = Rake::RDocTask
13
13
  end
14
+ require 'rspec/core/rake_task'
14
15
 
15
16
  RDoc::Task.new(:rdoc) do |rdoc|
16
17
  rdoc.rdoc_dir = 'rdoc'
@@ -23,6 +24,10 @@ end
23
24
  APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
24
25
  load 'rails/tasks/engine.rake'
25
26
 
27
+ RSpec::Core::RakeTask.new(:spec)
28
+ task :default => :spec
29
+ spec = Gem::Specification.find_by_name 'rspec_api_documentation'
30
+ load "#{spec.gem_dir}/lib/tasks/docs.rake"
26
31
 
27
32
 
28
33
  Bundler::GemHelper.install_tasks
@@ -7,10 +7,13 @@ class DigitalAssetsController < ApplicationController
7
7
  CACHE_LAST_PARSE_TIME = 'last_parse_time'
8
8
  # GET /digital_assets
9
9
  # GET /digital_assets.json
10
+ #/digital_assets/search/sami_code=92023
11
+ #/digital_assets/search/sami_code=NE00192&title=Fund%20Prospectus&fund_code=20293
10
12
  def index
11
- @digital_assets = DigitalAsset.all
13
+ @digital_assets = request.query_parameters.present? ? search_da(request.query_parameters) : DigitalAsset.all
12
14
  respond_with(@digital_assets)
13
15
  end
16
+ alias :search :index
14
17
 
15
18
  # GET /digital_assets/1
16
19
  # GET /digital_assets/1.json
@@ -19,13 +22,33 @@ class DigitalAssetsController < ApplicationController
19
22
  respond_with(@digital_asset)
20
23
  end
21
24
 
22
- #/digital_assets/search/sami_code=92023
23
- #/digital_assets/search/sami_code=NE00192&title=Fund%20Prospectus&fund_code=20293
24
- def search
25
- @digital_assets = search_da(params)
26
- respond_with(@digital_assets)
25
+ def update
26
+ da_passed = params[:digital_asset]
27
+ da = DigitalAsset.find_or_initialize_by(digital_asset_id: da_passed[:digital_asset_id])
28
+ da.update_attributes! da_passed
29
+ head :ok
27
30
  end
28
31
 
32
+ alias :create :update
33
+
34
+ def destroy
35
+ da = DigitalAsset.where(:digital_asset_id => params[:id])
36
+ da[0].delete if da.present?
37
+ head :ok
38
+ end
39
+
40
+ def updated_time
41
+ Daengine.log "updated_time params #{params.inspect}", "info"
42
+ ids = params[:ids]
43
+ updated_time = Hash.new
44
+ ids.each do |id|
45
+ da = DigitalAsset.where(:digital_asset_id => id)
46
+ updated_time[id] = da[0].doc_changed_at if da.present?
47
+ end
48
+ Daengine.log "updated_time result #{updated_time.inspect}", "info"
49
+ render json: updated_time.to_json, status: :ok
50
+ end
51
+
29
52
  def fund_docs
30
53
  @digital_assets = []
31
54
  fund_doctypes = {:doctype => [
@@ -43,45 +66,5 @@ class DigitalAssetsController < ApplicationController
43
66
  respond_with(@digital_assets)
44
67
  end
45
68
 
46
- def sync_assets
47
- time0 = Rails.cache.read(CACHE_LAST_PARSE_TIME)
48
- if time0.nil?
49
- time0 = 2.days.ago
50
- end
51
- logger.info "Last time when ssc deploy files were read: #{time0.inspect}"
52
- time1 = Time.new
53
- logger.info "Current time: #{time1.inspect}"
54
-
55
- Rails.cache.write(CACHE_LAST_PARSE_TIME, time1)
56
- deploy_files= []
57
-
58
- start_directory = EDIST['digital_assets_directory']
59
- logger.info "Reading digital asset deployment files from #{start_directory}"
60
- if (File::directory?(start_directory))
61
- Dir.foreach(start_directory) do |entry|
62
- if (!File::directory?(entry))
63
- filename = start_directory + entry
64
- difference0 = File.mtime(filename)- time0 #To-Do - We should be looking at created time - ctime
65
- difference1 = File.mtime(filename) - time1
66
- if ((difference0 >= 0) & (difference1 < 0))
67
- if(/bulk-ssc_|selective-ssc_/ =~ filename)
68
- deploy_files << filename
69
- end
70
- end
71
- end
72
- end
73
- end
74
-
75
- deploy_files.each do |filename|
76
- #parse the file and add content to database.
77
- logger.info "Processing file #{filename} found."
78
- file = File.expand_path(filename, __FILE__)
79
- open_file = open(file, 'rb')
80
- Etl::TeamsiteMetadataParser.parse_tuple_file(open_file)
81
- logger.info "Finished parsing #{filename}."
82
- end
83
-
84
- head :accepted
85
- end
86
69
 
87
70
  end
@@ -3,11 +3,20 @@ module DigitalAssetsHelper
3
3
  def search_da(params)
4
4
  digital_assets = []
5
5
  # loop thru each parameter that matches one of the method signatures
6
+ # x_is for singular, x_in for arrays, x_since for dates
6
7
  digital_assets = params.keys.select do |pk|
7
- DigitalAsset.respond_to?("#{pk}_is".to_sym) or DigitalAsset.respond_to?("#{pk}_in".to_sym)
8
+ DigitalAsset.respond_to?("#{pk}_is".to_sym) or DigitalAsset.respond_to?("#{pk}_in".to_sym) or DigitalAsset.respond_to?("#{pk}_since".to_sym)
8
9
  end.reduce(DigitalAsset) do |sum, key|
9
10
  # for each key, call the 'named query' method with the value given and chain...
10
- method = DigitalAsset.respond_to?("#{key}_in".to_sym) ? "#{key}_in".to_sym : "#{key}_is".to_sym
11
+ method = case
12
+ when DigitalAsset.respond_to?("#{key}_in".to_sym)
13
+ "#{key}_in".to_sym
14
+ when DigitalAsset.respond_to?("#{key}_since".to_sym)
15
+ "#{key}_since".to_sym
16
+ else
17
+ "#{key}_is".to_sym
18
+ end
19
+ # method = DigitalAsset.respond_to?("#{key}_in".to_sym) ? "#{key}_in".to_sym : "#{key}_is".to_sym
11
20
  sum.send(method, method.to_s.end_with?('in') ? params[key].to_a : params[key]) # should return result of the send call for chaining
12
21
  end
13
22
  digital_assets.respond_to?(:each) ? digital_assets : []
@@ -1,16 +1,16 @@
1
- require 'active_resource'
2
- require 'daengine'
3
- # Represents a generic piece of content for display on an OFI web property
4
- # This model represents the 'human edited' version of website content, final displayed
5
- # pages will be 'value added' with system-sourced data and 'mashed-in' data
6
- #
7
- class ContentServiceResource < ActiveResource::Base
8
-
9
- # self.site = Daengine.config[:content_service_url]
10
- self.prefix = "/litcenter-service/query/"
11
- self.element_name = "resource"
12
-
13
- def self.find_all
14
- ContentServiceResource.find(:all, :params => {:contentQuery => "audienceIds='490,5270';;expired='false'"})
15
- end
1
+ require 'active_resource'
2
+ require 'daengine'
3
+ # Represents a generic piece of content for display on an OFI web property
4
+ # This model represents the 'human edited' version of website content, final displayed
5
+ # pages will be 'value added' with system-sourced data and 'mashed-in' data
6
+ #
7
+ class ContentServiceResource < ActiveResource::Base
8
+
9
+ # self.site = Daengine.config[:content_service_url]
10
+ self.prefix = "/litcenter-service/query/"
11
+ self.element_name = "resource"
12
+
13
+ def self.find_all
14
+ ContentServiceResource.find(:all, :params => {:contentQuery => "audienceIds='490,5270';;expired='false'"})
15
+ end
16
16
  end
@@ -8,87 +8,86 @@ class DigitalAsset
8
8
  field :changed_at, type: Time
9
9
  field :audiences, type: Array, default: []
10
10
  field :sami_code, type: String
11
- field :product_ids, type: Array, default: []
12
11
  field :published_at, type: Time
13
12
  field :unpublished_at, type: Time
14
13
  field :expires_at, type: Time
15
14
  field :guid, type: String
16
- # field :fund_ids, type: Array, default: []
17
15
  field :business_owner, type: String
18
16
  field :summary, type: String
19
- field :content_organization_ids, type: Array, default: []
20
- field :program_ids, type: Array, default: []
21
-
22
17
  field :omniture_codes, type: Array, default: []
23
18
  field :orderable, :type => Boolean, default: false
24
-
25
- field :ml_category, type: String
26
- field :control_number, type: String
27
- field :key_accounts, type: Array, default: []
28
-
29
- key :guid
19
+ field :product_ids, type: Array, default: []
20
+ field :program_ids, type: Array, default: []
21
+ # refactor version:
22
+ field :path, type: String
23
+ field :legacy_path, type: String
24
+ field :doc_changed_at, type: Time
25
+ field :content_type, type: String
26
+ field :pages, type: Integer, default: 1
27
+ field :size, type: String
28
+ field :mime_type, type: String
29
+ field :subject, type: String
30
+ field :keywords, type: Array, default: []
31
+ field :author, type: String
32
+ field :finra_path, type: String
33
+ field :fund_codes, type: Array, default: []
34
+ field :digital_asset_id, type: String
35
+ key :digital_asset_id
30
36
 
31
37
  # field :documents, type: Hash
38
+ # embeds_many :documents, :class_name => 'DigitalAsset::Document'
39
+ # accepts_nested_attributes_for :documents
32
40
 
33
- embeds_many :documents, :class_name => 'DigitalAsset::Document'
34
-
35
- accepts_nested_attributes_for :documents
36
41
 
37
42
  #Exclude XBRL documents from all queries
38
- default_scope excludes(:'documents.content_type' => "LDJDCMAIK") #Had to use static value instead of a Constant
43
+ # default_scope excludes(:'content_type' => "LDJDCMAIK") #Had to use static value instead of a Constant
39
44
 
40
45
  scope :title_is, ->(title) { where(:title => title)}
41
46
  scope :business_owner_is, ->(business_owner) { where(:business_owner => business_owner)}
42
47
  scope :guid_is, ->(guid) { where(:guid => guid)}
43
- # scope :funds_in, ->(fund_id) { where(:fund_ids.in => fund_id)}
48
+ scope :digital_asset_id_is, ->(id) { where(:digital_asset_id => id)}
49
+ scope :fund_in, ->(fund_code) {where(:fund_codes.in => fund_code)}
44
50
  scope :audience_in, ->(audience_id) {where(:audiences.in => audience_id)}
45
51
  scope :audience_investor_approved, -> {where(:audiences.in => [Audience::INVESTOR_APPROVED])}
46
52
 
53
+ scope :published_since, ->(since) {where(:published_at.gte => since)}
47
54
  scope :content_organization_in, ->(content_organization_id) {where(:content_organization_ids.in => content_organization_id)}
48
55
  scope :program_id_in, ->(program_id) {where(:program_ids.in => program_id)}
49
56
  scope :sami_is, ->(sami_code) {where(:sami_code => sami_code)}
50
57
  scope :sami_in, ->(sami_codes) {where(:sami_code.in => sami_codes)}
51
- scope :path_is, ->(path) {where(:'documents.path' => path)}
52
- scope :doctype_in, ->(types) {where(:'documents.content_type'.in => types)}
53
- scope :content_type_in, ->(types) {where(:'documents.content_type'.in => types)}
58
+ scope :path_is, ->(path) {where(:'path' => path)}
59
+ scope :doctype_in, ->(types) {where(:'content_type'.in => types)}
60
+ scope :content_type_in, ->(types) {where(:'content_type'.in => types)}
54
61
  scope :product_in, ->(types) {where(:product_ids.in => types)}
55
62
  scope :stale, -> {where(:updated_at.lte => 2.minutes.ago)}
56
63
  scope :orderable_is, ->(orderable) {where(:orderable => orderable)}
57
64
  scope :orderable, -> {where(orderable: true)}
58
- scope :has_finra, -> {where(:'documents.content_type' => ContentType::FINRA)}
59
65
  scope :audience_in, ->(audience) {where(:audiences.in => audience)}
60
66
  scope :alphabetical, order_by(:title => :asc)
61
- scope :not_xbrl, -> {excludes(:'documents.content_type' => ContentType::XBRL_DOCUMENT)}
62
-
63
- scope :key_account_in, ->(key_account) {where(:key_accounts => key_account)}
64
-
65
- #scope :order_by_fund, order_by[[:product_ids, :asc]]
66
- #default_scope {not_in(:'documents.content_type' => ["LDJDCMAIK"])}
67
+ scope :not_xbrl, -> {excludes(:'content_type' => ContentType::XBRL_DOCUMENT)}
67
68
 
68
69
  # validations
69
- validates_presence_of :guid, :title, :changed_at, :published_at,
70
- :expires_at, :audiences, :documents
71
-
70
+ validates_presence_of :digital_asset_id, :title, :changed_at, :published_at,
71
+ :expires_at, :audiences, :path
72
+ validates_uniqueness_of :path, :digital_asset_id
72
73
  validate :validate_future_expiration
73
74
 
74
- # validates_uniqueness_of :guid
75
-
76
- def as_json(opts = {})
77
- super(opts).merge({:comp_fundcode => fund_code, :content_type_id => content_type_id, :latest_doc_changed_at => latest_doc_changed_at})
78
- end
75
+ # def as_json(opts = {})
76
+ # super(opts).merge({:comp_fundcode => fund_codes, :content_type_id => content_type_id, :latest_doc_changed_at => latest_doc_changed_at})
77
+ # end
79
78
 
80
79
  def self.purge!
81
- # last_update = DigitalAsset.desc(:updated_at).try(:first).try :updated_at
82
80
  DigitalAsset.stale.destroy_all if bulk_processed?
83
81
  end
84
82
 
85
83
  def latest_doc_changed_at
86
- documents.reduce(nil) do |latest_date, d|
87
- unless d.content_type == '549'
88
- latest_date = d.doc_changed_at if (latest_date == nil || latest_date < d.doc_changed_at)
89
- end
90
- latest_date
91
- end
84
+ doc_changed_at
85
+ # documents.reduce(nil) do |latest_date, d|
86
+ # unless d.content_type == '549'
87
+ # latest_date = d.doc_changed_at if (latest_date == nil || latest_date < d.doc_changed_at)
88
+ # end
89
+ # latest_date
90
+ # end
92
91
  end
93
92
 
94
93
  def validate_future_expiration
@@ -99,39 +98,39 @@ class DigitalAsset
99
98
  (stale.count.to_f / self.count) <= 0.05
100
99
  end
101
100
 
102
- def path_is(path)
103
- documents.where(path: path).first unless documents.blank?
104
- end
101
+ # def path_is(path)
102
+ # documents.where(path: path).first unless documents.blank?
103
+ # end
105
104
 
106
- def doc_changed_at(path)
107
- path_is(path).try(:doc_changed_at)
108
- end
105
+ # def doc_changed_at(path)
106
+ # path_is(path).try(:doc_changed_at)
107
+ # end
109
108
 
110
- def doc_size
111
- first_non_finra.try(:size)
112
- end
109
+ # def doc_size
110
+ # first_non_finra.try(:size)
111
+ # end
113
112
 
114
- def content_type_ids
115
- ids = []
116
- documents.try(:each) do |d|
117
- ids << d.content_type
118
- end
119
- ids
120
- end
121
- alias :doctype_ids :content_type_ids
113
+ # def content_type_ids
114
+ # ids = []
115
+ # documents.try(:each) do |d|
116
+ # ids << d.content_type
117
+ # end
118
+ # ids
119
+ # end
120
+ # alias :doctype_ids :content_type_ids
122
121
 
123
122
  def has_finra?
124
- finra_document != nil
123
+ finra_path.present?
125
124
  end
126
125
 
127
126
  def expired?
128
127
  expires_at < Time.now
129
128
  end
130
129
 
131
- def finra_document
132
- finra_idx = documents.index {|d| d.content_type == ContentType::FINRA}
133
- documents[finra_idx] if finra_idx
134
- end
130
+ # def finra_document
131
+ # finra_idx = documents.index {|d| d.content_type == ContentType::FINRA}
132
+ # documents[finra_idx] if finra_idx
133
+ # end
135
134
 
136
135
  def is_investor_approved?
137
136
  audiences.index(DigitalAsset::Audience::INVESTOR_APPROVED)
@@ -153,66 +152,56 @@ class DigitalAsset
153
152
  TaxonomyTerm.label_for_term(content_organization_ids[0])
154
153
  end
155
154
 
156
- def fund_code
157
- pid = product_ids.find {|pid| TaxonomyTerm.term_id_is(pid)[0].try(:fund_code)}
158
- pid and TaxonomyTerm.term_id_is(pid)[0].try(:fund_code).try(:rjust, 5, '0')
159
- end
155
+ # def fund_code
156
+ # pid = product_ids.find {|pid| TaxonomyTerm.term_id_is(pid)[0].try(:fund_code)}
157
+ # pid and TaxonomyTerm.term_id_is(pid)[0].try(:fund_code).try(:rjust, 5, '0')
158
+ # end
160
159
 
161
160
  def content_type
162
161
  TaxonomyTerm.label_for_term(content_type_id)
163
162
  end
164
163
  def content_type_id
165
- first_non_finra.try(:content_type)
164
+ :content_type
166
165
  end
167
166
 
168
- def pages; first_non_finra.pages end
169
-
170
167
  def audience
171
168
  TaxonomyTerm.label_for_term(audiences[0])
172
169
  end
173
170
 
174
171
  def primary_path
175
- first_non_finra.try(:path)
172
+ :path
176
173
  end
177
174
 
178
175
  def primary_extension
179
- first_non_finra.try(:path).try(:split,'.').try(:last).try(:upcase)
176
+ self.try(:path).try(:split,'.').try(:last).try(:upcase)
180
177
  end
181
178
 
182
179
  private
183
180
 
184
- def first_non_finra
185
- documents.try(:detect) do |d|
186
- d.content_type != ContentType::FINRA
187
- end
188
- end
181
+ # def first_non_finra
182
+ # documents.try(:detect) do |d|
183
+ # d.content_type != ContentType::FINRA
184
+ # end
185
+ # end
189
186
 
190
187
 
191
188
  end
192
189
 
193
- class DigitalAsset::Document
194
- include Mongoid::Document
190
+ # class DigitalAsset::Document
191
+ # include Mongoid::Document
195
192
 
196
- field :path, type: String
197
- field :doc_changed_at, type: Time
198
- field :content_type, type: String
199
- field :pages, type: Integer, default: 1
200
- field :size, type: String
201
- field :mime_type, type: String
202
- field :subject, type: String
203
- field :keywords, type: Array, default: []
204
- field :author, type: String
193
+
205
194
 
206
- embedded_in :digital_asset
195
+ # embedded_in :digital_asset
207
196
 
208
- key :path
197
+ # key :path
209
198
 
210
- validates_uniqueness_of :path
199
+ # validates_uniqueness_of :path
211
200
 
212
- validates_presence_of :path #, :doc_changed_at, :content_type
213
- validates_format_of :path, without: /\/manifest|archives\// # dont accept manifest files
201
+ # validates_presence_of :path #, :doc_changed_at, :content_type
202
+ # validates_format_of :path, without: /\/manifest|archives\// # dont accept manifest files
214
203
 
215
- end
204
+ # end
216
205
 
217
206
  class DigitalAsset::ContentType
218
207
  FINRA = '549'