solidus_product_feed 1.0.0 → 1.1.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.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +35 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +10 -2
  6. data/.rspec +2 -1
  7. data/.rubocop.yml +3 -149
  8. data/.rubocop_todo.yml +50 -0
  9. data/CHANGELOG.md +63 -0
  10. data/Gemfile +28 -9
  11. data/LICENSE +2 -2
  12. data/README.md +71 -26
  13. data/Rakefile +4 -19
  14. data/app/decorators/controllers/solidus_product_feed/spree/products_controller_decorator.rb +25 -0
  15. data/app/models/spree/feed_product.rb +39 -10
  16. data/app/overrides/rss_link.rb +2 -0
  17. data/app/views/spree/products/index.rss.builder +10 -12
  18. data/bin/console +17 -0
  19. data/bin/r +13 -0
  20. data/bin/rails +15 -0
  21. data/bin/rake +7 -0
  22. data/bin/sandbox +84 -0
  23. data/bin/sandbox_rails +18 -0
  24. data/bin/setup +8 -0
  25. data/config/locales/en.yml +5 -0
  26. data/config/routes.rb +3 -1
  27. data/lib/generators/solidus_product_feed/install/install_generator.rb +6 -8
  28. data/lib/solidus_product_feed.rb +42 -1
  29. data/lib/solidus_product_feed/engine.rb +9 -10
  30. data/lib/solidus_product_feed/factories.rb +4 -0
  31. data/lib/solidus_product_feed/version.rb +3 -1
  32. data/lib/spree_product_feed.rb +2 -0
  33. data/solidus_product_feed.gemspec +36 -30
  34. data/spec/controllers/products_controller_spec.rb +14 -2
  35. data/spec/models/spree/feed_product_spec.rb +10 -1
  36. data/spec/spec_helper.rb +23 -13
  37. data/spec/support/devise.rb +5 -0
  38. metadata +53 -92
  39. data/.travis.yml +0 -21
  40. data/Guardfile +0 -10
  41. data/app/assets/javascripts/admin/solidus_product_feed.js +0 -1
  42. data/app/assets/javascripts/spree/backend/solidus_product_feed.js +0 -0
  43. data/app/assets/javascripts/spree/backend/spree_product_feed.js +0 -0
  44. data/app/assets/javascripts/spree/frontend/solidus_product_feed.js +0 -0
  45. data/app/assets/javascripts/spree/frontend/spree_product_feed.js +0 -0
  46. data/app/assets/javascripts/store/solidus_product_feed.js +0 -1
  47. data/app/assets/stylesheets/admin/solidus_product_feed.css +0 -3
  48. data/app/assets/stylesheets/spree/backend/solidus_product_feed.css +0 -0
  49. data/app/assets/stylesheets/spree/backend/spree_product_feed.css +0 -0
  50. data/app/assets/stylesheets/spree/frontend/solidus_product_feed.css +0 -0
  51. data/app/assets/stylesheets/spree/frontend/spree_product_feed.css +0 -0
  52. data/app/assets/stylesheets/store/solidus_product_feed.css +0 -3
  53. data/app/controllers/spree/products_controller_decorator.rb +0 -18
  54. data/script/rails +0 -7
data/Rakefile CHANGED
@@ -1,21 +1,6 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
1
+ # frozen_string_literal: true
3
2
 
4
- require 'rspec/core/rake_task'
5
- require 'spree/testing_support/common_rake'
3
+ require 'solidus_dev_support/rake_tasks'
4
+ SolidusDevSupport::RakeTasks.install
6
5
 
