power_reviews 0.1.1 → 0.3.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b2a2e183b2e2a588ad0b7f13a74d761b3d4f5583
4
+ data.tar.gz: dd366a763d0c19fe4bd17e5eaeeb1aef0b0d3789
5
+ SHA512:
6
+ metadata.gz: 6bbbedf27521de7be69d7bb136477ea5535a4d38c2c848eab439ee84dd2f083b256838c3a517223325e07ef328af649802783daec374b0f08d2a6a4eb9515c23
7
+ data.tar.gz: de26c90d3c0cdcc72d339421a71df29a2ea8b7ed8332dfea6656ce45231a1dd6d00d655ff76def731678ff04a6e56e65234230dd657360a1a94f30f5c29534ae
data/README CHANGED
@@ -1,13 +1,73 @@
1
- PowerReviews
2
- ============
1
+ = PowerReviews
3
2
 
4
- Introduction goes here.
3
+ Integrates the third party PowerReviews service with Ruby. Currently focused on Ruby on Rails
4
+ but includes some tools to aid in non-rails tasks like data feed generation and automated
5
+ zip downloads/uploads.
5
6
 
7
+ == Dependencies
6
8
 
7
- Example
8
- =======
9
+ PowerReviews gem requires FasterCSV[http://fastercsv.rubyforge.org/] for csv generation and
10
+ Whenever[http://www.github.com/javan/whenever] for managing your crontab. It also requires that
11
+ a native +zip+ tool be installed.
9
12
 
10
- Example goes here.
13
+ which zip
14
+ # /usr/bin/zip
11
15
 
16
+ == Getting Started
12
17
 
13
- Copyright (c) 2009 [name of plugin creator], released under the MIT license
18
+ Step one, install the gem.
19
+
20
+ In your rails environment file:
21
+
22
+ config.gem 'power_reviews', :source => 'http://gems.k2sportsdev.com'
23
+
24
+ Then
25
+
26
+ rake gems:install
27
+
28
+ or from your shell:
29
+
30
+ gem install power_reviews --source=http://gems.k2sportsdev.com
31
+
32
+ With the gem installed it's now time to generate the necessary files in your rails project.
33
+ From the root of your rails project run:
34
+
35
+ script/generate power_reviews
36
+
37
+ Which will output:
38
+
39
+ exists lib/tasks
40
+ create lib/tasks/power_reviews_tasks.rake
41
+ exists config/initializers
42
+ create config/power_reviews.yml
43
+ create config/initializers/power_reviews.rb
44
+ create config/schedule.rb
45
+
46
+ === Power Reviews configuration
47
+
48
+ Define which files the PowerReviews::Sync class will be looking for when doing its nigtly download
49
+ of files, like the database.yml file in your rails configuration you can have a different configuration
50
+ for each environment. In this example, for development PowerReviews will use the local filesystem instead
51
+ of connection to the ftp server with the live data.
52
+
53
+ [+:protocol+] is the type of sync client you wish to use +:cp+ or +:ftp+
54
+ [+:zip+l] the zip file you will receive from Power Reviews
55
+
56
+ development:
57
+ protocol: cp
58
+ zip: test/brand.zip
59
+ done: test/brand_done.txt
60
+ datafeed: tmp/brand_feed.zip
61
+
62
+ production:
63
+ protocol: ftp
64
+ zip: brand.zip
65
+ done: brand_done.txt
66
+ data_feed: brand_data.zip
67
+ host: partners.powerreviews.com
68
+ username: user
69
+ password: passy
70
+
71
+ == Example
72
+
73
+ Copyright (c) 2009 K2 Sports, released under the MIT license
data/Rakefile CHANGED
@@ -12,11 +12,13 @@ begin
12
12
  gemspec.email = "beaucollins@gmail.com"
13
13
  gemspec.homepage = "http://github.com/beaucollins/power_reviews"
14
14
  gemspec.authors = ["Beau Collins"]
15
- gemspec.add_runtime_dependency 'javan-whenever'
15
+ gemspec.add_runtime_dependency 'whenever'
16
16
  gemspec.add_runtime_dependency 'fastercsv'
17
+ gemspec.add_development_dependency 'activesupport'
18
+ gemspec.add_development_dependency 'shoulda'
17
19
  end
18
20
  rescue LoadError
19
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
21
+ puts "Jeweler not available. Install it with: gem install jeweler"
20
22
  end
21
23
 
22
24
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.3.2
@@ -1,4 +1,4 @@
1
- # For retrieving the zip file from PowerReviews
1
+ # For retrieving the zip file from PowerReviews and delivering your updated data feed
2
2
  #
3
3
  #
4
4
 
@@ -6,11 +6,13 @@ development:
6
6
  protocol: cp
7
7
  zip: test/k2skis.zip
8
8
  done: test/k2skis_done.txt
9
+ datafeed: test/k2skis_data.zip
9
10
 
10
11
  production:
11
12
  protocol: ftp
12
13
  zip: k2skis.zip
13
14
  done: k2skis_done.txt
14
- # host: partners.powerreviews.com
15
- # username: user
16
- # password: passy
15
+ data_feed: k2skis_data.zip
16
+ host: partners.powerreviews.com
17
+ username: user
18
+ password: passy
@@ -1,19 +1,13 @@
1
- # desc "Explaining what the task does"
2
- # task :power_reviews do
3
- # # Task goes here
4
- # end
5
1
  namespace :power_reviews do
6
2
 
7
- desc "Generates the product data feed in csv format"
3
+ desc "Outputs the PowerReviews feed in CSV format"
8
4
  task :feed => :environment do
9
- puts "Generating Power Reviews product feed"
10
- PowerReviews::Feed.process
11
- puts "Completed"
5
+ puts PowerReviews::Feed.process
12
6
  end
13
7
 
14
- desc "Copy the zip file from the ftp and unpack it"
8
+ desc "Copy the zip file from the ftp and unpack it then deliver the product feed"
15
9
  task :sync => :environment do
16
- puts "Fetching power review data"
10
+ puts "Syncing PowerReviews data"
17
11
  PowerReviews::Sync.execute
18
12
  puts "Completed"
19
13
  end
@@ -1,20 +1,31 @@
1
1
  module PowerReviews
2
2
  class Config
3
3
 
4
- def self.merchant_group_id
5
- @@merchant_group_id
6
- end
4
+ class << self
5
+ def merchant_group_id
6
+ @merchant_group_id
7
+ end
7
8
 
8
- def self.merchant_group_id=id
9
- @@merchant_group_id = id
10
- end
9
+ def merchant_group_id=id
10
+ @merchant_group_id = id
11
+ end
11
12
 
12
- def self.site_id
13
- @@site_id
14
- end
13
+ def site_id
14
+ @site_id
15
+ end
15
16
 
16
- def self.site_id=id
17
- @@site_id = id
17
+ def site_id=id
18
+ @site_id = id
19
+ end
20
+
21
+ def review_data_path
22
+ @review_data_path || 'public/system/pwr'
23
+ end
24
+
25
+ def review_data_path=path
26
+ @review_data_path = path
27
+ end
28
+
18
29
  end
19
30
 
20
31
  end
@@ -1,3 +1,5 @@
1
+ require "faster_csv"
2
+
1
3
  module PowerReviews
2
4
 
3
5
  # Collects the feed data then outputs to CSV file for delivery to the power review peeps
@@ -28,8 +30,7 @@ module PowerReviews
28
30
  end
29
31
 
30
32
  def to_csv
31
- require 'fastercsv'
32
- FasterCSV.open("#{RAILS_ROOT}/tmp/power_reviews.csv", 'w') do |csv|
33
+ @csv ||= FasterCSV.generate do |csv|
33
34
  csv << FeedItem.field_names
34
35
  @items.each do |item|
35
36
  csv << item.values
@@ -24,6 +24,9 @@ module PowerReviews
24
24
  puts 'This is the base class'
25
25
  end
26
26
 
27
+ def copy_data_feed(from)
28
+ puts 'This is the base class'
29
+ end
27
30
 
28
31
  # do any cleanup necessary
29
32
  def cleanup
@@ -16,6 +16,10 @@ module PowerReviews
16
16
  FileUtils.cp(@config['zip'], to)
17
17
  end
18
18
 
19
+ def copy_data_feed(from)
20
+ # do nothing, leave the zip where it is
21
+ end
22
+
19
23
  end
20
24
  end
21
25
  end
@@ -20,6 +20,11 @@ module PowerReviews
20
20
  client.getbinaryfile(@config['zip'], to)
21
21
  end
22
22
 
23
+ # Puts the data_feed on the specified ftp server
24
+ def copy_data_feed(from)
25
+ client.putbinaryfile(from, @config['data_feed'])
26
+ end
27
+
23
28
  # do any cleanup necessary
24
29
  def cleanup
25
30
  @client.close
@@ -0,0 +1,100 @@
1
+ require 'find'
2
+ require 'rexml/document'
3
+
4
+ module PowerReviews
5
+
6
+ class ReviewData
7
+
8
+ class MissingData < StandardError; end;
9
+
10
+ DATA_FILES = ['review_data_complete', 'review_data_summary']
11
+
12
+ class << self
13
+
14
+ # retrieve the summary data for the given page_id
15
+ def summary(page_id)
16
+ document.summary(page_id)
17
+ rescue MissingData
18
+ nil
19
+ end
20
+
21
+ def reload!
22
+ @document = nil
23
+ end
24
+
25
+ protected
26
+
27
+ def document
28
+ @document ||= new
29
+ end
30
+
31
+ end
32
+
33
+
34
+ # initializes a new ReviewData document
35
+ def initialize(search_path=nil)
36
+ @search_path = search_path || PowerReviews::Config.review_data_path
37
+ end
38
+
39
+ def summary(page_id)
40
+ node = nil
41
+ summary_data.elements.each("//pageid") do |e|
42
+ node = e.parent if e.get_text == page_id
43
+ end
44
+ !node.nil? ? Summary.new(node) : nil
45
+ end
46
+
47
+ def summary_data
48
+ @summary_data ||= read_document('review_data_summary')
49
+ end
50
+
51
+ def product_data
52
+ @product_data ||= read_document('review_data_complete')
53
+ end
54
+
55
+ protected
56
+
57
+ def read_document(name)
58
+ REXML::Document.new(File.new(xml_documents[name]))
59
+ end
60
+
61
+ def xml_documents
62
+ return @files unless @files.nil?
63
+ files = {}
64
+ Find.find(@search_path) do |path|
65
+ bn = File.basename(path, '.xml')
66
+ files[bn] = path if DATA_FILES.include?(bn)
67
+ end
68
+ missing = DATA_FILES.select { |f| files[f].blank? }
69
+ raise MissingData, "missing Power Reviews xml: #{missing.collect {|f| f + ".xml"}.join(', ')}" unless missing.empty?
70
+ @files = files
71
+ @files
72
+ end
73
+
74
+ class Summary
75
+
76
+ attr_reader :full_name, :average_rating, :reviews
77
+
78
+ def initialize(element)
79
+ @element = element
80
+ @full_name = text_for_element('name')
81
+ @average_rating = text_for_element('average_rating_decimal').to_s.to_f
82
+ @reviews = text_for_element('fullreviews').to_s.to_i
83
+ end
84
+
85
+ protected
86
+
87
+ def text_for_element(name)
88
+ element = nil
89
+ @element.each_element(name) { |e| element = e if element.nil? }
90
+ element.nil? ? '' : element.get_text
91
+ end
92
+
93
+
94
+ end
95
+
96
+
97
+ end
98
+
99
+
100
+ end
@@ -1,6 +1,7 @@
1
1
  require 'power_reviews/protocols/base'
2
2
  require 'power_reviews/protocols/cp'
3
3
  require 'power_reviews/protocols/ftp'
4
+ require 'power_reviews/feed'
4
5
 
5
6
  module PowerReviews
6
7
  # Downloads the ftp file and stores it in the correct location unzipped
@@ -13,29 +14,44 @@ module PowerReviews
13
14
  :ftp => Protocols::Ftp
14
15
  }
15
16
 
16
- # Execute the necessary actions
17
- def self.execute
18
- self.start do |client, config|
17
+ class << self
18
+
19
+ # Execute the necessary actions
20
+ def execute
21
+ self.start do |client, config|
19
22
 
20
- zip_path = "#{RAILS_ROOT}/public/system/reviews.zip"
23
+ zip_path = "#{Rails.root}/public/system/reviews.zip"
21
24
 
22
- unless client.done?
23
- FileUtils.mkdir_p(File.dirname(zip_path))
24
- # we need the correct path to be setup
25
- client.copy_zip(zip_path)
26
- `cd #{File.dirname(zip_path)} && unzip -o #{zip_path}`
27
- client.done!
28
- end
25
+ unless client.done?
26
+ FileUtils.mkdir_p(File.dirname(zip_path))
27
+ # we need the correct path to be setup
28
+ client.copy_zip(zip_path)
29
+ `cd #{File.dirname(zip_path)} && unzip -o #{zip_path}`
30
+ client.done!
31
+ end
29
32
 
33
+ # zip up the powerreviews data tell the client to store it
34
+ data_path = "#{RAILS_ROOT}/tmp/review_data.csv"
35
+ File.open(data_path, 'w') do |f|
36
+ f.puts PowerReviews::Feed.process
37
+ end
38
+ client.copy_data_feed(data_path)
39
+
40
+ end
30
41
  end
31
- end
32
42
 
33
- # Given the environment loads up the yaml file and creates a new instance
34
- def self.start
35
- config = YAML::load(File.open("#{RAILS_ROOT}/config/power_reviews.yml"))[RAILS_ENV] || {}
36
- syncer = PROTOCOLS[config.delete('protocol').intern].new(config)
37
- yield syncer, config
38
- syncer.cleanup
43
+ # Given the environment loads up the yaml file and creates a new instance
44
+ def start
45
+ config = self.configure
46
+ syncer = PROTOCOLS[config.delete('protocol').intern].new(config)
47
+ yield syncer, config
48
+ syncer.cleanup
49
+ end
50
+
51
+ def configure
52
+ @config ||= YAML::load(File.open("#{RAILS_ROOT}/config/power_reviews.yml"))[Rails.env] || {}
53
+ end
54
+
39
55
  end
40
56
 
41
57
  end
@@ -1,10 +1,51 @@
1
1
  module PowerReviews
2
2
  module ViewHelpers
3
+
4
+ # generates hReview compatible HTML for the given page_id
5
+ # renders the content as HTML at render time instead of relying
6
+ # on the Power Reviews javascript library to render the review content
7
+ def power_reviews_hreview(page_id, &blk)
8
+
9
+ summary = PowerReviews::ReviewData.summary(page_id)
10
+
11
+ if block_given?
12
+ yield summary unless summary.nil?
13
+ elsif !summary.nil?
3
14
 
4
- def power_reviews_javascript_tag
5
- javascript_include_tag('/system/pwr/engine/js/full')
15
+ <<-review
16
+ <div class='hreview-aggregate'>
17
+ <span class="item">
18
+ <span class="fn">#{summary.full_name}</span>
19
+ </span>
20
+ <span class="rating">
21
+ <span class="average">#{summary.average_rating}</span>
22
+ </span>
23
+ based on
24
+ <span class="count">#{summary.reviews}</span> user reviews.
25
+ </div>
26
+ review
27
+ else
28
+ ''
29
+ end
30
+ end
31
+
32
+ # Includes the power reviews javascript, optionally provide the path to
33
+ # the javascript file if not installed in the default location
34
+ def power_reviews_javascript_tag(path_to_file = '/system/pwr/engine/js/full')
35
+ unless @power_reviews_javascript_needed.nil?
36
+ javascript_include_tag(path_to_file)
37
+ end
6
38
  end
7
39
 
40
+ # Generates the javascript variables for a page that will be rendering
41
+ # PowerReviews elements
42
+ #
43
+ # Options:
44
+ #
45
+ # +:locale+ - default: en_US
46
+ # +:zip_location+ - where Power Reviews data is stored default: /system/
47
+ # +:pr_style_sheet - Location of custom Power Reviews stylesheet default: "" (empty string)
48
+ #
8
49
  def power_reviews_javascript_variables(options = {})
9
50
  options = {
10
51
  :locale => 'en_US',
@@ -15,31 +56,65 @@ module PowerReviews
15
56
  options.collect { |key, val| "var pr_#{key} = '#{val}';" unless val.blank? }.compact!.join("\n")
16
57
  end
17
58
  end
18
-
59
+
60
+ # Generates JavaScript to display the Power Reviews "snippet" element. Will show a summary
61
+ # of the reviews for the given +page_id+.
62
+ #
63
+ # Arguments:
64
+ # +page_id+ - the identifier for the product
65
+ # +write_review_url+ - the url to link to a page where the user can author a review
66
+ # +review_ancor+ - the url or anchor that links to the full reviews. Default: "#ReviewHeader"
19
67
  def power_reviews_snippet(page_id, write_review_url, review_anchor = '#ReviewHeader')
68
+ @power_reviews_javascript_needed = true
20
69
  javascript_tag do
21
70
  <<-eos
22
- POWERREVIEWS.display.snippet(document, {
23
- pr_page_id : '#{page_id}',
24
- pr_write_review : '#{write_review_url}',
25
- pr_read_review : '#{review_anchor}'
26
- });
71
+ if(POWERREVIEWS){
72
+ POWERREVIEWS.display.snippet(document, {
73
+ pr_page_id : '#{page_id}',
74
+ pr_write_review : '#{write_review_url}',
75
+ pr_read_review : '#{review_anchor}'
76
+ });
77
+ }
27
78
  eos
28
79
  end
29
80
  end
30
-
81
+
82
+ # Displays the full reviews for the given +page_id+
83
+ #
84
+ # Arguments:
85
+ # +page_id+ - The identifier for the item to show reviews for
86
+ # +write_review_url+ - A url for a page where the user can write a review for the given product
31
87
  def power_reviews_display(page_id, write_review_url)
88
+ @power_reviews_javascript_needed = true
32
89
  javascript_tag do
33
90
  <<-eos
34
- POWERREVIEWS.display.engine(document, {
35
- pr_page_id : '#{page_id}',
36
- pr_write_review : '#{write_review_url}'
37
- });
91
+ if(POWERREVIEWS){
92
+ POWERREVIEWS.display.engine(document, {
93
+ pr_page_id : '#{page_id}',
94
+ pr_write_review : '#{write_review_url}'
95
+ });
96
+ }
38
97
  eos
39
98
  end
40
99
  end
41
100
 
101
+ # Generates the javascript that renders the PowerReviews authoring form.
102
+ #
103
+ # Arguments:
104
+ # +page_id+ - The id of the item being reviewd
105
+ #
106
+ # Options:
107
+ # +:locale+ default ""
108
+ # +:site_id+ default: PowerReviews::Config.site_id
109
+ # +:merchant_group_id+ default: PowerReviews::Config.merchant_group_id
110
+ # +:source+ default: 'web'
111
+ # +:merchant_user_id+ default: ''
112
+ # +:merchant_user_email+ default: ''
113
+ # +:promo_code+ default: ''
114
+ # +:style_sheet+ default: ''
115
+
42
116
  def power_reviews_form(page_id, options = {})
117
+ @power_reviews_javascript_needed = true
43
118
  options = {
44
119
  :locale => '',
45
120
  :site_id => PowerReviews::Config.site_id,
data/lib/power_reviews.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'power_reviews/config'
2
+ require 'power_reviews/review_data'
2
3
 
3
4
  require 'power_reviews/feed_item'
4
5
  require 'power_reviews/feed'