acts_as_elibri_product 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Piotr Szmielew
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ [![Build Status](https://secure.travis-ci.org/elibri/acts_as_elibri_product.png?branch=master)](http://travis-ci.org/elibri/acts_as_elibri_product)
2
+
3
+ Gem designed to allow easy addition of eLibri based product to your application.
4
+
5
+ Currently only tested and supported under REE.
6
+
7
+ Usage guide:
8
+
9
+ * Add `'acts_as_elibri_product'` to your Gemfile
10
+
11
+ * Run `rails g add_acts_as_elibri_product [YOUR_PRODUCT_MODEL_NAME]`
12
+
13
+ * Run `rake db:migrate`
14
+
15
+ * Add `acts_as_elibri_product TRAVERSE_VECTOR` to your product_model
16
+
17
+ * Schedule (for example in cron) regular calls to `ProductModel.batch_create_or_update_from_elibri` providing `xml_string` from eLibri API as an argument.
18
+
19
+ TRAVERSE_VECTOR is a structure containing information about mapping elibri arguments to your model arguments. Attributes not specified here, will be ignored during data import.
20
+
21
+ Structure is build using hashes, general rule is:
22
+ ```ruby
23
+ {
24
+ :elibri_attribute_name => :application_attribute_name,
25
+ :another_elibri_attribute_name => :another_application_attribute_name
26
+ }
27
+ ```
28
+
29
+ When dealing with embedded objects and relations, you should use embedded hashes:
30
+
31
+ ```ruby
32
+ :elibri_embedded_object_name =>
33
+ { :application_relations_name =>
34
+ {
35
+ :embedded_object_elibri_attribute_name => :application_relation_object_attribute_name,
36
+ :another_embedded_object_elibri_attribute_name => :another_application_relation_object_attribute_name
37
+ }
38
+ }
39
+ ```
40
+
41
+ In embedded object, id may change, however import_id and/or record_reference will always remain unchanged.
42
+
43
+ example vector:
44
+
45
+ ```ruby
46
+ :record_reference => :record_reference,
47
+ :isbn13 => :isbn,
48
+ :title => :title,
49
+ :full_title => :full_title,
50
+ :trade_title => :trade_title,
51
+ :original_title => :original_title,
52
+ :number_of_pages => :number_of_pages,
53
+ :duration => :duration,
54
+ :width => :width,
55
+ :height => :height,
56
+ :cover_type => :cover_type,
57
+ :pkwiu => :pkwiu,
58
+ :edition_statement => :edition_statement,
59
+ :reading_age_from => :audience_age_from,
60
+ :reading_age_to => :audience_age_to,
61
+ :cover_price => :price_amount,
62
+ :vat => :vat,
63
+ :product_form => :product_form,
64
+ :no_contributor? => :no_contributor,
65
+ :unnamed_persons? => :unnamed_persons,
66
+ :contributors => { #embedded name in elibri
67
+ :contributors => { #embedded name in elibri
68
+ :id => :import_id, #name transition atrybutow elibri => our app
69
+ :role_name => :role_name,
70
+ :role => :role,
71
+ :from_language => :from_language,
72
+ :person_name => :full_name,
73
+ :titles_before_names => :title,
74
+ :names_before_key => :first_name,
75
+ :prefix_to_key => :last_name_prefix,
76
+ :key_names => :last_name,
77
+ :names_after_key => :last_name_postfix,
78
+ :biographical_note => :biography
79
+ }
80
+ },
81
+ :text_contents => { #embedded name in elibri
82
+ :product_texts => { #embedded name in elibri
83
+ :id => :import_id, #name transition atrybutow elibri => our app
84
+ :text => :text,
85
+ :type_name => :text_type,
86
+ :author => :text_author,
87
+ :source_title => :source_title,
88
+ :source_url => :resource_link
89
+ }
90
+ },
91
+ :imprint => {
92
+ :imprint => {
93
+ :name => :name
94
+ }
95
+ }
96
+ ```
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'ActsAsElibriProduct'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ desc "Running specs"
29
+ task :spec do |t|
30
+ exec "cd spec/ && bundle exec rspec acts_as_elibri_product_spec.rb"
31
+ end
32
+
33
+ task :default => ["spec"]
@@ -0,0 +1,3 @@
1
+ module ActsAsElibriProduct
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,144 @@
1
+ require 'elibri_onix_mocks'
2
+ require 'elibri_xml_versions'
3
+ require 'ostruct'
4
+
5
+ module ActsAsElibriProduct
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def self.traverse_vector
14
+ @@traverse_vector
15
+ end
16
+
17
+ @@traverse_vector = {}
18
+
19
+ def acts_as_elibri_product(traverse_vector = {})
20
+ @@traverse_vector = traverse_vector
21
+ end
22
+
23
+ def create_from_elibri(xml_string)
24
+ product = Elibri::ONIX::Release_3_0::ONIXMessage.from_xml(xml_string).products.first
25
+ db_product = self.new
26
+ @@traverse_vector.each_pair do |k, v|
27
+ if v.is_a?(Symbol)
28
+ db_product.send(:write_attribute, v, product.send(k))
29
+ elsif v.is_a?(Hash)
30
+ object = db_product.send(v.keys.first)
31
+ ActsAsElibriProduct.set_objects_from_array(k, v.keys.first, v.values.first, product.send(k), db_product) if product.send(k)
32
+ end
33
+ end
34
+ db_product.old_xml = xml_string
35
+ db_product.save
36
+ end
37
+
38
+ def create_or_update_from_elibri(xml_string)
39
+ recreated_product = Elibri::ONIX::Release_3_0::ONIXMessage.from_xml(xml_string).products.first
40
+ if Product.find(:first, :conditions => {:record_reference => recreated_product.record_reference})
41
+ #update
42
+ Product.find(:first, :conditions => {:record_reference => recreated_product.record_reference}).update_product_from_elibri(xml_string)
43
+ else
44
+ Product.create_from_elibri(xml_string)
45
+ end
46
+ end
47
+
48
+ def batch_create_or_update_from_elibri(xml_string)
49
+ recreated_products = Elibri::ONIX::Release_3_0::ONIXMessage.from_xml(xml_string)
50
+ recreated_products.products.each do |product|
51
+ xml = product.to_xml.to_s
52
+ dialect = product.elibri_dialect
53
+ header = "<?xml version='1.0' encoding='UTF-8'?>
54
+ <ONIXMessage xmlns:elibri='http://elibri.com.pl/ns/extensions' xmlns='`http://www.editeur.org/onix/3.0/reference' release='3.0'>
55
+ <elibri:Dialect>#{dialect}</elibri:Dialect>"
56
+
57
+ xml = header + xml + "</ONIXMessage>"
58
+ create_or_update_from_elibri(xml)
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ def update_product_from_elibri(new_xml)
65
+ product = Elibri::ONIX::Release_3_0::ONIXMessage.from_xml(read_attribute :old_xml).products.first
66
+ product_updated = Elibri::ONIX::Release_3_0::ONIXMessage.from_xml(new_xml).products.first
67
+ elibri_xml_versions = Elibri::XmlVersions.new(product, product_updated)
68
+ details = elibri_xml_versions.diff
69
+ details[:changes].each do |change|
70
+ if change.is_a?(Symbol) && traverse_vector[change]
71
+ write_attribute(traverse_vector[change], product_updated.send(change))
72
+ elsif change.is_a?(Hash) && traverse_vector[change.keys.first]
73
+ change.values.first.each do |elibri_attrib|
74
+ db_attrib = traverse_vector[change.keys.first].values.first[elibri_attrib]
75
+ object = self.send(traverse_vector[change.keys.first].keys.first)
76
+ elibri_object = product_updated.send(change.keys.first)
77
+ object.send(:write_attribute, db_attrib, elibri_object.send(elibri_attrib))
78
+ end
79
+ # read_attribute(traverse_vector[change.keys.first]).send("#{traverse_vector[change[keys.first]]}=", product_updated.send(change.keys.first).send(change[keys.first]))
80
+ else
81
+ #nieistotne :)
82
+ end
83
+ details[:deleted].each do |deleted|
84
+ if traverse_vector[deleted.keys.first] && traverse_vector[deleted.keys.first].keys.first
85
+ deleted.each_pair do |dele_key, dele|
86
+ dele.each do |del|
87
+ self.send(traverse_vector[dele_key].keys.first).each { |x| x if x.send(traverse_vector[dele_key].values.first[:id]) == del.id }.compact.each(&:delete)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ details[:added].each do |added|
93
+ if traverse_vector[added.keys.first] && traverse_vector[added.keys.first].keys.first
94
+ ActsAsElibriProduct.set_objects_from_array(traverse_vector[added.keys.first], traverse_vector[added.keys.first].keys.first, traverse_vector[added.keys.first].values.first, added.values.first, self)
95
+ # object = self.send(traverse_vector[added.keys.first].keys.first)
96
+ # ActsAsElibriProduct.set_objects_from_array(traverse_vector[added.keys.first].keys.fir, v.keys.first, v.values.first, product.send(k), db_product)
97
+ end
98
+ end
99
+ write_attribute(:old_xml, new_xml)
100
+ self.save
101
+
102
+ end
103
+
104
+ end
105
+
106
+ def traverse_vector
107
+ ActsAsElibriProduct::ClassMethods.traverse_vector
108
+ end
109
+
110
+ def self.set_objects_from_array(elibri_object_name, db_object_name, object_traverse_vector, elibri_objects, db_product)
111
+ if elibri_objects.is_a?(Array)
112
+ elibri_objects.each do |elibri_object|
113
+ db_product.send(db_object_name).build.tap do |inner_object|
114
+ # db_product.send
115
+ object_traverse_vector.each_pair do |k, v|
116
+ if v.is_a?(Hash)
117
+ #TODO
118
+ # set_objects_from_array(object.send(v.keys.first), v.values.first, product, k)
119
+ else
120
+ inner_object.send(:write_attribute, v, elibri_object.send(k))
121
+ end
122
+ end
123
+ end
124
+ end
125
+ else
126
+ db_product.send("build_#{db_object_name}").tap do |inner_object|
127
+ # db_product.send
128
+ object_traverse_vector.each_pair do |k, v|
129
+ if v.is_a?(Hash)
130
+ #TODO
131
+ # set_objects_from_array(object.send(v.keys.first), v.values.first, product, k)
132
+ else
133
+ inner_object.send(:write_attribute, v, elibri_objects.send(k))
134
+ end
135
+ end
136
+ inner_object.save
137
+ end
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+
144
+ ActiveRecord::Base.send :include, ActsAsElibriProduct
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate add_acts_as_elibri_product Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,23 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ class AddActsAsElibriProductGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ argument :model_name, :type => :string
8
+
9
+ def self.next_migration_number(path)
10
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
11
+ end
12
+
13
+ def migration
14
+ migration_template "add_old_xml_to_model.rb", "db/migrate/add_old_xml_to_#{model_name.underscore}_model.rb"
15
+ end
16
+
17
+ private
18
+
19
+ def table_name
20
+ model_name.pluralize.underscore
21
+ end
22
+
23
+ end
@@ -0,0 +1,9 @@
1
+ class AddOldXmlTo<%= model_name %>Model < ActiveRecord::Migration
2
+ def up
3
+ add_column :<%= table_name %>, :old_xml, :text
4
+ end
5
+
6
+ def down
7
+ remove_column :<%= table_name %>, :old_xml
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :acts_as_elibri_product do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_elibri_product
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Piotr Szmielew
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-04-05 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ hash: 15
28
+ segments:
29
+ - 3
30
+ - 2
31
+ - 0
32
+ version: 3.2.0
33
+ version_requirements: *id001
34
+ name: rails
35
+ type: :runtime
36
+ - !ruby/object:Gem::Dependency
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ version_requirements: *id002
48
+ name: elibri_xml_versions
49
+ type: :runtime
50
+ - !ruby/object:Gem::Dependency
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ version_requirements: *id003
62
+ name: elibri_onix_mocks
63
+ type: :development
64
+ - !ruby/object:Gem::Dependency
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ version_requirements: *id004
76
+ name: rspec
77
+ type: :development
78
+ - !ruby/object:Gem::Dependency
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ version_requirements: *id005
90
+ name: rspec-rails
91
+ type: :development
92
+ - !ruby/object:Gem::Dependency
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ version_requirements: *id006
104
+ name: sqlite3
105
+ type: :development
106
+ description: Gem designed to allow easy addition of eLibri based product to your application. Currently only tested under REE.
107
+ email:
108
+ - p.szmielew@ava.waw.pl
109
+ executables: []
110
+
111
+ extensions: []
112
+
113
+ extra_rdoc_files: []
114
+
115
+ files:
116
+ - lib/acts_as_elibri_product/version.rb
117
+ - lib/acts_as_elibri_product.rb
118
+ - lib/generators/add_acts_as_elibri_product/add_acts_as_elibri_product_generator.rb
119
+ - lib/generators/add_acts_as_elibri_product/templates/add_old_xml_to_model.rb
120
+ - lib/generators/add_acts_as_elibri_product/USAGE
121
+ - lib/tasks/acts_as_elibri_product_tasks.rake
122
+ - MIT-LICENSE
123
+ - Rakefile
124
+ - README.md
125
+ homepage: http://elibri.com.pl
126
+ licenses: []
127
+
128
+ post_install_message:
129
+ rdoc_options: []
130
+
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ hash: 3
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ hash: 3
148
+ segments:
149
+ - 0
150
+ version: "0"
151
+ requirements: []
152
+
153
+ rubyforge_project:
154
+ rubygems_version: 1.8.17
155
+ signing_key:
156
+ specification_version: 3
157
+ summary: Easy addition of eLibri based product to your application
158
+ test_files: []
159
+