7
- RSpec::Core::RakeTask.new
8
-
9
- task :default do
10
- if Dir["spec/dummy"].empty?
11
- Rake::Task[:test_app].invoke
12
- Dir.chdir("../../")
13
- end
14
- Rake::Task[:spec].invoke
15
- end
16
-
17
- desc 'Generates a dummy app for testing'
18
- task :test_app do
19
- ENV['LIB_NAME'] = 'spree_product_feed'
20
- Rake::Task['common:test_app'].invoke("Spree::User")
21
- end
6
+ task default: 'extension:specs'
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusProductFeed
4
+ module Spree
5
+ module ProductsControllerDecorator
6
+ def self.prepended(klass)
7
+ klass.respond_to :rss, only: :index
8
+ klass.before_action :verify_requested_format!, only: :index
9
+ end
10
+
11
+ def index
12
+ load_feed_products if request.format.rss?
13
+ super
14
+ end
15
+
16
+ private
17
+
18
+ def load_feed_products
19
+ @feed_products = ::Spree::Product.all.map(&SolidusProductFeed.feed_product_class.method(:new))
20
+ end
21
+
22
+ ::Spree::ProductsController.prepend self
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Spree
2
4
  class FeedProduct
3
5
  attr_reader :product
@@ -6,20 +8,38 @@ module Spree
6
8
  @product = product
7
9
  end
8
10
 
9
- def id
10
- product.id
11
+ def schema
12
+ {
13
+ 'g:id' => id,
14
+ 'title' => title,
15
+ 'description' => description,
16
+ 'link' => link,
17
+ 'g:image_link' => image_link,
18
+ 'g:condition' => condition,
19
+ 'g:price' => price,
20
+ 'g:availability' => availability,
21
+ 'g:brand' => brand,
22
+ 'g:mpn' => mpn,
23
+ 'category' => category,
24
+ }
11
25
  end
12
26
 
27
+ delegate :id, to: :product
28
+
13
29
  def title
14
30
  product.name
15
31
  end
16
32
 
17
- def description
18
- product.description
33
+ delegate :description, to: :product
34
+
35
+ def link
36
+ ->(view) { view.product_url(product) }
19
37
  end
20
38
 
21
- # Must be selected from https://support.google.com/merchants/answer/1705911
22
- def category
39
+ def image_link
40
+ return unless product.images.any?
41
+
42
+ product.images.first.attachment.url(:large)
23
43
  end
24
44
 
25
45
  # Must be "new", "refurbished", or "used".
@@ -28,12 +48,21 @@ module Spree
28
48
  end
29
49
 
30
50
  def price
31
- Spree::Money.new(product.price)
51
+ Spree::Money.new(product.price).money.format(symbol: false, with_currency: true)
32
52
  end
33
53
 
34
- def image_link
35
- return unless product.images.any?
36
- product.images.first.attachment.url(:large)
54
+ def availability
55
+ product.master.in_stock? ? 'in stock' : 'out of stock'
56
+ end
57
+
58
+ def brand; end
59
+
60
+ def mpn
61
+ product.master.sku
62
+ end
63
+
64
+ def category
65
+ # Must be selected from https://support.google.com/merchants/answer/1705911
37
66
  end
38
67
  end
