solidus_related_products 1.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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.hound.yml +25 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +15 -0
  7. data/CONTRIBUTING.md +81 -0
  8. data/Gemfile +6 -0
  9. data/Guardfile +10 -0
  10. data/LICENSE.md +26 -0
  11. data/README.md +80 -0
  12. data/Rakefile +15 -0
  13. data/app/assets/javascripts/spree/backend/solidus_related_products.js +1 -0
  14. data/app/assets/javascripts/spree/frontend/solidus_related_products.js +1 -0
  15. data/app/assets/stylesheets/spree/backend/solidus_related_products.css +3 -0
  16. data/app/assets/stylesheets/spree/frontend/solidus_related_products.css +3 -0
  17. data/app/controllers/spree/admin/products_controller_decorator.rb +10 -0
  18. data/app/controllers/spree/admin/relation_types_controller.rb +6 -0
  19. data/app/controllers/spree/admin/relations_controller.rb +80 -0
  20. data/app/controllers/spree/api/relations_controller.rb +78 -0
  21. data/app/models/spree/calculator/related_product_discount.rb +50 -0
  22. data/app/models/spree/product_decorator.rb +106 -0
  23. data/app/models/spree/relation.rb +7 -0
  24. data/app/models/spree/relation_type.rb +6 -0
  25. data/app/overrides/add_product_relation_admin_sub_menu_tab.rb +6 -0
  26. data/app/overrides/add_related_product_admin_tabs.rb +6 -0
  27. data/app/views/spree/admin/products/_related_products.html.erb +3 -0
  28. data/app/views/spree/admin/products/_related_products_table.html.erb +42 -0
  29. data/app/views/spree/admin/products/related.html.erb +70 -0
  30. data/app/views/spree/admin/relation_types/_form.html.erb +19 -0
  31. data/app/views/spree/admin/relation_types/edit.html.erb +14 -0
  32. data/app/views/spree/admin/relation_types/index.html.erb +44 -0
  33. data/app/views/spree/admin/relation_types/new.html.erb +14 -0
  34. data/app/views/spree/admin/relations/create.js.erb +5 -0
  35. data/app/views/spree/admin/relations/destroy.js.erb +1 -0
  36. data/app/views/spree/api/relations/show.v1.rabl +2 -0
  37. data/bin/rails +7 -0
  38. data/config/locales/cs.yml +18 -0
  39. data/config/locales/de.yml +18 -0
  40. data/config/locales/en.yml +18 -0
  41. data/config/locales/es.yml +18 -0
  42. data/config/locales/fr.yml +18 -0
  43. data/config/locales/it.yml +18 -0
  44. data/config/locales/nl.yml +18 -0
  45. data/config/locales/pl.yml +18 -0
  46. data/config/locales/pt-BR.yml +18 -0
  47. data/config/locales/ru.yml +18 -0
  48. data/config/locales/sv.yml +18 -0
  49. data/config/routes.rb +24 -0
  50. data/db/migrate/20100308090631_create_relation_types.rb +14 -0
  51. data/db/migrate/20100308092101_create_relations.rb +14 -0
  52. data/db/migrate/20100324123835_add_discount_to_relation.rb +9 -0
  53. data/db/migrate/20111129044813_prefixing_tables_with_spree.rb +6 -0
  54. data/db/migrate/20120208144454_update_relation_types.rb +9 -0
  55. data/db/migrate/20120623014337_update_relations.rb +11 -0
  56. data/db/migrate/20130727004612_add_position_to_spree_relations.rb +5 -0
  57. data/lib/generators/solidus_related_products/install/install_generator.rb +20 -0
  58. data/lib/solidus_related_products.rb +7 -0
  59. data/lib/solidus_related_products/engine.rb +24 -0
  60. data/lib/solidus_related_products/version.rb +18 -0
  61. data/solidus_related_products.gemspec +45 -0
  62. data/spec/controllers/spree/admin/products_controller_decorator_spec.rb +20 -0
  63. data/spec/controllers/spree/admin/relations_controller_spec.rb +96 -0
  64. data/spec/controllers/spree/api/relations_controller_spec.rb +98 -0
  65. data/spec/factories/relation_factory.rb +7 -0
  66. data/spec/factories/relation_type_factory.rb +6 -0
  67. data/spec/features/spree/admin/product_relation_spec.rb +86 -0
  68. data/spec/features/spree/admin/relation_types_spec.rb +97 -0
  69. data/spec/models/spree/calculator/related_product_discount_spec.rb +48 -0
  70. data/spec/models/spree/product_spec.rb +129 -0
  71. data/spec/models/spree/relation_spec.rb +13 -0
  72. data/spec/models/spree/relation_type_spec.rb +18 -0
  73. data/spec/spec_helper.rb +48 -0
  74. data/spec/support/capybara.rb +20 -0
  75. data/spec/support/database_cleaner.rb +23 -0
  76. data/spec/support/factory_girl.rb +7 -0
  77. data/spec/support/spree.rb +18 -0
  78. metadata +388 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 796ec99b0714a1e62195cac718d7ee685e444885
