spree_core 4.0.8 → 4.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree.js +0 -1
  3. data/app/finders/spree/products/find.rb +19 -6
  4. data/app/finders/spree/variants/option_types_finder.rb +21 -0
  5. data/app/finders/spree/variants/visible_finder.rb +22 -0
  6. data/app/helpers/spree/base_helper.rb +48 -18
  7. data/app/helpers/spree/products_helper.rb +76 -8
  8. data/app/models/concerns/spree/user_methods.rb +2 -2
  9. data/app/models/spree/app_dependencies.rb +1 -7
  10. data/app/models/spree/credit_card.rb +4 -5
  11. data/app/models/spree/image/configuration/active_storage.rb +9 -1
  12. data/app/models/spree/image.rb +52 -3
  13. data/app/models/spree/line_item.rb +1 -2
  14. data/app/models/spree/option_type.rb +4 -0
  15. data/app/models/spree/order/address_book.rb +20 -7
  16. data/app/models/spree/order.rb +12 -12
  17. data/app/models/spree/payment_method.rb +8 -0
  18. data/app/models/spree/preferences/preferable.rb +1 -1
  19. data/app/models/spree/product.rb +7 -6
  20. data/app/models/spree/promotion/actions/create_item_adjustments.rb +1 -1
  21. data/app/models/spree/promotion_handler/coupon.rb +2 -1
  22. data/app/models/spree/return_item/eligibility_validator/base_validator.rb +1 -1
  23. data/app/models/spree/store.rb +2 -1
  24. data/app/models/spree/taxon.rb +2 -6
  25. data/app/models/spree/variant.rb +2 -14
  26. data/app/models/spree/zone.rb +6 -3
  27. data/app/presenters/spree/product_summary_presenter.rb +26 -0
  28. data/app/presenters/spree/variant_presenter.rb +69 -0
  29. data/app/presenters/spree/variants/option_types_presenter.rb +74 -0
  30. data/app/presenters/spree/variants/options_presenter.rb +49 -0
  31. data/app/services/spree/checkout/get_shipping_rates.rb +10 -7
  32. data/app/services/spree/checkout/update.rb +2 -13
  33. data/config/locales/en.yml +156 -14
  34. data/db/default/spree/stores.rb +8 -3
  35. data/db/migrate/20140309033438_create_store_from_preferences.rb +8 -4
  36. data/db/migrate/20191005121504_add_store_id_to_payment_methods.rb +7 -0
  37. data/db/migrate/20191016134113_add_deafult_value_for_store_default_currency.rb +5 -0
  38. data/db/migrate/20200102141311_add_social_to_spree_stores.rb +7 -0
  39. data/lib/generators/spree/dummy/dummy_generator.rb +3 -1
  40. data/lib/generators/spree/dummy/templates/initializers/bullet.rb +5 -0
  41. data/lib/generators/spree/install/install_generator.rb +13 -5
  42. data/lib/generators/spree/install/templates/config/initializers/spree.rb +0 -1
  43. data/lib/generators/spree/install/templates/config/initializers/spree_storefront.rb +1 -0
  44. data/lib/generators/spree/install/templates/config/spree_storefront.yml +67 -0
  45. data/lib/spree/core/controller_helpers/order.rb +12 -6
  46. data/lib/spree/core/controller_helpers/store.rb +2 -2
  47. data/lib/spree/core/search/base.rb +59 -22
  48. data/lib/spree/core/version.rb +1 -3
  49. data/lib/spree/core.rb +0 -1
  50. data/lib/spree/money.rb +8 -1
  51. data/lib/spree/permitted_attributes.rb +3 -2
  52. data/lib/spree/testing_support/capybara_ext.rb +0 -52
  53. data/lib/spree/testing_support/common_rake.rb +1 -1
  54. data/lib/spree/testing_support/factories/store_factory.rb +3 -0
  55. data/lib/spree/testing_support/order_walkthrough.rb +7 -3
  56. data/spree_core.gemspec +9 -15
  57. metadata +49 -34
  58. data/app/finders/spree/addresses/find.rb +0 -17
  59. data/app/services/spree/account/addresses/base.rb +0 -39
  60. data/app/services/spree/account/addresses/create.rb +0 -18
  61. data/app/services/spree/account/addresses/update.rb +0 -18
  62. data/lib/spree/database_type_utilities.rb +0 -12