39
68
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Deface::Override.new(virtual_path: 'layouts/spree_application',
2
4
  name: 'product_rss_link',
3
5
  original: '86987c7feaaea3181df195ca520571d801bbbaf3',
@@ -1,22 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  xml.instruct! :xml, version: "1.0"
2
4
 
3
5
  xml.rss version: "2.0", "xmlns:g" => "http://base.google.com/ns/1.0" do
4
6
  xml.channel do
5
- xml.title current_store.name
6
- xml.link "http://#{current_store.url}"
7
- xml.description "Find out about new products on http://#{current_store.url} first!"
8
- xml.language 'en-us'
7
+ xml.title SolidusProductFeed.evaluate(SolidusProductFeed.title, self)
8
+ xml.link SolidusProductFeed.evaluate(SolidusProductFeed.link, self)
9
+ xml.description SolidusProductFeed.evaluate(SolidusProductFeed.description, self)
10
+ xml.language SolidusProductFeed.evaluate(SolidusProductFeed.language, self)
9
11
 
10
12
  @feed_products.each do |feed_product|
11
13
  xml.item do
12
- xml.tag! 'g:id', feed_product.id
13
- xml.title feed_product.title
14
- xml.description feed_product.description
15
- xml.category feed_product.category if feed_product.category
16
- xml.link product_url(feed_product.product)
17
- xml.tag! 'g:image_link', feed_product.image_link
18
- xml.tag! 'g:condition', feed_product.condition
19
- xml.tag! 'g:price', feed_product.price.money.format(symbol: false, with_currency: true)
14
+ feed_product.schema.each_pair do |tag, value|
15
+ value = value.call(self) if value.respond_to?(:call)
16
+ xml.tag! tag, value
17
+ end
20
18
  end
21
19
  end
22
20
  end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "bundler/setup"
6
+ require "solidus_product_feed"
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+ $LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"])
11
+
12
+ # (If you use this, don't forget to add pry to your Gemfile!)
13
+ # require "pry"
14
+ # Pry.start
15
+
16
+ require "irb"
17
+ IRB.start(__FILE__)
data/bin/r ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('..', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/solidus_product_feed/engine', __dir__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
10
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11
+
12
+ require 'rails/all'
13
+ require 'rails/engine/commands'
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ app_root = 'spec/dummy'
6
+
7
+ unless File.exist? "#{app_root}/bin/rails"
8
+ system "bin/rake", app_root or begin # rubocop:disable Style/AndOr
9
+ warn "Automatic creation of the dummy app failed"
10
+ exit 1
11
+ end
12
+ end
13
+
14
+ Dir.chdir app_root
15
+ exec 'bin/rails', *ARGV
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "rubygems"
5
+ require "bundler/setup"
6
+
7
+ load Gem.bin_path("rake", "rake")
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ case "$DB" in
6
+ postgres|postgresql)
7
+ RAILSDB="postgresql"
8
+ ;;
9
+ mysql)
10
+ RAILSDB="mysql"
11
+ ;;
12
+ sqlite|'')
13
+ RAILSDB="sqlite3"
14
+ ;;
15
+ *)
16
+ echo "Invalid DB specified: $DB"
17
+ exit 1
18
+ ;;
19
+ esac
20
+
21
+ if [ ! -z $SOLIDUS_BRANCH ]
22
+ then
23
+ BRANCH=$SOLIDUS_BRANCH
24
+ else
25
+ BRANCH="master"
26
+ fi
27
+
28
+ extension_name="solidus_product_feed"
29
+
30
+ # Stay away from the bundler env of the containing extension.
31
+ function unbundled {
32
+ ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- $@
33
+ }
34
+
35
+ rm -rf ./sandbox
36
+ unbundled bundle exec rails new sandbox --database="$RAILSDB" \
37
+ --skip-bundle \
38
+ --skip-git \
39
+ --skip-keeps \
40
+ --skip-rc \
41
+ --skip-spring \
42
+ --skip-test \
43
+ --skip-javascript
44
+
45
+ if [ ! -d "sandbox" ]; then
46
+ echo 'sandbox rails application failed'
47
+ exit 1
48
+ fi
49
+
50
+ cd ./sandbox
51
+ cat <<RUBY >> Gemfile
52
+ gem 'solidus', github: 'solidusio/solidus', branch: '$BRANCH'
53
+ gem 'solidus_auth_devise', '>= 2.1.0'
54
+ gem 'rails-i18n'
55
+ gem 'solidus_i18n'
56
+
57
+ gem '$extension_name', path: '..'
58
+
59
+ group :test, :development do
60
+ platforms :mri do
61
+ gem 'pry-byebug'
62
+ end
63
+ end
64
+ RUBY
65
+
66
+ unbundled bundle install --gemfile Gemfile
67
+
68
+ unbundled bundle exec rake db:drop db:create
69
+
70
+ unbundled bundle exec rails generate spree:install \
71
+ --auto-accept \
72
+ --user_class=Spree::User \
73
+ --enforce_available_locales=true \
74
+ --with-authentication=false \
75
+ $@
76
+
77
+ unbundled bundle exec rails generate solidus:auth:install
78
+
79
+ echo
80
+ echo "🚀 Sandbox app successfully created for $extension_name!"
81
+ echo "🚀 Using $RAILSDB and Solidus $BRANCH"
82
+ echo "🚀 Use 'export DB=[postgres|mysql|sqlite]' to control the DB adapter"
83
+ echo "🚀 Use 'export SOLIDUS_BRANCH=<BRANCH-NAME>' to control the Solidus version"
84
+ echo "🚀 This app is intended for test purposes."
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ app_root = 'sandbox'
6
+
7
+ unless File.exist? "#{app_root}/bin/rails"
8
+ warn 'Creating the sandbox app...'
9
+ Dir.chdir "#{__dir__}/.." do
10
+ system "#{__dir__}/sandbox" or begin # rubocop:disable Style/AndOr
11
+ warn 'Automatic creation of the sandbox app failed'
12
+ exit 1
13
+ end
14
+ end
15
+ end
16
+
17
+ Dir.chdir app_root
18
+ exec 'bin/rails', *ARGV
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ gem install bundler --conservative
7
+ bundle update
8
+ bin/rake clobber
@@ -0,0 +1,5 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ hello: Hello world
@@ -1,3 +1,5 @@
1
- Rails.application.routes.draw do
1
+ # frozen_string_literal: true
2
+
3
+ Spree::Core::Engine.routes.draw do
2
4
  # Add your extension routes here