4
+ data.tar.gz: 383f4d8974811a381e1ab46ca51078bdd4bb00d2
5
+ SHA512:
6
+ metadata.gz: df78c358ae876c2d31319614c7122020379ccdd6b7c1720646874b69b15c2164afe2fd03c22671093f6af4d236e0725b98cb0bbbfcf9932c71749741d2e0df75
7
+ data.tar.gz: 335f7498dbe1557d39fed0f93dadb058fbfce3bec0e66ef213b8d2953b479e3bf28d7d28c90a769bc66a60bd8111f317bffd58301a96951948b4b3cb8e77866c
@@ -0,0 +1,12 @@
1
+ *.swp
2
+ .DS_Store
3
+ .rvmrc
4
+ Gemfile.lock
5
+ pkg
6
+ spec/dummy
7
+ *~
8
+ tmp
9
+ .localeapp
10
+ coverage
11
+ .ruby-version
12
+ .ruby-gemset
@@ -0,0 +1,25 @@
1
+ ---
2
+ # Too picky.
3
+ LineLength:
4
+ Enabled: false
5
+
6
+ # This should truly be on for well documented gems.
7
+ Documentation:
8
+ Enabled: false
9
+
10
+ # Neatly aligned code is too swell.
11
+ SpaceBeforeFirstArg:
12
+ Enabled: false
13
+
14
+ # Don't mess with RSpec DSL.
15
+ Blocks:
16
+ Exclude:
17
+ - 'spec/**/*'
18
+
19
+ # It say we should use fail over raise.
20
+ SignalException:
21
+ Enabled: false
22
+
23
+ # Avoid contradictory style rules by enforce single quotes.
24
+ StringLiterals:
25
+ EnforcedStyle: single_quotes
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ -r spec_helper
3
+ -f documentation
@@ -0,0 +1,8 @@
1
+ ---
2
+ inherit_from: .hound.yml
3
+
4
+ AllCops:
5
+ Exclude:
6
+ - spec/dummy/**/*
7
+ - bin/*
8
+ - Guardfile
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.2
5
+ sudo: false
6
+ cache: bundler
7
+ env:
8
+ matrix:
9
+ - SOLIDUS_BRANCH=master
10
+ - SOLIDUS_BRANCH=v1.2
11
+ - SOLIDUS_BRANCH=v1.1
12
+ before_script:
13
+ - bundle exec rake test_app
14
+ script:
15
+ - bundle exec rspec spec
@@ -0,0 +1,81 @@
1
+ # Contributing
2
+
3
+ Spree Related Products is an open source project and we encourage contributions. Please see the [contributors guidelines](http://spreecommerce.com/documentation/contributing_to_spree.html) for more information before contributing.
4
+
5
+ In the spirit of [free software][1], **everyone** is encouraged to help improve this project.
6
+
7
+ Here are some ways *you* can contribute:
8
+
9
+ * by using prerelease versions
10
+ * by reporting [bugs][2]
11
+ * by suggesting new features
12
+ * by writing [translations][3]
13
+ * by writing or editing documentation
14
+ * by writing specifications
15
+ * by writing code (*no patch is too small*: fix typos, add comments, clean up inconsistent whitespace)
16
+ * by refactoring code
17
+ * by resolving [issues][2]
18
+ * by reviewing patches
19
+
20
+ ---
21
+
22
+ ## Filing an issue
23
+
24
+ When filing an issue on this extension, please first do these things:
25
+
26
+ * Verify you can reproduce this issue in a brand new application.
27
+ * Run through the steps to reproduce the issue again.
28
+
29
+ In the issue itself please provide:
30
+
31
+ * A comprehensive list of steps to reproduce the issue.
32
+ * What you're *expecting* to happen compared with what's *actually* happening.
33
+ * The version of Spree *and* the version of Rails.
34
+ * A list of all extensions.
35
+ * Any relevant stack traces ("Full trace" preferred)
36
+ * Your `Gemfile`
37
+
38
+ In 99% of cases, this information is enough to determine the cause and solution to the problem that is being described.
39
+
40
+ ---
41
+
42
+ ## Pull requests
43
+
44
+ We gladly accept pull requests to fix bugs and, in some circumstances, add new features to this extension.
45
+
46
+ Here's a quick guide:
47
+
48
+ 1. Fork the repo.
49
+
50
+ 2. Run the tests. We only take pull requests with passing tests, and it's great to know that you have a clean slate.
51
+
52
+ 3. Create new branch then make changes and add tests for your changes. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, we need tests!
53
+
54
+ 4. Push to your fork and submit a pull request. If the changes will apply cleanly to the latest stable branches and master branch, you will only need to submit one pull request.
55
+
56
+ At this point you're waiting on us. We may suggest some changes or improvements or alternatives.
57
+
58
+ Some things that will increase the chance that your pull request is accepted, taken straight from the Ruby on Rails guide:
59
+
60
+ * Use Rails idioms and helpers.
61
+ * Include tests that fail without your code, and pass with it.
62
+ * Update the documentation, the surrounding one, examples elsewhere, guides, whatever is affected by your contribution.
63
+
64
+ ---
65
+
66
+ ## TL;DR
67
+
68
+ * Fork the repo
69
+ * Clone your repo
70
+ * Run `bundle install`
71
+ * Run `bundle exec rake test_app` to create the test application in `spec/dummy`
72
+ * Make your changes
73
+ * Ensure specs pass by running `bundle exec rspec spec`
74
+ * Ensure all syntax ok by running `rubocop .`
75
+ * Submit your pull request
76
+
77
+ And in case we didn't emphasize it enough: **we love tests!**
78
+
79
+ [1]: http://www.fsf.org/licensing/essays/free-sw.html
80
+ [2]: https://github.com/spree-contrib/spree_related_products/issues
81
+ [3]: https://github.com/spree-contrib/spree_related_products/tree/master/config/locales
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ branch = ENV.fetch('SOLIDUS_BRANCH', 'master')
4
+ gem 'solidus', github: 'solidusio/solidus', branch: branch
5
+
6
+ gemspec
@@ -0,0 +1,10 @@
1
+ guard 'rspec', cmd: 'bundle exec rspec' do
2
+ watch('spec/spec_helper.rb') { 'spec' }
3
+ watch('config/routes.rb') { 'spec/controllers' }
4
+ watch(%r{^spec/(.+)_spec\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
5
+ watch(%r{^app/(.+)_decorator\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
6
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch(%r{^app/(.*)(\.erb)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
8
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
9
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb" }
10
+ end
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2010-2015 Brian Quinn and contributors.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,80 @@
1
+ # Related Products
2
+
3
+ [![Build Status](https://travis-ci.org/solidusio-contrib/solidus_related_products.svg?branch=master)](https://travis-ci.org/solidusio-contrib/solidus_related_products)
4
+ [![Gem](https://img.shields.io/gem/v/solidus_related_products.svg)](https://rubygems.org/gems/solidus_related_products)
5
+ [![License](http://img.shields.io/badge/license-BSD-yellowgreen.svg)](LICENSE.md)
6
+
7
+ This extension provides a generic way for you to define different types of relationships between your products, by defining a RelationType for each type of relationship you'd like to maintain.
8
+
9
+ You can manage RelationTypes via the admin configuration menu, and you can maintain product relationships via __Related Products__ tab on the edit product UI.
10
+
11
+ ## Installation
12
+
13
+ Add to `Gemfile`:
14
+ ```ruby
15
+ gem 'spree_related_products'
16
+ ```
17
+
18
+ Run:
19
+ ```sh
20
+ $ bundle install
21
+ $ bundle exec rails g solidus_related_products:install
22
+ ```
23
+
24
+ ## Possible uses
25
+
26
+ * Accessories
27
+ * Cross Sells
28
+ * Up Sells
29
+ * Compatible Products
30
+ * Replacement Products
31
+ * Warranty & Support Products
32
+
33
+ ## Relation Types
34
+
35
+ When you create a RelationType you can access that set of related products by referencing the relation_type name, see below for an example:
36
+ ```ruby
37
+ rt = Spree::RelationType.create(name: 'Accessories', applies_to: 'Spree::Product')
38
+ => #<Spree::RelationType id: 4, name: "Accessories" ...>
39
+ product = Spree::Product.last
40
+ => #<Spree::Product id: 1060500592 ...>
41
+ product.accessories
42
+ => []
43
+ ```
44
+
45
+ Since respond_to? will not work in this case, you can test whether a relation_type method exists with has_related_products?(method):
46
+
47
+ ```ruby
48
+ product.has_related_products?('accessories')
49
+ # => true
50
+
51
+ if product.has_related_products?('accessories')
52
+ # Display an accessories box..
53
+ end
54
+ ```
55
+
56
+ You can access all related products regardless of RelationType by:
57
+ ```ruby
58
+ product.relations
59
+ => []
60
+ ```
61
+
62
+ **Discounts**
63
+ You can optionally specify a discount amount to be applied if a customer purchases both products.
64
+
65
+ Note: In order for the coupon to be automatically applied, you must create a promotion leaving the __code__ value empty, and adding an Action of type : __RelatedProductDiscount__ (blank codes are required for coupons to be automatically applied).
66
+
67
+ ## Contributing
68
+
69
+ See corresponding [guidelines][4]
70
+
71
+ ---
72
+
73
+ Copyright (c) 2010-2015 [Brian Quinn][5] and [contributors][6], released under the [New BSD License][3]
74
+
75
+ [1]: http://www.fsf.org/licensing/essays/free-sw.html
76
+ [2]: https://github.com/spree-contrib/spree_related_products/issues
77
+ [3]: https://github.com/spree-contrib/spree_related_products/blob/master/LICENSE.md
78
+ [4]: https://github.com/spree-contrib/spree_related_products/blob/master/CONTRIBUTING.md
79
+ [5]: https://github.com/BDQ
80
+ [6]: https://github.com/spree-contrib/spree_related_products/graphs/contributors
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/common_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task default: :spec
10
+
11
+ desc 'Generates a dummy app for testing'
12
+ task :test_app do
13
+ ENV['LIB_NAME'] = 'solidus_related_products'
14
+ Rake::Task['common:test_app'].invoke
15
+ end
@@ -0,0 +1 @@
1
+ //= require spree/backend
@@ -0,0 +1 @@
1
+ //= require spree/frontend
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require spree/backend
3
+ */
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require spree/frontend
3
+ */
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module Admin
3
+ ProductsController.class_eval do
4
+ def related
5
+ load_resource
6
+ @relation_types = Spree::Product.relation_types
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module Spree
2
+ module Admin
3
+ class RelationTypesController < ResourceController
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,80 @@
1
+ module Spree
2
+ module Admin
3
+ class RelationsController < BaseController
4
+ before_action :load_data, only: [:create, :destroy]
5
+
6
+ respond_to :js, :html
7
+
8
+ def create
9
+ @relation = Relation.new(relation_params)
10
+ @relation.relatable = @product
11
+ @relation.related_to = Spree::Variant.find(relation_params[:related_to_id]).product
12
+ @relation.save
13
+
14
+ respond_with(@relation)
15
+ end
16
+
17
+ def update
18
+ @relation = Relation.find(params[:id])
19
+ @relation.update_attribute :discount_amount, relation_params[:discount_amount] || 0
20
+
21
+ redirect_to(related_admin_product_url(@relation.relatable))
22
+ end
23
+
24
+ def update_positions
25
+ params[:positions].each do |id, index|
26
+ model_class.where(id: id).update_all(position: index)
27
+ end
28
+
29
+ respond_to do |format|
30
+ format.js { render text: 'Ok' }
31
+ end
32
+ end
33
+
34
+ def destroy
35
+ @relation = Relation.find(params[:id])
36
+ if @relation.destroy
37
+ flash[:success] = flash_message_for(@relation, :successfully_removed)
38
+
39
+ respond_with(@relation) do |format|
40
+ format.html { redirect_to location_after_destroy }
41
+ format.js { render :partial => "spree/admin/shared/destroy" }
42
+ end
43
+
44
+ else
45
+
46
+ respond_with(@relation) do |format|
47
+ format.html { redirect_to location_after_destroy }
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def relation_params
55
+ params.require(:relation).permit(*permitted_attributes)
56
+ end
57
+
58
+ def permitted_attributes
59
+ [
60
+ :related_to,
61
+ :relation_type,
62
+ :relatable,
63
+ :related_to_id,
64
+ :discount_amount,
65
+ :relation_type_id,
66
+ :related_to_type,
67
+ :position
68
+ ]
69
+ end
70
+
71
+ def load_data
72
+ @product = Spree::Product.friendly.find(params[:product_id])
73
+ end
74
+
75
+ def model_class
76
+ Spree::Relation
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,78 @@
1
+ module Spree
2
+ module Api
3
+ class RelationsController < Spree::Api::BaseController
4
+ before_action :load_data, only: [:create, :destroy]
5
+ before_action :find_relation, only: [:update, :destroy]
6
+
7
+ def create
8
+ authorize! :create, Relation
9
+ @relation = @product.relations.new(relation_params)
10
+ @relation.relatable = @product
11
+ @relation.related_to = Spree::Variant.find(relation_params[:related_to_id]).product
12
+ if @relation.save
13
+ respond_with(@relation, status: 201, default_template: :show)
14
+ else
15
+ invalid_resource!(@relation)
16
+ end
17
+ end
18
+
19
+ def update
20
+ authorize! :update, Relation
21
+ if @relation.update_attributes(relation_params)
22
+ respond_with(@relation, status: 200, default_template: :show)
23
+ else
24
+ invalid_resource!(@relation)
25
+ end
26
+ end
27
+
28
+ def update_positions
29
+ authorize! :update, Relation
30
+ params[:positions].each do |id, index|
31
+ model_class.where(id: id).update_all(position: index)
32
+ end
33
+
34
+ respond_to do |format|
35
+ format.json { render nothing: true, status: 200 }
36
+ format.js { render text: 'Ok' }
37
+ end
38
+ end
39
+
40
+ def destroy
41
+ authorize! :destroy, Relation
42
+ @relation.destroy
43
+ respond_with(@relation, status: 204)
44
+ end
45
+
46
+ private
47
+
48
+ def relation_params
49
+ params.require(:relation).permit(*permitted_attributes)
50
+ end
51
+
52
+ def permitted_attributes
53
+ [
54
+ :related_to,
55
+ :relation_type,
56
+ :relatable,
57
+ :related_to_id,
58
+ :discount_amount,
59
+ :relation_type_id,
60
+ :related_to_type,
61
+ :position
62
+ ]
63
+ end
64
+
65
+ def load_data
66
+ @product = Spree::Product.friendly.find(params[:product_id])
67
+ end
68
+
69
+ def find_relation
70
+ @relation = Relation.find(params[:id])
71
+ end
72
+
73
+ def model_class
74
+ Spree::Relation
75
+ end
76
+ end
77
+ end
78
+ end