Hello everyone ! I'm trying to update Solidus fro...
# support
j
Hello everyone ! I'm trying to update Solidus from
3.0.8
to
3.1.8
I followed the steps on the Changelog but I have some problems with the preferences. We have a class like this:
Copy code
module Spree
  module Calculator::CompanyAmount
    class FlatDefault < CompanyAmountCalculator
      preference :rate, :decimal, default: 25.0
      preference :fixed_amount, :decimal, default: 0.0

      preference :click_and_collect_rate, :decimal, default: -> { preferred_rate }
      preference :click_and_collect_fixed_amount, :decimal, default: -> { preferred_fixed_amount }

      preference :co_branding_rate, :decimal, default: -> { preferred_rate }
      preference :co_branding_fixed_amount, :decimal, default: -> { preferred_fixed_amount }
    end
  end
end
And when tryin to initialize it it can not access the
preffered_rate
(or
preferred_fixed_amount
)
Copy code
Failure/Error: preference :click_and_collect_rate, :decimal, default: -> { preferred_rate }
     
     NameError:
       undefined local variable or method `preferred_rate' for #<Class:0x000000012e280030>
       Did you mean?  preference_encryptor
Did I miss something or are preferences not utilized correctly ?
w
What does
Spree::Calculator::FlatDefault
ancestors return?
j
Here is the output:
Copy code
pry(main)> Spree::Calculator::CompanyAmount::FlatDefault.ancestors
[
  [  0] class Spree::Calculator::CompanyAmount::FlatDefault < Spree::CompanyAmountCalculator {
    :id => :integer,
    :type => :string,
    :calculable_id => :integer,
    :calculable_type => :string,
    :created_at => :datetime,
    :updated_at => :datetime,
    :preferences => :text
  },
  [  1] Spree::Calculator::CompanyAmount::FlatDefault::GeneratedAssociationMethods,
  [  2] Spree::Calculator::CompanyAmount::FlatDefault::GeneratedAttributeMethods,
  [  3] class Spree::CompanyAmountCalculator < Spree::Calculator {
    :id => :integer,
    :type => :string,
    :calculable_id => :integer,
    :calculable_type => :string,
    :created_at => :datetime,
    :updated_at => :datetime,
    :preferences => :text
  },
  [  4] Spree::CompanyAmountCalculator::GeneratedAssociationMethods,
  [  5] Spree::CompanyAmountCalculator::GeneratedAttributeMethods,
  [  6] class Spree::Calculator < Spree::Base {
    :id => :integer,
    :type => :string,
    :calculable_id => :integer,
    :calculable_type => :string,
    :created_at => :datetime,
    :updated_at => :datetime,
    :preferences => :text
  },
  [  7] Spree::Preferences::Preferable,
  [  8] Spree::Preferences::Persistable,
  [  9] Spree::Calculator::GeneratedAssociationMethods,
  [ 10] Spree::Calculator::GeneratedAttributeMethods,
  [ 11] ApplicationRecordDecorator,
  [ 12] Spree::Base(abstract) < ActiveRecord::Base,
  [ 13] Spree::RansackableAttributes,
  [ 14] Spree::Core::Permalinks,
  [ 15] Kaminari::ConfigurationMethods,
  [ 16] Kaminari::ActiveRecordModelExtension,
  [ 17] Spree::Base::GeneratedAssociationMethods,
  [ 18] Spree::Base::GeneratedAttributeMethods,
  [ 19] ActiveRecord::Base,
  [ 20] ActionText::Attribute,
  [ 21] ActiveStorage::Reflection::ActiveRecordExtensions,
  [ 22] ActiveStorage::Attached::Model,
  [ 23] Dragonfly::Model::InstanceMethods,
  [ 24] ValidatesTimeliness::ORM::ActiveRecord,
  [ 25] ValidatesTimeliness::AttributeMethods,
  [ 26] Paperclip::Schema,
  [ 27] Paperclip::Validators::HelperMethods,
  [ 28] Paperclip::Validators,
  [ 29] Paperclip::Callbacks::Running,
  [ 30] Paperclip::Callbacks,
  [ 31] Paperclip::Glue,
  [ 32] GlobalID::Identification,
  [ 33] Alchemy::Essence,
  [ 34] Ddb::Userstamp::Stampable::InstanceMethods,
  [ 35] Ddb::Userstamp::Stampable,
  [ 36] Ddb::Userstamp::Stamper,
  [ 37] PhonyRails::Extension,
  [ 38] Juixe::Acts::Commentable,
  [ 39] Kaminari::ActiveRecordExtension,
  [ 40] FriendlyId::UnfriendlyUtils,
  [ 41] CanCan::ModelAdditions,
  [ 42] ActiveRecord::Suppressor,
  [ 43] ActiveRecord::SignedId,
  [ 44] ActiveRecord::SecureToken,
  [ 45] ActiveRecord::Store,
  [ 46] ActiveRecord::Serialization,
  [ 47] ActiveModel::Serializers::JSON,
  [ 48] ActiveModel::Serialization,
  [ 49] ActiveRecord::Reflection,
  [ 50] ActiveRecord::NoTouching,
  [ 51] ActiveRecord::TouchLater,
  [ 52] ActiveRecord::Transactions,
  [ 53] ActiveRecord::NestedAttributes,
  [ 54] ActiveRecord::AutosaveAssociation,
  [ 55] ActiveModel::SecurePassword,
  [ 56] ActiveRecord::Associations,
  [ 57] ActiveRecord::Timestamp,
  [ 58] ActiveModel::Validations::Callbacks,
  [ 59] ActiveRecord::Callbacks,
  [ 60] ActiveRecord::AttributeMethods::Serialization,
  [ 61] ActiveRecord::AttributeMethods::Dirty,
  [ 62] ActiveModel::Dirty,
  [ 63] ActiveRecord::AttributeMethods::TimeZoneConversion,
  [ 64] ActiveRecord::AttributeMethods::PrimaryKey,
  [ 65] ActiveRecord::AttributeMethods::Query,
  [ 66] ActiveRecord::AttributeMethods::BeforeTypeCast,
  [ 67] ActiveRecord::AttributeMethods::Write,
  [ 68] ActiveRecord::AttributeMethods::Read,
  [ 69] ActiveRecord::Base::GeneratedAssociationMethods,
  [ 70] ActiveRecord::Base::GeneratedAttributeMethods,
  [ 71] ActiveRecord::AttributeMethods,
  [ 72] ActiveModel::AttributeMethods,
  [ 73] ActiveRecord::Locking::Pessimistic,
  [ 74] ActiveRecord::Locking::Optimistic,
  [ 75] ActiveRecord::Attributes,
  [ 76] ActiveRecord::CounterCache,
  [ 77] ActiveRecord::Validations,
  [ 78] ActiveModel::Validations::HelperMethods,
  [ 79] ActiveSupport::Callbacks,
  [ 80] ActiveModel::Validations,
  [ 81] ActiveRecord::Integration,
  [ 82] ActiveModel::Conversion,
  [ 83] ActiveRecord::AttributeAssignment,
  [ 84] ActiveModel::AttributeAssignment,
  [ 85] ActiveModel::ForbiddenAttributesProtection,
  [ 86] ActiveRecord::Sanitization,
  [ 87] ActiveRecord::Scoping::Named,
  [ 88] ActiveRecord::Scoping::Default,
  [ 89] ActiveRecord::Scoping,
  [ 90] ActiveRecord::Inheritance,
  [ 91] ActiveRecord::ModelSchema,
  [ 92] ActiveRecord::ReadonlyAttributes,
  [ 93] ActiveRecord::Persistence,
  [ 94] ActiveRecord::Core,
  [ 95] ActiveSupport::ForkTracker::CoreExtPrivate,
  [ 96] ActiveSupport::ForkTracker::CoreExt,
  [ 97] ActiveSupport::ToJsonWithActiveSupportEncoder,
  [ 98] Object < BasicObject,
  [ 99] PP::ObjectMixin,
  [100] FriendlyId::ObjectUtils,
  [101] ActiveSupport::Dependencies::Loadable,
  [102] ActiveSupport::Tryable,
  [103] JSON::Ext::Generator::GeneratorMethods::Object,
  [104] Kernel,
  [105] BasicObject
]
w
What do you get on initialization if you add:
Copy code
preference :click_and_collect_rate, :decimal, default: -> { abort self.inspect }
before the current
:click_and_collect_rate
preference?
j
If I place it before I get nothing... If I replace it I get:
Spree::Calculator::CompanyAmount::FlatDefault(id: integer, type: string, calculable_id: integer, calculable_type: string, created_at: datetime, updated_at: datetime, preferences: text)
w
Did that work on v3.0? Giving a proc is not meant to be executed at the instance level.
j
Yes it worked, the app is running in
v3.0.8
in production right now
w
j
In v3.1.0 I get the same:
Copy code
pry(main)> Spree::Calculator::CompanyAmount::FlatDefault.new()
#<Spree::Calculator::EpiceryAmount::FlatDefault id: nil, type: "Spree::Calculator::EpiceryAmount::FlatDefault", calculable_id: nil, calculable_type: nil, created_at: nil, updated_at: nil, preferences: {}>
But the error change if I do not put the
abort self.inspect
Copy code
Loading development environment (Rails 6.1.7)
[1] pry(main)> Spree::Calculator::CompanyAmount::FlatDefault.new()
(pry) output error: #<NoMethodError: undefined method `map' for true:TrueClass
Did you mean?  tap>
/Users/me/.rbenv/versions/2.7.6/lib/ruby/2.7.0/psych.rb:352:in `safe_load'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-6.1.7/lib/active_record/coders/yaml_column.rb:63:in `yaml_load'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-6.1.7/lib/active_record/coders/yaml_column.rb:26:in `load'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-6.1.7/lib/active_record/type/serialized.rb:22:in `deserialize'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activemodel-6.1.7/lib/active_model/type/helpers/mutable.rb:8:in `cast'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activemodel-6.1.7/lib/active_model/attribute.rb:175:in `type_cast'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activemodel-6.1.7/lib/active_model/attribute.rb:43:in `value'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activemodel-6.1.7/lib/active_model/attribute_set.rb:29:in `block in to_hash'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-6.1.7/lib/active_support/core_ext/enumerable.rb:81:in `block in index_with'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-6.1.7/lib/active_support/core_ext/enumerable.rb:81:in `each'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-6.1.7/lib/active_support/core_ext/enumerable.rb:81:in `index_with'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activemodel-6.1.7/lib/active_model/attribute_set.rb:29:in `to_hash'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-6.1.7/lib/active_record/attribute_methods.rb:265:in `attributes'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/awesome_print-1.9.2/lib/awesome_print/ext/active_record.rb:47:in `awesome_active_record_instance'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/awesome_print-1.9.2/lib/awesome_print/formatter.rb:26:in `format'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/awesome_print-1.9.2/lib/awesome_print/inspector.rb:118:in `unnested'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/awesome_print-1.9.2/lib/awesome_print/inspector.rb:77:in `awesome'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/awesome_print-1.9.2/lib/awesome_print/core_ext/kernel.rb:10:in `ai'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/awesome_print-1.9.2/lib/awesome_print/custom_defaults.rb:45:in `block in pry!'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:302:in `show_result'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:672:in `block in handle_line'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_class.rb:377:in `critical_section'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:671:in `handle_line'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:261:in `block (2 levels) in eval'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:260:in `catch'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:260:in `block in eval'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:259:in `catch'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_instance.rb:259:in `eval'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:77:in `block in repl'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:67:in `loop'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:67:in `repl'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:38:in `block in start'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/input_lock.rb:61:in `__with_ownership'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/input_lock.rb:78:in `with_ownership'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:38:in `start'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:15:in `start'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-byebug-3.10.1/lib/pry-byebug/pry_ext.rb:15:in `start_with_pry_byebug'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_class.rb:188:in `start'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/railties-6.1.7/lib/rails/commands/console/console_command.rb:70:in `start'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/railties-6.1.7/lib/rails/commands/console/console_command.rb:19:in `start'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/railties-6.1.7/lib/rails/commands/console/console_command.rb:102:in `perform'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/railties-6.1.7/lib/rails/command/base.rb:69:in `perform'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/railties-6.1.7/lib/rails/command.rb:48:in `invoke'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/railties-6.1.7/lib/rails/commands.rb:18:in `<main>'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/bootsnap-1.13.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/bootsnap-1.13.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
bin/rails:6:in `<main>'
w
I see. So, it doesn’t look to be working on v3.0 either. The context in the proc is the class itself, so you can’t access the
preferred_xxx
instance method.
j
In
v3.0.8
it works fine:
Copy code
Loading development environment (Rails 6.1.7)
[1] pry(main)> Spree::Calculator::CompanyAmount::FlatDefault.new()
Spree/Company Amount/Flat Default {
  :id => nil,
    :type => "Spree::Calculator::CompanyAmount::FlatDefault",
    :calculable_id => nil,
      :calculable_type => nil,
  :created_at => nil,
  :updated_at => nil,
  :preferences => {
    :rate => 25.0,
    :fixed_amount => 0.0,
    :click_and_collect_rate => 25.0,
    :click_and_collect_fixed_amount => 0.0,
    :co_branding_rate => 25.0,
    :co_branding_fixed_amount => 0.0
  }
}
The previous output was with
v3.1.0
w
Not sure I follow. Does
self
within the proc reference the class context both in v3.0 & v3.1?
j
No
v3.0.8
Copy code
pry(main)> Spree::Calculator::CompanyAmount::FlatDefault.new()
#<Spree::Calculator::CompanyAmount::FlatDefault id: nil, type: "Spree::Calculator::CompanyAmount::FlatDefault", calculable_id: nil, calculable_type: nil, created_at: nil, updated_at: nil, preferences: {}>
v3.1.8
Copy code
pry(main)> Spree::Calculator::CompanyAmount::FlatDefault.new()
Spree::Calculator::CompanyAmount::FlatDefault(id: integer, type: string, calculable_id: integer, calculable_type: string, created_at: datetime, updated_at: datetime, preferences: text)
w
Oh, I see
j
So, do you have any idea of how I could solve this ? 😅
w
No idea! 😢 I’ll try to do some debugging tomorrow.
I’ve confirmed this is a bug and created a bug report on Solidus: https://github.com/solidusio/solidus/issues/4720
As a workaround, could it work for you to define those preferences as instance methods?
There, you could access the generated
preferred_
methods