@@ -0,0 +1,67 @@
1
+ default:
2
+ navigation:
3
+ - title: Women
4
+ subtitle: Categories
5
+ url: /t/women
6
+ items:
7
+ - :title: Skirts
8
+ :url: /t/women/skirts
9
+ - :title: Dresses
10
+ :url: /t/women/dresses
11
+ - :title: Shirts and Blouses
12
+ :url: /t/women/shirts-and-blouses
13
+ - :title: Sweaters
14
+ :url: /t/women/sweaters
15
+ - :title: Tops and T-shirts
16
+ :url: /t/women/tops-and-t-shirts
17
+ - :title: Jackets and Coats
18
+ :url: /t/women/jackets-and-coats
19
+ promo_banners:
20
+ - subtitle: New collection
21
+ title: Summer 2019
22
+ url: /t/summer-collection
23
+ image: 'meganav/promo_banner_left-first-category.jpg'
24
+ - subtitle: Special Offers
25
+ title: Get up to 30% off
26
+ url: /t/special-offers
27
+ image: 'meganav/promo_banner_right-first-category.jpg'
28
+ - title: Men
29
+ subtitle: Categories
30
+ url: /t/men
31
+ items:
32
+ - :title: Shirts
33
+ :url: /t/men/shirts
34
+ - :title: T-shirts
35
+ :url: /t/men/t-shirts
36
+ - :title: Sweaters
37
+ :url: /t/men/sweaters
38
+ - :title: Jackets and Coats
39
+ :url: /t/men/jackets-and-coats
40
+ promo_banners:
41
+ - subtitle: New collection
42
+ title: Summer 2019
43
+ url: /t/summer-collection
44
+ image: 'meganav/promo_banner_left-second-category.jpg'
45
+ - subtitle: Special Offers
46
+ title: Get up to 30% off
47
+ url: /t/special-offers
48
+ image: 'meganav/promo_banner_right-second-category.jpg'
49
+ - title: Sportswear
50
+ subtitle: Categories
51
+ url: /t/sportswear
52
+ items:
53
+ - :title: Tops
54
+ :url: /t/sportswear/tops
55
+ - :title: Sweatshirts
56
+ :url: /t/sportswear/sweatshirts
57
+ - :title: Pants
58
+ :url: /t/sportswear/pants
59
+ promo_banners:
60
+ - subtitle: New collection
61
+ title: Summer 2019
62
+ url: /t/summer-collection
63
+ image: 'meganav/promo_banner_left-third-category.jpg'
64
+ - subtitle: Special Offers
65
+ title: Get up to 30% off
66
+ url: /t/special-offers
67
+ image: 'meganav/promo_banner_right-third-category.jpg'
@@ -5,8 +5,6 @@ module Spree
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- before_action :set_current_order
9
-
10
8
  helper_method :current_order
11
9
  helper_method :simple_current_order
12
10
  end
@@ -28,6 +26,7 @@ module Spree
28
26
  # The current incomplete order from the token for use in cart and during checkout
29
27
  def current_order(options = {})
30
28
  options[:create_order_if_necessary] ||= false
29
+ options[:includes] ||= true
31
30
 
32
31
  if @current_order
33
32
  @current_order.last_ip_address = ip_address
@@ -66,8 +65,8 @@ module Spree
66
65
 
67
66
  private
68
67
 
69
- def last_incomplete_order
70
- @last_incomplete_order ||= try_spree_current_user.last_incomplete_spree_order(current_store)
68
+ def last_incomplete_order(includes = {})
69
+ @last_incomplete_order ||= try_spree_current_user.last_incomplete_spree_order(current_store, includes: includes)
71
70
  end
72
71
 
73
72
  def current_order_params
@@ -77,8 +76,15 @@ module Spree
77
76
  def find_order_by_token_or_user(options = {}, with_adjustments = false)
78
77
  options[:lock] ||= false
79
78
 
79
+ includes = if options[:includes]
80
+ { line_items: [variant: [:images, :option_values, :product]] }
81
+ else
82
+ {}
83
+ end
84
+
80
85
  # Find any incomplete orders for the token
81
- incomplete_orders = Spree::Order.incomplete.includes(line_items: [variant: [:images, :option_values, :product]])
86
+ incomplete_orders = Spree::Order.incomplete.includes(includes)
87
+
82
88
  token_order_params = current_order_params.except(:user_id)
83
89
  order = if with_adjustments
