solidus_product_feed 1.0.0 → 1.1.0

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