power_reviews 0.1.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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'