84
90
  incomplete_orders.includes(:adjustments).lock(options[:lock]).find_by(token_order_params)
@@ -87,7 +93,7 @@ module Spree
87
93
  end
88
94
 
89
95
  # Find any incomplete orders for the current user
90
- order = last_incomplete_order if order.nil? && try_spree_current_user
96
+ order = last_incomplete_order(includes) if order.nil? && try_spree_current_user
91
97
 
92
98
  order
93
99
  end
@@ -11,7 +11,7 @@ module Spree
11
11
  end
12
12
 
13
13
  def current_currency
14
- Spree::Config[:currency]
14
+ current_store.default_currency
15
15
  end
16
16
 
17
17
  def current_store
@@ -43,7 +43,7 @@ module Spree
43
43
  private
44
44
 
45
45
  def current_tax_zone
46
- @current_tax_zone ||= current_order.try(:tax_zone) || Spree::Zone.default_tax
46
+ @current_tax_zone ||= @current_order&.tax_zone || Spree::Zone.default_tax
47
47
  end
48
48
  end
49
49
  end
@@ -13,7 +13,7 @@ module Spree
13
13
  end
14
14
 
15
15
  def retrieve_products
16
- @products = get_base_scope
16
+ @products = extended_base_scope&.available
17
17
  curr_page = page || 1
18
18
 
19
19
  unless Spree::Config.show_products_without_price
@@ -33,34 +33,37 @@ module Spree
33
33
 
34
34
  protected
35
35
 
36
- def get_base_scope
36
+ def extended_base_scope
37
37
  base_scope = Spree::Product.spree_base_scopes.active
38
- base_scope = base_scope.in_taxon(taxon) unless taxon.blank?
39
38
  base_scope = get_products_conditions_for(base_scope, keywords)
39
+ base_scope = Spree::Products::Find.new(
40
+ scope: base_scope,
41
+ params: {
42
+ filter: {
43
+ price: price,
44
+ option_value_ids: option_value_ids,
45
+ taxons: taxon&.id
46
+ },
47
+ sort_by: sort_by
48
+ },
49
+ current_currency: current_currency
50
+ ).execute
40
51
  base_scope = add_search_scopes(base_scope)
41
52
  base_scope = add_eagerload_scopes(base_scope)
42
53
  base_scope
43
54
  end
44
55
 
45
56
  def add_eagerload_scopes(scope)
46
- # TL;DR Switch from `preload` to `includes` as soon as Rails starts honoring
47
- # `order` clauses on `has_many` associations when a `where` constraint
48
- # affecting a joined table is present (see
49
- # https://github.com/rails/rails/issues/6769).
50
- #
51
- # Ideally this would use `includes` instead of `preload` calls, leaving it
52
- # up to Rails whether associated objects should be fetched in one big join
53
- # or multiple independent queries. However as of Rails 4.1.8 any `order`
54
- # defined on `has_many` associations are ignored when Rails builds a join
55
- # query.
56
- #
57
- # Would we use `includes` in this particular case, Rails would do
58
- # separate queries most of the time but opt for a join as soon as any
59
- # `where` constraints affecting joined tables are added to the search;
60
- # which is the case as soon as a taxon is added to the base scope.
61
- scope = scope.preload(:tax_category)
62
- scope = scope.preload(master: :prices)
63
- scope = scope.preload(master: :images) if include_images
57
+ scope = scope.includes(
58
+ :tax_category,
59
+ variants: [
60
+ { images: { attachment_attachment: :blob } }
61
+ ],
62
+ master: [
63
+ :prices,
64
+ { images: { attachment_attachment: :blob } }
65
+ ]
66
+ )
64
67
  scope
65
68
  end
66
69
 
@@ -68,6 +71,7 @@ module Spree
68
71
  if search.is_a?(ActionController::Parameters)
69
72
  search.each do |name, scope_attribute|
70
73
  scope_name = name.to_sym
74
+
71
75
  base_scope = if base_scope.respond_to?(:search_scopes) && base_scope.search_scopes.include?(scope_name.to_sym)
72
76
  base_scope.send(scope_name, *scope_attribute)
73
77
  else
@@ -81,15 +85,48 @@ module Spree
81
85
  # method should return new scope based on base_scope
82
86
  def get_products_conditions_for(base_scope, query)
83
87
  unless query.blank?
