netphase-acts_as_amazon_product 2.0.0
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/.gitignore +3 -0
- data/CHANGELOG +33 -0
- data/COPYING +18 -0
- data/README +135 -0
- data/Rakefile +85 -0
- data/VERSION +1 -0
- data/acts_as_amazon_product.gemspec +57 -0
- data/generators/acts_as_amazon_product_migration/acts_as_amazon_product_migration_generator.rb +11 -0
- data/generators/acts_as_amazon_product_migration/templates/migration.rb +16 -0
- data/init.rb +3 -0
- data/install.rb +1 -0
- data/lib/acts_as_amazon_product.rb +123 -0
- data/lib/amazon_product.rb +70 -0
- data/tasks/acts_as_amazon_product_tasks.rake +4 -0
- data/test/acts_as_amazon_product_test.rb +226 -0
- data/test/config-example.yml +7 -0
- data/test/example.rb +28 -0
- data/uninstall.rb +1 -0
- metadata +81 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
= 1.4
|
2
|
+
=== 11th October, 2008
|
3
|
+
* Added load_from_amazon and load_from_amazon! methods to load up Amazon attributes into a local object directly (see the README for usage)
|
4
|
+
* Added new tests for the above functionality
|
5
|
+
* Changed the response group so that it is a passed-in option, with the default being 'Medium' rather than having it hardcoded.
|
6
|
+
|
7
|
+
= 1.3
|
8
|
+
=== 11th August, 2008
|
9
|
+
* (Thanks to David Eisinger for changes in this release)
|
10
|
+
* Test wasn't dropping magazines table, causing error when running tests multiple times
|
11
|
+
* Added access_key and associate_tag to movie and magazine in tests; not setting them was causing tests to fail without ENV variables
|
12
|
+
* Added a generator to create the amazon_products database migration
|
13
|
+
* Changed the Hpricot search method: If multiple values, returns them as a comma-separated string; Returns nil if no value found
|
14
|
+
* Got rid of the amazon_product#hdoc method, moved functionality in to #get
|
15
|
+
* Added method_missing to amazon_product to search XML based on method name
|
16
|
+
|
17
|
+
= 1.2
|
18
|
+
=== 24th April, 2008
|
19
|
+
* Accepts search_index parameter to work better with Magazines (patch from Parker Morse)
|
20
|
+
* Changed scm to Git and moved repository to github.com
|
21
|
+
|
22
|
+
= 1.1
|
23
|
+
=== 3rd November, 2007
|
24
|
+
* Use defaults for access_key and associate_tag from the environment: AMAZON_ACCESS_KEY_ID, AMAZON_ASSOCIATE_TAG
|
25
|
+
* Added example.rb
|
26
|
+
|
27
|
+
= 1.0
|
28
|
+
=== 21st September, 2007
|
29
|
+
|
30
|
+
* Initial release as a gem
|
31
|
+
* Caches response from Amazon
|
32
|
+
* Some basic tests. Run "rake test"
|
33
|
+
|
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2007 netphase.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
= ActsAsAmazonProduct
|
2
|
+
|
3
|
+
This "acts_as" module makes it extremely simple to add Amazon integration to an
|
4
|
+
existing model.
|
5
|
+
|
6
|
+
== Setup
|
7
|
+
|
8
|
+
This code does not require changing any current database tables. It only requires
|
9
|
+
adding one migration for a single new table used to cache responses from Amazon.
|
10
|
+
Run the following to create the migration:
|
11
|
+
|
12
|
+
script/generate acts_as_amazon_product_migration
|
13
|
+
|
14
|
+
== Using acts_as_amazon_product
|
15
|
+
|
16
|
+
Add the "acts_as" line to your model. Only :access_key is required. The :asin and
|
17
|
+
:name assignments override what attributes in your class should be used for a direct
|
18
|
+
lookup (item_lookup) or general search (item_search). If no value is assigned to :asin
|
19
|
+
then a general search is made and the first item (sorted by salesrank) is assigned
|
20
|
+
(this functionality will likely change).
|
21
|
+
|
22
|
+
There are two ways to use Acts as Amazon Product. The first is to simply allow all of the Amazon data for your product
|
23
|
+
to be stored in the AmazonProduct object:
|
24
|
+
|
25
|
+
require 'acts_as_amazon_product'
|
26
|
+
|
27
|
+
class Book < ActiveRecord::Base
|
28
|
+
acts_as_amazon_product :asin => 'isbn', :name => 'title',
|
29
|
+
:access_key => '0123456', :associate_tag => 'assoc-20'
|
30
|
+
end
|
31
|
+
|
32
|
+
Other interesting options for the acts_as_amazon call:
|
33
|
+
|
34
|
+
:search_index => 'Books' (default value if not specified)
|
35
|
+
:response_group => 'Medium' (default value if not specified)
|
36
|
+
:auto_load_fields => see below
|
37
|
+
:ignore_fields => see below
|
38
|
+
|
39
|
+
You can now access the Amazon data in your views like so:
|
40
|
+
|
41
|
+
@book = Book.new(:title => 'Getting Things Done')
|
42
|
+
@book.amazon.isbn
|
43
|
+
@book.amazon.title
|
44
|
+
@book.amazon.author
|
45
|
+
@book.amazon.small_image_url
|
46
|
+
|
47
|
+
or
|
48
|
+
@book.amazon.get('itemattributes/foobar')
|
49
|
+
|
50
|
+
The second way to use Acts as Amazon Product is to load the Amazon data directly into an existing object in your
|
51
|
+
application. You can elect to have the Amazon data loaded into a new, unsaved object, or go one step further and allow
|
52
|
+
Acts as Amazon Product to load the data and save the loaded object all in one shot. The mapping between the
|
53
|
+
Amazon fields and your object are declared by passing a hash called auto_load_fields to the acts_as_amazon_product
|
54
|
+
call as shown below:
|
55
|
+
|
56
|
+
require 'acts_as_amazon_product'
|
57
|
+
|
58
|
+
class LocalBook < ActiveRecord::Base
|
59
|
+
acts_as_amazon_product(
|
60
|
+
:asin => 'isbn', :name => 'title',
|
61
|
+
:access_key => '0123456', :associate_tag => 'assoc-20',
|
62
|
+
:auto_load_fields => {:title => 'title', :isbn => 'asin', :publisher_name => 'manufacturer', :author => 'author'}
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
The keys in the auto_load_fields hash are the fields in your object, and the values are their Amazon equivalents.
|
67
|
+
In the true Rails convention over configuration spirit, we have included some of the most popular auto load fields as
|
68
|
+
defaults. If your object contains the following attributes, they will automatically be loaded with their Amazon
|
69
|
+
equivalents:
|
70
|
+
|
71
|
+
:auto_load_fields => {:title => 'title', :isbn => 'asin', :publisher_name => 'manufacturer',
|
72
|
+
:author => 'author', :binding => 'binding', :list_price => 'listprice/amount', :pages => 'numberofpages',
|
73
|
+
:description => 'content', :small_image_url => 'smallimage/url', :medium_image_url => 'mediumimage/url',
|
74
|
+
:large_image_url => 'largeimage/url', :detail_url => 'detailpageurl'}
|
75
|
+
|
76
|
+
Don't worry if your object does not have some or most of these fields; Acts as Amazon Product is smart enough to check
|
77
|
+
to see if the method exists before attempting to load up the Amazon value.
|
78
|
+
|
79
|
+
Now, if by some coincidence you have some fields in your local object that have the same name as our auto_load
|
80
|
+
defaults, you can choose to specifically ignore those fields using, you guessed it, :ignore_fields. :ignore_fields is
|
81
|
+
a simple array of fields in your object that you do NOT want to be replaced with the Amazon equivalent. You would
|
82
|
+
specify them like this:
|
83
|
+
|
84
|
+
acts_as_amazon_product(
|
85
|
+
:asin => 'isbn', :name => 'title',
|
86
|
+
:access_key => '0123456', :associate_tag => 'assoc-20',
|
87
|
+
:ignore_fields => [:small_image_url, :medium_image_url]
|
88
|
+
)
|
89
|
+
|
90
|
+
In this instance, the object in question would load Amazon info for any of the default fields that the object has,
|
91
|
+
with the exception of the small_image_url and medium_image_url values.
|
92
|
+
|
93
|
+
To load the Amazon values into your object for local storage, you may call the following methods:
|
94
|
+
|
95
|
+
load_from_amazon(title_or_asin, by_title = false)
|
96
|
+
load_from_amazon!(title_or_asin, by_title = false)
|
97
|
+
|
98
|
+
The two methods do exactly the same thing, except the first simply returns a new, unsaved object with its Amazon-like
|
99
|
+
fields loaded with their appropriate Amazon values. The second version (load_from_amazon!) goes one step further and
|
100
|
+
saves the object for good measure.
|
101
|
+
|
102
|
+
You may pass either an isbn (asin) or a title in. If you are passing a title, you need to specify that you are
|
103
|
+
passing a title by also passing true as the second parameter so we will perform an item_search rather than an
|
104
|
+
item_lookup. Note that passing a title is risky business, since currently the code will take the first result returned
|
105
|
+
and load that into your object. So unless your title is unique, I would recommend sticking with the isbn (asin) value.
|
106
|
+
Since that is the default, all you need to do would be something like this:
|
107
|
+
|
108
|
+
@local_book = LocalBook.load_from_amazon('1590598415')
|
109
|
+
|
110
|
+
If your object was similar to the LocalBook object in our example, for instance, you would not need to specify the
|
111
|
+
auto_load_fields in the acts_as call at all. The title, isbn, publisher_name and author methods would automatically
|
112
|
+
be called once you call load_from_amazon, and their values populated appropriately.
|
113
|
+
|
114
|
+
It is important to note that if you call load_from_amazon with an invalid asin, you will simply get back an empty
|
115
|
+
object.
|
116
|
+
|
117
|
+
Now, calling load_from_amazon still allows you to take advantage of the other Acts as Amazon features, like the
|
118
|
+
dynamic loading of Amazon attributes on the fly by using the various amazon.foo methods as described above.
|
119
|
+
|
120
|
+
== Unit tests
|
121
|
+
|
122
|
+
There are tests you can run in the [gem]/test directory. Just create a
|
123
|
+
test/config.yml from the example and run "Rake test" from the [gem] directory.
|
124
|
+
|
125
|
+
= Credits
|
126
|
+
acts_as_amazon_product was created by Scott Nedderman and Chris Beck from netphase.com
|
127
|
+
|
128
|
+
We'd love to here how you like it. Also, if you'd like us to help out with your next
|
129
|
+
project, let us know.
|
130
|
+
|
131
|
+
http://netphase.com
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'fileutils'
|
8
|
+
include FileUtils
|
9
|
+
|
10
|
+
NAME = "acts_as_amazon_product"
|
11
|
+
# REV = File.read(".svn/entries")[/committed-rev="(\d+)"/, 1] rescue nil
|
12
|
+
# VERS = ENV['VERSION'] || ("1.1" + (REV ? ".#{REV}" : ""))
|
13
|
+
VERS = ENV['VERSION'] || "1.4"
|
14
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config', 'test/test.log']
|
15
|
+
|
16
|
+
desc 'Default: run unit tests.'
|
17
|
+
task :default => [:package]
|
18
|
+
task :package => [:clean]
|
19
|
+
|
20
|
+
desc 'Generate documentation for the acts_as_amazon_product plugin.'
|
21
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
23
|
+
rdoc.title = 'ActsAsAmazonProduct'
|
24
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
25
|
+
rdoc.rdoc_files.include('README')
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
+
end
|
28
|
+
|
29
|
+
# Gem::manage_gems
|
30
|
+
# require 'rake/gempackagetask'
|
31
|
+
# spec = Gem::Specification.new do |s|
|
32
|
+
# s.platform = Gem::Platform::RUBY
|
33
|
+
# s.name = NAME
|
34
|
+
# s.version = VERS
|
35
|
+
# s.author = "Scott Nedderman"
|
36
|
+
# s.email = "scott@netphase.com"
|
37
|
+
# s.homepage = "http://netphase.com"
|
38
|
+
# s.summary = "A package for simplifying use of the Amazon/ECS API"
|
39
|
+
# s.files = FileList['lib/*.rb', 'test/*'].to_a.reject {|f| f.match /config\.yml/ }
|
40
|
+
# s.require_path = "lib"
|
41
|
+
# # s.autorequire = "acts_as_amazon_product"
|
42
|
+
# s.test_files = Dir.glob('tests/*.rb')
|
43
|
+
# s.has_rdoc = true
|
44
|
+
# s.extra_rdoc_files = ["README"]
|
45
|
+
# s.add_dependency("amazon-ecs", ">=0.5.1")
|
46
|
+
# end
|
47
|
+
# Rake::GemPackageTask.new(spec) do |pkg|
|
48
|
+
# pkg.need_tar = true
|
49
|
+
# end
|
50
|
+
# task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
|
51
|
+
# puts "generated latest version"
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# task :install do
|
55
|
+
# sh %{rake package}
|
56
|
+
# sh %{sudo gem install pkg/#{NAME}-#{VERS}}
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# task :uninstall => [:clean] do
|
60
|
+
# sh %{sudo gem uninstall #{NAME}}
|
61
|
+
# end
|
62
|
+
|
63
|
+
desc 'Test the acts_as_amazon_product plugin.'
|
64
|
+
Rake::TestTask.new(:test) do |t|
|
65
|
+
t.libs << 'lib'
|
66
|
+
t.pattern = 'test/**/*_test.rb'
|
67
|
+
t.verbose = true
|
68
|
+
end
|
69
|
+
|
70
|
+
begin
|
71
|
+
require 'jeweler'
|
72
|
+
Jeweler::Tasks.new do |gemspec|
|
73
|
+
gemspec.name = "acts_as_amazon_product"
|
74
|
+
gemspec.summary = "A package for simplifying use of the Amazon/ECS API"
|
75
|
+
gemspec.email = "scott@netphase.com"
|
76
|
+
gemspec.homepage = "http://github.com/netphase/aaap"
|
77
|
+
gemspec.authors = ["Scott Nedderman","Chris Beck"]
|
78
|
+
gemspec.add_dependency("amazon-ecs", ">=0.5.1")
|
79
|
+
gemspec.files.exclude 'test/config.yml'
|
80
|
+
|
81
|
+
end
|
82
|
+
rescue LoadError
|
83
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
84
|
+
end
|
85
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{acts_as_amazon_product}
|
5
|
+
s.version = "2.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Scott Nedderman", "Chris Beck"]
|
9
|
+
s.date = %q{2009-06-18}
|
10
|
+
s.email = %q{scott@netphase.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"README"
|
13
|
+
]
|
14
|
+
s.files = [
|
15
|
+
".gitignore",
|
16
|
+
"CHANGELOG",
|
17
|
+
"COPYING",
|
18
|
+
"README",
|
19
|
+
"Rakefile",
|
20
|
+
"VERSION",
|
21
|
+
"acts_as_amazon_product.gemspec",
|
22
|
+
"generators/acts_as_amazon_product_migration/acts_as_amazon_product_migration_generator.rb",
|
23
|
+
"generators/acts_as_amazon_product_migration/templates/migration.rb",
|
24
|
+
"init.rb",
|
25
|
+
"install.rb",
|
26
|
+
"lib/acts_as_amazon_product.rb",
|
27
|
+
"lib/amazon_product.rb",
|
28
|
+
"tasks/acts_as_amazon_product_tasks.rake",
|
29
|
+
"test/acts_as_amazon_product_test.rb",
|
30
|
+
"test/config-example.yml",
|
31
|
+
"test/example.rb",
|
32
|
+
"uninstall.rb"
|
33
|
+
]
|
34
|
+
s.has_rdoc = true
|
35
|
+
s.homepage = %q{http://github.com/netphase/aaap}
|
36
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
37
|
+
s.require_paths = ["lib"]
|
38
|
+
s.rubygems_version = %q{1.3.1}
|
39
|
+
s.summary = %q{A package for simplifying use of the Amazon/ECS API}
|
40
|
+
s.test_files = [
|
41
|
+
"test/acts_as_amazon_product_test.rb",
|
42
|
+
"test/example.rb"
|
43
|
+
]
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
|
+
s.specification_version = 2
|
48
|
+
|
49
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_runtime_dependency(%q<amazon-ecs>, [">= 0.5.1"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<amazon-ecs>, [">= 0.5.1"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<amazon-ecs>, [">= 0.5.1"])
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class ActsAsAmazonProductMigration < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :amazon_products do |t|
|
4
|
+
t.string :asin
|
5
|
+
t.text :xml
|
6
|
+
t.integer :amazonable_id, :default => 0, :null => false
|
7
|
+
t.string :amazonable_type, :limit => 15, :default => "", :null => false
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :amazon_products
|
15
|
+
end
|
16
|
+
end
|
data/init.rb
ADDED
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'amazon/ecs'
|
4
|
+
require 'amazon_product'
|
5
|
+
|
6
|
+
module Netphase
|
7
|
+
module Acts #:nodoc:
|
8
|
+
module Amazonable #:nodoc:
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def acts_as_amazon_product(options = {})
|
16
|
+
defaults = {
|
17
|
+
:asin => 'asin',
|
18
|
+
:name => 'name',
|
19
|
+
:access_key => ENV['AMAZON_ACCESS_KEY_ID'],
|
20
|
+
:associate_tag => ENV['AMAZON_ASSOCIATE_TAG'],
|
21
|
+
:search_index => 'Books',
|
22
|
+
:response_group => 'Medium',
|
23
|
+
:auto_load_fields => {:title => 'title', :isbn => 'asin', :publisher_name => 'manufacturer',
|
24
|
+
:author => 'author', :binding => 'binding', :list_price => 'listprice/amount', :pages => 'numberofpages',
|
25
|
+
:description => 'content', :small_image_url => 'smallimage/url', :medium_image_url => 'mediumimage/url',
|
26
|
+
:large_image_url => 'largeimage/url', :detail_url => 'detailpageurl'},
|
27
|
+
:ignore_fields => [],
|
28
|
+
:auto_delete_amazon => true
|
29
|
+
}
|
30
|
+
options = defaults.merge options
|
31
|
+
|
32
|
+
Amazon::Ecs.options = {:aWS_access_key_id => options[:access_key],
|
33
|
+
:associate_tag => options[:associate_tag], :response_group => options[:response_group]}
|
34
|
+
|
35
|
+
write_inheritable_attribute(:amazon_asin, options[:asin])
|
36
|
+
write_inheritable_attribute(:amazon_name, options[:name])
|
37
|
+
write_inheritable_attribute(:amazon_search_index, options[:search_index])
|
38
|
+
write_inheritable_attribute(:amazon_associate_key, options[:associate_key])
|
39
|
+
write_inheritable_attribute(:auto_load_fields, options[:auto_load_fields])
|
40
|
+
write_inheritable_attribute(:ignore_fields, options[:ignore_fields])
|
41
|
+
write_inheritable_attribute(:auto_delete_amazon, options[:auto_delete_amazon])
|
42
|
+
class_inheritable_reader :amazon_asin, :amazon_name, :amazon_search_index, :amazon_associate_key
|
43
|
+
class_inheritable_reader :auto_load_fields, :ignore_fields, :auto_delete_amazon
|
44
|
+
|
45
|
+
has_one :amazon_product, :as => :amazonable #, :dependent => :delete
|
46
|
+
extend Netphase::Acts::Amazonable::SingletonMethods
|
47
|
+
include Netphase::Acts::Amazonable::InstanceMethods
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
# This module contains class methods
|
53
|
+
module SingletonMethods
|
54
|
+
def load_from_amazon(title_or_asin, by_title = false)
|
55
|
+
begin
|
56
|
+
unless by_title
|
57
|
+
res = Amazon::Ecs.item_lookup(title_or_asin)
|
58
|
+
else
|
59
|
+
res = Amazon::Ecs.item_search(title_or_asin, :search_index => self.amazon_search_index)
|
60
|
+
end
|
61
|
+
create_instance_from_amazon(res.items[0])
|
62
|
+
rescue
|
63
|
+
return self.new
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def load_from_amazon!(title_or_asin, by_title = false)
|
68
|
+
result = self.load_from_amazon(title_or_asin, by_title)
|
69
|
+
if result
|
70
|
+
result.save
|
71
|
+
return result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def create_instance_from_amazon(item)
|
77
|
+
newbie = self.new
|
78
|
+
self.auto_load_fields.each do |key, value|
|
79
|
+
if newbie.respond_to?(key.to_s) && !self.ignore_fields.include?(key)
|
80
|
+
newbie.send key.to_s + '=', item.get(value)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
return newbie
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
# This module contains instance methods
|
89
|
+
module InstanceMethods
|
90
|
+
def amazon
|
91
|
+
if self.amazon_product.nil?
|
92
|
+
asin = self.send(self.amazon_asin) rescue nil
|
93
|
+
name = self.send(self.amazon_name) rescue nil
|
94
|
+
options = { :response_group => 'Medium' }
|
95
|
+
if !asin.blank?
|
96
|
+
unless self.amazon_asin == 'asin'
|
97
|
+
options[:id_type] = self.amazon_asin.upcase
|
98
|
+
options[:search_index] = self.amazon_search_index
|
99
|
+
end
|
100
|
+
res = Amazon::Ecs.item_lookup(self.send(self.amazon_asin), options)
|
101
|
+
self.create_amazon_product(:xml => res.doc.to_html, :asin => res.doc.at('asin') && res.doc.at('asin').inner_html)
|
102
|
+
elsif !name.blank?
|
103
|
+
res = Amazon::Ecs.item_search(self.send(self.amazon_name), options.merge(:search_index => self.amazon_search_index))
|
104
|
+
res = res.doc.at('items/item')
|
105
|
+
asin = res.at('itemattributes/isbn') || res.at('asin') unless res.nil?
|
106
|
+
self.create_amazon_product(:xml => res && res.to_html, :asin => asin && asin.inner_html)
|
107
|
+
else
|
108
|
+
logger.error "No known attributes to search by"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
self.amazon_product if self.amazon_product.valid?
|
112
|
+
end
|
113
|
+
|
114
|
+
def after_save
|
115
|
+
if self.auto_delete_amazon && !self.amazon_product.nil?
|
116
|
+
self.amazon_product.destroy
|
117
|
+
self.reload
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
|
3
|
+
class AmazonProduct < ActiveRecord::Base
|
4
|
+
validates_presence_of :asin
|
5
|
+
|
6
|
+
def get(key, separator = ', ')
|
7
|
+
@doc ||= Hpricot.XML(xml)
|
8
|
+
values = (@doc/key).collect {|e| e.inner_html }
|
9
|
+
values *= separator unless separator.nil?
|
10
|
+
values unless values.blank?
|
11
|
+
end
|
12
|
+
|
13
|
+
def isbn
|
14
|
+
get("itemattributes/isbn")
|
15
|
+
end
|
16
|
+
|
17
|
+
def title
|
18
|
+
get("itemattributes/title")
|
19
|
+
end
|
20
|
+
|
21
|
+
def author
|
22
|
+
get("itemattributes/author")
|
23
|
+
end
|
24
|
+
|
25
|
+
def binding
|
26
|
+
get("itemattributes/binding")
|
27
|
+
end
|
28
|
+
|
29
|
+
def price
|
30
|
+
get("itemattributes/listprice/amount")
|
31
|
+
end
|
32
|
+
|
33
|
+
def pages
|
34
|
+
get("itemattributes/numberofpages")
|
35
|
+
end
|
36
|
+
|
37
|
+
def small_image_url
|
38
|
+
get("smallimage/url")
|
39
|
+
end
|
40
|
+
|
41
|
+
def medium_image_url
|
42
|
+
get("mediumimage/url")
|
43
|
+
end
|
44
|
+
|
45
|
+
def large_image_url
|
46
|
+
get("largeimage/url")
|
47
|
+
end
|
48
|
+
|
49
|
+
def detail_url
|
50
|
+
get("detailpageurl")
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(symbol, *args)
|
54
|
+
begin
|
55
|
+
super(symbol, *args)
|
56
|
+
rescue NoMethodError
|
57
|
+
get(symbol, *args)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def respond_to?(method_id, include_private = false)
|
62
|
+
unless self.xml.blank?
|
63
|
+
doc = Hpricot.XML(xml)
|
64
|
+
return (method_id.to_s.index(/[\W]/) || doc.at(method_id.to_s).nil?) ? super : true
|
65
|
+
else
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/acts_as_amazon_product")
|
5
|
+
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + "/../init")
|
7
|
+
|
8
|
+
config = open(File.dirname(__FILE__) + "/../test/config.yml") { |f| YAML.load(f.read)}
|
9
|
+
ActiveRecord::Base.establish_connection(config["database"])
|
10
|
+
|
11
|
+
#Amazon::Ecs.options = {:aWS_access_key_id => config['amazon']['access_key']}
|
12
|
+
@@access_key = config['amazon']['access_key']
|
13
|
+
@@associate_tag = config['amazon']['associate_tag']
|
14
|
+
|
15
|
+
ActiveRecord::Base.connection.drop_table :amazon_products rescue nil
|
16
|
+
ActiveRecord::Base.connection.drop_table :books rescue nil
|
17
|
+
ActiveRecord::Base.connection.drop_table :ean_books rescue nil
|
18
|
+
ActiveRecord::Base.connection.drop_table :movies rescue nil
|
19
|
+
ActiveRecord::Base.connection.drop_table :magazines rescue nil
|
20
|
+
ActiveRecord::Base.connection.drop_table :local_books rescue nil
|
21
|
+
|
22
|
+
ActiveRecord::Base.connection.create_table :books do |t|
|
23
|
+
t.column :type, :string
|
24
|
+
t.column :title, :string
|
25
|
+
t.column :author, :string
|
26
|
+
t.column :isbn, :string
|
27
|
+
t.column :ean, :string
|
28
|
+
end
|
29
|
+
|
30
|
+
ActiveRecord::Base.connection.create_table :movies do |t|
|
31
|
+
t.column :name, :string
|
32
|
+
t.column :asin, :string
|
33
|
+
end
|
34
|
+
|
35
|
+
ActiveRecord::Base.connection.create_table :magazines do |t|
|
36
|
+
t.column :name, :string
|
37
|
+
t.column :asin, :string
|
38
|
+
end
|
39
|
+
|
40
|
+
ActiveRecord::Base.connection.create_table :local_books do |t|
|
41
|
+
t.column :title, :string
|
42
|
+
t.column :author, :string
|
43
|
+
t.column :isbn, :string
|
44
|
+
t.column :publisher_name, :string
|
45
|
+
t.column :small_image_url, :string
|
46
|
+
t.column :medium_image_url, :string
|
47
|
+
end
|
48
|
+
|
49
|
+
ActiveRecord::Base.connection.create_table :amazon_products do |t| # , :id => false
|
50
|
+
t.column :asin, :string
|
51
|
+
t.column :xml, :text
|
52
|
+
t.column :created_at, :datetime, :null => false
|
53
|
+
t.column :amazonable_id, :integer, :default => 0, :null => false
|
54
|
+
t.column :amazonable_type, :string, :limit => 15, :default => "", :null => false
|
55
|
+
end
|
56
|
+
|
57
|
+
class Book < ActiveRecord::Base
|
58
|
+
acts_as_amazon_product(
|
59
|
+
:asin => 'isbn', :name => 'title',
|
60
|
+
:access_key => @@access_key, :associate_tag => @@associate_tag)
|
61
|
+
end
|
62
|
+
|
63
|
+
class EANBook < Book
|
64
|
+
acts_as_amazon_product(
|
65
|
+
:asin => 'ean', :name => 'title',
|
66
|
+
:access_key => @@access_key, :associate_tag => @@associate_tag)
|
67
|
+
end
|
68
|
+
|
69
|
+
class Movie < ActiveRecord::Base
|
70
|
+
acts_as_amazon_product :access_key => @@access_key, :associate_tag => @@associate_tag
|
71
|
+
end
|
72
|
+
|
73
|
+
class Magazine < ActiveRecord::Base
|
74
|
+
acts_as_amazon_product :search_index => 'Magazines', :access_key => @@access_key,
|
75
|
+
:associate_tag => @@associate_tag
|
76
|
+
end
|
77
|
+
|
78
|
+
class LocalBook < ActiveRecord::Base
|
79
|
+
acts_as_amazon_product(
|
80
|
+
:asin => 'isbn', :name => 'title',
|
81
|
+
:access_key => @@access_key, :associate_tag => @@associate_tag, :ignore_fields => [:small_image_url, :medium_image_url]
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
AmazonProduct.delete_all
|
86
|
+
|
87
|
+
class ActAsAmazonProductTest < Test::Unit::TestCase
|
88
|
+
|
89
|
+
def setup
|
90
|
+
Book.delete_all
|
91
|
+
@book_gtd = Book.create(:title => 'Getting Things Done', :author => 'Dude', :isbn => '0142000280')
|
92
|
+
@book_ror = Book.create(:title => 'Rails Recipes')
|
93
|
+
@book_perl = Book.create(:title => 'Perl')
|
94
|
+
@book_eg = EANBook.create(:ean => '9780765342294')
|
95
|
+
@movie_dh = Movie.create(:name=>'Live Free or Die Hard', :asin=>'B000VNMMRA')
|
96
|
+
@mag_lci = Magazine.create(:name => 'La Cucina Italiana')
|
97
|
+
LocalBook.delete_all
|
98
|
+
@local_rails = LocalBook.load_from_amazon('1590598415')
|
99
|
+
@local_roots = LocalBook.load_from_amazon!('Roots', true)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_isbn
|
103
|
+
assert_not_nil(@book_gtd.amazon)
|
104
|
+
assert_equal("0142000280", @book_gtd.amazon.isbn)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_title
|
108
|
+
assert_not_nil(@book_gtd.amazon)
|
109
|
+
assert_equal("Getting Things Done: The Art of Stress-Free Productivity", @book_gtd.amazon.title)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_magazine
|
113
|
+
assert_not_nil(@mag_lci.amazon)
|
114
|
+
assert_equal("B00009XFML", @mag_lci.amazon.asin)
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_lookup_by_nonstandard_id
|
118
|
+
assert_not_nil(@book_eg.amazon)
|
119
|
+
assert_equal("Ender's Game", @book_eg.amazon.title)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_invalid_isbn
|
123
|
+
b = Book.create(:isbn => '12345')
|
124
|
+
assert_nil(b.amazon)
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_invalid_title
|
128
|
+
b = Book.create(:title => "AQAQAQAQ")
|
129
|
+
assert_nil(b.amazon)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_small_image
|
133
|
+
assert_not_nil(@book_gtd.amazon)
|
134
|
+
assert_match(/4104N6ME70L\._SL75_\.jpg/, @book_gtd.amazon.small_image_url)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_author
|
138
|
+
assert_not_nil(@book_gtd.amazon)
|
139
|
+
assert_equal("David Allen", @book_gtd.amazon.author)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_binding
|
143
|
+
assert_not_nil(@book_gtd.amazon)
|
144
|
+
assert_equal("Paperback", @book_gtd.amazon.binding)
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_find_with_multiple
|
148
|
+
assert_equal("Advanced Rails Recipes", @book_ror.amazon.title)
|
149
|
+
assert_equal("Mike Clark", @book_ror.amazon.author)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_returns_nil_if_attribute_not_found
|
153
|
+
assert_equal(nil, @book_ror.amazon.get('contributor'))
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_update
|
157
|
+
assert_not_nil(@book_perl.amazon)
|
158
|
+
isbn = @book_perl.amazon.isbn
|
159
|
+
@book_perl.title = "Websters"
|
160
|
+
@book_perl.amazon.destroy
|
161
|
+
@book_perl.save
|
162
|
+
assert_not_equal(isbn, @book_perl.reload.amazon.isbn)
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_product_with_all_defaults
|
166
|
+
assert_not_nil(@movie_dh.amazon)
|
167
|
+
assert_equal 'Bruce Willis, Justin Long, Timothy Olyphant, Maggie Q, Cliff Curtis',
|
168
|
+
@movie_dh.amazon.get('itemattributes/actor')
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_accepts_a_custom_separator
|
172
|
+
assert_equal 'Bruce Willis | Justin Long | Timothy Olyphant | Maggie Q | Cliff Curtis',
|
173
|
+
@movie_dh.amazon.get('itemattributes/actor', ' | ')
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_returns_array_if_separator_is_nil
|
177
|
+
assert_equal ["Bruce Willis", "Justin Long", "Timothy Olyphant", "Maggie Q", "Cliff Curtis"],
|
178
|
+
@movie_dh.amazon.get('itemattributes/actor', nil)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_method_missing
|
182
|
+
assert_equal 'Bruce Willis, Justin Long, Timothy Olyphant, Maggie Q, Cliff Curtis', @movie_dh.amazon.actor
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_method_missing_with_separator
|
186
|
+
assert_equal 'Bruce Willis | Justin Long | Timothy Olyphant | Maggie Q | Cliff Curtis', @movie_dh.amazon.actor(' | ')
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_load_local_book
|
190
|
+
assert_not_nil(@local_rails.title)
|
191
|
+
assert_not_nil(@local_rails.isbn)
|
192
|
+
assert_not_nil(@local_rails.publisher_name)
|
193
|
+
assert_not_nil(@local_rails.author)
|
194
|
+
assert_not_nil(@local_roots.title)
|
195
|
+
assert_not_nil(@local_roots.isbn)
|
196
|
+
assert_not_nil(@local_roots.publisher_name)
|
197
|
+
assert_not_nil(@local_roots.author)
|
198
|
+
assert_equal "Practical Rails Social Networking Sites (Expert's Voice)", @local_rails.title
|
199
|
+
assert_equal '0882667033', @local_roots.isbn
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_new_versus_saved_load
|
203
|
+
assert_equal @local_rails.new_record?, true
|
204
|
+
assert_equal @local_roots.new_record?, false
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_lack_of_initial_amazon_product_for_local
|
208
|
+
@local_woody = LocalBook.load_from_amazon!('0736412662')
|
209
|
+
assert_nil AmazonProduct.find_by_amazonable_id(@local_woody.id)
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_ignore_fields
|
213
|
+
assert_nil @local_rails.small_image_url
|
214
|
+
assert_nil @local_rails.medium_image_url
|
215
|
+
assert_nil @local_roots.small_image_url
|
216
|
+
assert_nil @local_roots.medium_image_url
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_locals_load_amazon_attributes_if_needed
|
220
|
+
assert_not_nil @local_rails.amazon.binding
|
221
|
+
assert_not_nil @local_roots.amazon.binding
|
222
|
+
assert_equal @local_rails.amazon.binding, 'Paperback'
|
223
|
+
assert_equal @local_roots.amazon.binding, 'Paperback'
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
data/test/example.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
$: << 'lib'
|
2
|
+
|
3
|
+
require 'acts_as_amazon_product'
|
4
|
+
|
5
|
+
ActiveRecord::Base.establish_connection({:adapter => 'sqlite3', :database => 'test.db'})
|
6
|
+
ActiveRecord::Base.connection.create_table :books, :force => true do |t|
|
7
|
+
t.column :name, :string
|
8
|
+
t.column :asin, :string
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
class Book < ActiveRecord::Base
|
13
|
+
acts_as_amazon_product
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
book = Book.create(:name => 'Rails Recipes')
|
18
|
+
|
19
|
+
puts <<EOS
|
20
|
+
Title: #{book.amazon.title}
|
21
|
+
Author: #{book.amazon.author}
|
22
|
+
Price: #{book.amazon.price}
|
23
|
+
Image: #{book.amazon.small_image_url}
|
24
|
+
Details: #{book.amazon.detail_url}
|
25
|
+
EOS
|
26
|
+
|
27
|
+
|
28
|
+
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: netphase-acts_as_amazon_product
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Scott Nedderman
|
8
|
+
- Chris Beck
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-06-18 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: amazon-ecs
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.5.1
|
25
|
+
version:
|
26
|
+
description:
|
27
|
+
email: scott@netphase.com
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- README
|
34
|
+
files:
|
35
|
+
- .gitignore
|
36
|
+
- CHANGELOG
|
37
|
+
- COPYING
|
38
|
+
- README
|
39
|
+
- Rakefile
|
40
|
+
- VERSION
|
41
|
+
- acts_as_amazon_product.gemspec
|
42
|
+
- generators/acts_as_amazon_product_migration/acts_as_amazon_product_migration_generator.rb
|
43
|
+
- generators/acts_as_amazon_product_migration/templates/migration.rb
|
44
|
+
- init.rb
|
45
|
+
- install.rb
|
46
|
+
- lib/acts_as_amazon_product.rb
|
47
|
+
- lib/amazon_product.rb
|
48
|
+
- tasks/acts_as_amazon_product_tasks.rake
|
49
|
+
- test/acts_as_amazon_product_test.rb
|
50
|
+
- test/config-example.yml
|
51
|
+
- test/example.rb
|
52
|
+
- uninstall.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/netphase/aaap
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --charset=UTF-8
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.2.0
|
76
|
+
signing_key:
|
77
|
+
specification_version: 2
|
78
|
+
summary: A package for simplifying use of the Amazon/ECS API
|
79
|
+
test_files:
|
80
|
+
- test/acts_as_amazon_product_test.rb
|
81
|
+
- test/example.rb
|