3
5
  end
@@ -1,22 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SolidusProductFeed
2
4
  module Generators
3
5
  class InstallGenerator < Rails::Generators::Base
4
6
  class_option :auto_run_migrations, type: :boolean, default: false
5
7
 
6
8
  def add_migrations
7
- run 'rake railties:install:migrations FROM=spree_product_feed'
8
- end
9
-
10
- def add_javascripts
11
- append_file "vendor/assets/javascripts/spree/backend/all.js", "//= require spree/backend/spree_product_feed\n"
9
+ run 'bin/rails railties:install:migrations FROM=solidus_product_feed'
12
10
  end
13
11
 
14
12
  def run_migrations
15
- run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
13
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]')) # rubocop:disable Metrics/LineLength
16
14
  if run_migrations
17
- run 'rake db:migrate'
15
+ run 'bin/rails db:migrate'
18
16
  else
19
- puts "Skipping rake db:migrate, don't forget to run it!"
17
+ puts 'Skipping bin/rails db:migrate, don\'t forget to run it!' # rubocop:disable Rails/Output
20
18
  end
21
19
  end
22
20
  end
@@ -1,2 +1,43 @@
1
- require 'spree_core'
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_core'
4
+ require 'solidus_support'
5
+
6
+ require 'solidus_product_feed/version'
2
7
  require 'solidus_product_feed/engine'
8
+
9
+ require 'deface'
10
+
11
+ module SolidusProductFeed
12
+ class << self
13
+ attr_writer :title, :link, :description, :language, :feed_product_class
14
+
15
+ def configure
16
+ yield self
17
+ end
18
+
19
+ def evaluate(value, view_context)
20
+ value.respond_to?(:call) ? value.call(view_context) : value
21
+ end
22
+
23
+ def title
24
+ @title ||= ->(view) { view.current_store.name }
25
+ end
26
+
27
+ def link
28
+ @link ||= ->(view) { "http://#{view.current_store.url}" }
29
+ end
30
+
31
+ def description
32
+ @description ||= ->(view) { "Find out about new products on http://#{view.current_store.url} first!" }
33
+ end
34
+
35
+ def language
36
+ @language ||= 'en-us'
37
+ end
38
+
39
+ def feed_product_class
40
+ (@feed_product_class ||= 'Spree::FeedProduct').constantize
41
+ end
42
+ end
43
+ end
@@ -1,20 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spree/core'
4
+ require 'solidus_product_feed'
5
+
1
6
  module SolidusProductFeed
2
7
  class Engine < Rails::Engine
3
- engine_name 'solidus_product_feed'
8
+ include SolidusSupport::EngineExtensions
9
+
10
+ isolate_namespace ::Spree
4
11
 
5
- config.autoload_paths += %W(#{config.root}/lib)
12
+ engine_name 'solidus_product_feed'
6
13
 
7
14
  # use rspec for tests
8
15
  config.generators do |g|
9
16
  g.test_framework :rspec
10
17
  end
11
-
12
- def self.activate
13
- Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator.rb')) do |c|
14
- Rails.configuration.cache_classes ? require(c) : load(c)
15
- end
16
- end
17
-
18
- config.to_prepare(&method(:activate).to_proc)
19
18
  end
20
19
  end