84
- base_scope = base_scope.like_any([:name, :description], query.split)
88
+ base_scope = base_scope.like_any([:name, :description], [query])
89
+ end
90
+ base_scope
91
+ end
92
+
93
+ def get_products_option_values_conditions(base_scope, option_value_ids)
94
+ unless option_value_ids.blank?
95
+ base_scope = base_scope.joins(variants: :option_values).where(spree_option_values: { id: option_value_ids })
85
96
  end
86
97
  base_scope
87
98
  end
88
99
 
100
+ def get_price_range(price_param)
101
+ return if price_param.blank?
102
+
103
+ less_than_string = I18n.t('activerecord.attributes.spree/product.less_than')
104
+
105
+ if price_param.include? less_than_string
106
+ low_price = 0
107
+ high_price = Monetize.parse(price_param.remove("#{less_than_string} ")).to_i
108
+ else
109
+ low_price, high_price = Monetize.parse_collection(price_param).map(&:to_i)
110
+ end
111
+
112
+ "#{low_price},#{high_price}"
113
+ end
114
+
115
+ def build_option_value_ids(params)
116
+ filter_params = Spree::OptionType.all.map(&:filter_param)
117
+
118
+ filter_params.reduce([]) do |acc, filter_param|
119
+ acc + params[filter_param].to_s.split(',')
120
+ end
121
+ end
122
+
89
123
  def prepare(params)
90
124
  @properties[:taxon] = params[:taxon].blank? ? nil : Spree::Taxon.find(params[:taxon])
91
125
  @properties[:keywords] = params[:keywords]
126
+ @properties[:option_value_ids] = build_option_value_ids(params)
127
+ @properties[:price] = get_price_range(params[:price])
92
128
  @properties[:search] = params[:search]
129
+ @properties[:sort_by] = params[:sort_by] || 'default'
93
130
  @properties[:include_images] = params[:include_images]
94
131
 
95
132
  per_page = params[:per_page].to_i
@@ -1,7 +1,5 @@
1
1
  module Spree
2
- VERSION = '4.0.8'.freeze
3
-
4
2
  def self.version
5
- VERSION
3
+ '4.1.0.rc1'
6
4
  end
7
5
  end
data/lib/spree/core.rb CHANGED
@@ -93,7 +93,6 @@ require 'spree/money'
93
93
  require 'spree/permitted_attributes'
94
94
  require 'spree/service_module'
95
95
  require 'spree/dependencies_helper'
96
- require 'spree/database_type_utilities'
97
96
 
98
97
  require 'spree/core/importer'
99
98
  require 'spree/core/query_filters'
data/lib/spree/money.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'money'
2
2
 
3
3
  Money.locale_backend = :i18n
4
+ Money.rounding_mode = BigDecimal::ROUND_HALF_UP
4
5
 
5
6
  module Spree
6
7
  class Money
@@ -18,6 +19,7 @@ module Spree
18
19
  delegate :cents, :currency, to: :money
19
20
 
20
21
  def initialize(amount, options = {})
22
+ use_default_currency
21
23
  @money = Monetize.parse([amount, (options[:currency] || Spree::Config[:currency])].join)
22
24
  @options = Spree::Money.default_formatting_rules.merge(options)
23
25
  end
@@ -27,7 +29,7 @@ module Spree
27
29
  end
28
30
 
29
31
  def to_s
30
- money.format(options)
32
+ money&.format(options)
31
33
  end
32
34
 
33
35
  # 1) prevent blank, breaking spaces
@@ -62,6 +64,11 @@ module Spree
62
64
  money == obj.money
63
65
  end
64
66
 
67
+ def use_default_currency
68
+ currency = Spree::Store.default.default_currency || Spree::Config[:currency]
69
+ ::Money.default_currency = currency
70
+ end
71
+
65
72
  private
66
73
 
67
74
  attr_reader :options
@@ -39,7 +39,7 @@ module Spree
39
39
  ]
40
40
 
41
41
  @@checkout_attributes = [
42
- :coupon_code, :email, :shipping_method_id, :special_instructions, :use_billing,
42
+ :coupon_code, :email, :shipping_method_id, :special_instructions, :use_billing,
43
43
  :user_id, :bill_address_id, :ship_address_id
44
44
  ]
45
45
 
@@ -97,7 +97,8 @@ module Spree
97
97
  ]
98
98
 
99
99
  @@store_attributes = [:name, :url, :seo_title, :code, :meta_keywords,
100
- :meta_description, :default_currency, :mail_from_address]
100
+ :meta_description, :default_currency, :mail_from_address,
101
+ :facebook, :twitter, :instagram]
101
102
 
102
103
  @@store_credit_attributes = %i[amount currency category_id memo]
103
104
 
@@ -32,51 +32,6 @@ module CapybaraExt
32
32
  end
33
33
  end
34
34
 
35
- def select2_search(value, options)
36
- options[:from] = select2_from_label(options[:from])
37
- targetted_select2_search(value, options)
38
- end
39
-
40
- def targetted_select2_search(value, options)
41
- select2_el = find(:css, options[:from])
42
- select2_el.click
43
- page.document.find('.select2-search input.select2-input,
44
- .select2-search-field input.select2-input.select2-focused').send_keys(value)
45
- select_select2_result(value)
46
- end
47
-
48
- def select2(value, options)
49
- options[:from] = select2_from_label(options[:from])
50
- targetted_select2(value, options)
51
- end
52
-
53
- def select2_from_label(from)
54
- label = find(:label, from, class: '!select2-offscreen')
55
- within label.first(:xpath, './/..') do
56
- "##{find('.select2-container')['id']}"
57
- end
58
- end
59
-
60
- def select2_no_label(value, options = {})
61
- raise "Must pass a hash containing 'from'" if !options.is_a?(Hash) || !options.key?(:from)
62
-
63
- placeholder = options[:from]
64
- click_link placeholder
65
-
66
- select_select2_result(value)
67
- end
68
-
69
- def targetted_select2(value, options)
70
- # find select2 element and click it
71
- find(options[:from]).find('a').click
72
- select_select2_result(value)
73
- end
74
-
75
- def select_select2_result(value)
76
- # results are in a div appended to the end of the document
77
- page.document.find('div.select2-result-label', match: :first, text: %r{#{Regexp.escape(value)}}i).click
78
- end
79
-
80
35
  # arg delay in seconds
81
36
  def wait_for_ajax(delay = Capybara.default_max_wait_time)
82
37
  Timeout.timeout(delay) do
@@ -108,13 +63,6 @@ rescue Selenium::WebDriver::Error::TimeOutError
108
63
  default_options[:error].nil? ? false : raise(default_options[:error])
109
64
  end
110
65
 
111
- # Usage examples:
112
- # fill_in_with_force 'CVC', with: 123
113
- def fill_in_with_force(locator, with:)
114
- field_id = find_field(locator)[:id]
115
- page.execute_script "document.getElementById('#{field_id}').value = '#{with}';"
116
- end
117
-
118
66
  Capybara.configure do |config|
119
67
  config.match = :smart
120
68
  config.ignore_hidden_elements = true
@@ -15,7 +15,7 @@ namespace :common do
15
15
  Rails.env = 'test'
16
16
 
17
17
  Spree::DummyGenerator.start ["--lib_name=#{ENV['LIB_NAME']}", '--quiet']
18
- Spree::InstallGenerator.start ["--lib_name=#{ENV['LIB_NAME']}", '--auto-accept', '--migrate=false', '--seed=false', '--sample=false', '--quiet', '--copy_views=false', "--user_class=#{args[:user_class]}"]
18
+ Spree::InstallGenerator.start ["--lib_name=#{ENV['LIB_NAME']}", '--auto-accept', '--migrate=false', '--seed=false', '--sample=false', '--quiet', '--copy_storefront=false', "--user_class=#{args[:user_class]}"]
19
19
 
20
20
  puts 'Setting up dummy database...'
21
21
  system("bundle exec rake db:drop db:create > #{File::NULL}")
@@ -5,5 +5,8 @@ FactoryBot.define do
5
5
  url { 'www.example.com' }
6
6
  mail_from_address { 'spree@example.org' }
7
7
  default_currency { 'USD' }
8
+ facebook { 'spreecommerce' }
9
+ twitter { 'spreecommerce' }
10
+ instagram { 'spreecommerce' }
8
11
  end
9
12
  end
@@ -1,7 +1,7 @@
1
1
  class OrderWalkthrough
2
2
  def self.up_to(state)
3
3
  # A default store must exist to provide store settings
4
- FactoryBot.create(:store) unless Spree::Store.exists?
4
+ store = Spree::Store.default || FactoryBot.create(:store, default: true)
5
5
 
6
6
  # A payment method must exist for an order to proceed through the Address state
7
7
  unless Spree::PaymentMethod.exists?
@@ -18,7 +18,7 @@ class OrderWalkthrough
18
18
  unless Spree::ShippingMethod.exists?
19
19
  FactoryBot.create(:shipping_method).tap do |sm|
20
20
  sm.calculator.preferred_amount = 10
21
- sm.calculator.preferred_currency = Spree::Config[:currency]
21
+ sm.calculator.preferred_currency = store.default_currency
22
22
  sm.calculator.save
23
23
  end
24
24
  end
@@ -53,7 +53,11 @@ class OrderWalkthrough
53
53
  end
54
54
 
55
55
  def self.payment(order)
56
- order.payments.create!(payment_method: Spree::PaymentMethod.first, amount: order.total)
56
+ FactoryBot.create :payment,
57
+ order: order,
58
+ payment_method: Spree::PaymentMethod.first,
59
+ amount: order.total
60
+
57
61
  # TODO: maybe look at some way of making this payment_state change automatic
58
62
  order.payment_state = 'paid'
59
63
  order.next!
data/spree_core.gemspec CHANGED
@@ -6,23 +6,17 @@ Gem::Specification.new do |s|
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.name = 'spree_core'
8
8
  s.version = Spree.version
9
- s.author = 'Sean Schofield'
10
- s.email = 'sean@spreecommerce.com'
11
9
  s.summary = 'The bare bones necessary for Spree.'
12
10
  s.description = 'The bare bones necessary for Spree.'
13
- s.homepage = 'http://spreecommerce.org'
14
- s.license = 'BSD-3-Clause'
15
-
16
- s.metadata = {
17
- "bug_tracker_uri" => "https://github.com/spree/spree/issues",
18
- "changelog_uri" => "https://github.com/spree/spree/releases/tag/v#{s.version}",
19
- "documentation_uri" => "https://guides.spreecommerce.org/",
20
- "source_code_uri" => "https://github.com/spree/spree/tree/v#{s.version}",
21
- }
22
11
 
23
12
  s.required_ruby_version = '>= 2.5.0'
24
13
  s.required_rubygems_version = '>= 1.8.23'
25
14
 
15
+ s.author = 'Sean Schofield'
16
+ s.email = 'sean@spreecommerce.com'
17
+ s.homepage = 'http://spreecommerce.org'
18
+ s.license = 'BSD-3-Clause'
19
+
26
20
  s.files = `git ls-files`.split("\n").reject { |f| f.match(/^spec/) && !f.match(/^spec\/fixtures/) }
27
21
  s.require_path = 'lib'
28
22
 
@@ -34,21 +28,21 @@ Gem::Specification.new do |s|
34
28
  s.add_dependency 'ffaker', '~> 2.9'
35
29
  s.add_dependency 'friendly_id', '>= 5.2.1', '< 5.4.0'
36
30
  s.add_dependency 'highline', '~> 2.0.0' # Necessary for the install generator
37
- s.add_dependency 'kaminari', '~> 1.2.1'
31
+ s.add_dependency 'kaminari', '>= 1.0.1', '< 1.2.0'
38
32
  s.add_dependency 'money', '~> 6.13'
39
33
  s.add_dependency 'monetize', '~> 1.9'
40
34
  s.add_dependency 'paranoia', '~> 2.4.2'
41
35
  s.add_dependency 'premailer-rails'
42
- s.add_dependency 'rails', '>= 5.2', '< 6.1'
36
+ s.add_dependency 'rails', '~> 6.0.0'
43
37
  s.add_dependency 'ransack', '~> 2.3.0'
44
38
  s.add_dependency 'responders'
45
39
  s.add_dependency 'state_machines-activerecord', '~> 0.6'
46
40
  s.add_dependency 'state_machines-activemodel', '~> 0.7'
47
41
  s.add_dependency 'stringex'
48
- s.add_dependency 'twitter_cldr', '~> 4.3'
42
+ s.add_dependency 'twitter_cldr', '>= 4.3', '< 6.0'
49
43
  s.add_dependency 'sprockets', '~> 3.7'
50
44
  s.add_dependency 'sprockets-rails'
51
- s.add_dependency 'mini_magick', '~> 4.9.4'
45
+ s.add_dependency 'mini_magick', '>= 4.9.4', '< 4.11.0'
52
46
  s.add_dependency 'image_processing', '~> 1.2'
53
47
 
54
48
  s.add_development_dependency 'email_spec', '~> 2.2'