0

Rails 4, Spree 2.1

The Issue:

Adding an item to cart with the Spree Flexi Variants engraving calculator, I get an error:

 undefined method `value' for nil:NilClass

Is this line in my engraving calculator model causing this error?

def compute(product_customization, variant=nil)
  return 0 unless valid_configuration? product_customization

  # expecting only one CustomizedProductOption
  opt = product_customization.customized_product_options.detect {|cpo| cpo.customizable_product_option.name == "inscription" } rescue ''
  opt.value.length * (preferred_price_per_letter || 0)
end

def valid_configuration?(product_customization)
  true
end

And as for the value method, any ideas on that?

I've tried defining value but nothing seems to work. I have another calculator called amount times contant. This is setup pretty much the same way; however, this one works. Getting kind of confused and way past my deadline.

Here is the github repo with the branch that I am using: https://github.com/jsqu99/spree_flexi_variants/tree/spree-2-1-wip

Trace:

NoMethodError (undefined method `value' for nil:NilClass)
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/calculator/engraving.rb:29:in `compute'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/product_customization.rb:11:in `price'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_contents_decorator.rb:32:in `block in add_to_line_item'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_contents_decorator.rb:32:in `map'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_contents_decorator.rb:32:in `add_to_line_item'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_contents_decorator.rb:7:in `add'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_populator_decorator.rb:36:in `attempt_cart_add'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_populator_decorator.rb:17:in `block in populate'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_populator_decorator.rb:16:in `each'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/models/spree/order_populator_decorator.rb:16:in `populate'
/Users/russellkompinski/Desktop/spree_commerce/spree_flexi_variants/app/controllers/spree/orders_controller_decorator.rb:18:in `populate'
nil
  • 2,238
  • 1
  • 19
  • 28
  • Your method `compute` returns `0` or `nil`. Are you sure that is what you want? – zwippie Dec 09 '13 at 18:14
  • no it's not. But this somehow works with the other calculator and still returns a value. – nil Dec 09 '13 at 18:17
  • If I delete the line and return without the condition, I receive "Spree::ProductCustomization can't be coerced into Fixnum" – nil Dec 09 '13 at 18:49
  • Oh I see, that was only part of the method. Can you show the rest of your `compute` method? – zwippie Dec 09 '13 at 19:02
  • @zwippie, just updated post with all compute method – nil Dec 09 '13 at 19:06

1 Answers1

2

The source code you pointed to on github contains a different definition of compute as follows:

enter image description here

which is consistent with your stack trace, since line 29 of engraving.rb involves an invocation of value. I'm not familiar with spree, but based on this code, the detect call is returning nil.

Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106
  • Thanks @Peter. But after update, still receiving the same error – nil Dec 09 '13 at 19:04
  • I didn't mean to suggest that updating would fix anything. :-) – Peter Alfvin Dec 09 '13 at 19:09
  • I was running something different on line 29, in which I didn't include the '|| 0' So I thought maybe without the 0, I was getting nil. So I tried adding the line that was different. – nil Dec 09 '13 at 19:09
  • Oh, ok. Well, anyway, the problem is with `opt` being `nil`, not with anything else going on in that line. Do you understand why it's being assigned `nil` in line 28? – Peter Alfvin Dec 09 '13 at 19:11
  • I don't understand why that is, exactly. It appears that way in the spree doc examples and other calculator examples, they all seem do it. I thought it had do with something regarding the 0 vs nil thing that I've come acrossed a few times. My mind can't comprehend nothing, maybe. Can you inform me? – nil Dec 09 '13 at 19:16
  • The other calculator here, the one that does work uses the same: https://github.com/jsqu99/spree_flexi_variants/blob/spree-2-1-wip/app/models/spree/calculator/amount_times_constant.rb – nil Dec 09 '13 at 19:28
  • And the spree docs seems to imply it here, when they use object=nil: http://guides.spreecommerce.com/developer/calculators.html – nil Dec 09 '13 at 19:28
  • I'm going to work on trying to hackup the amount_times_constant to behave the way I want it. Thanks for your time. I won't take anymore of it. – nil Dec 09 '13 at 19:39
  • I don't mind helping because I answer SO questions to force myself to learn about things I otherwise might not learn about. Anyway, I'm not suggesting there is anything wrong with that `compute` method. The example you pointed to is passing `nil` in. That's not what you're doing, though, right? – Peter Alfvin Dec 09 '13 at 19:47
  • It is basically. All I really am trying to achieve is to be able to calculate the fields to add up a total. So I wanted to have the calculators work the way they're intended to, only I was going to change the engraving from * val.length where it counts each letter and sums, to compute only the field as a whole.. The amount calculator is acting funky and I get different computations every other time. It's weird. So basically I was going to keep messing until it hopefully works – nil Dec 09 '13 at 20:08
  • I just came across google group from a post from Ryan Bigg. "If something goes wrong, an exception should be raised (and rescued) If the calculator is called and some criteria doesn't match, it should return 0 as it should not modify the order. If it returns nil, then Spree will attempt to add nil to a Float and that never ends well." – nil Dec 09 '13 at 20:18
  • The link to that is: https://groups.google.com/forum/#!msg/spree-user/AlVdkBeRk5k/BbPSQjmq9DcJ – nil Dec 09 '13 at 20:23
  • Ok, that's fine, but this `compute` method clearly expects there to be exactly one `inscription` option. Is that not ensured by your code? – Peter Alfvin Dec 09 '13 at 20:23
  • Ok, I see that `create_options` in the same `engraving.rb` file ensures that. So the question is why is the argument to `compute` not getting initialized and maintained properly. – Peter Alfvin Dec 09 '13 at 20:28
  • Well, i started trying to achieve this with the amount times constant calculator. Now I get no implicit conversion of BigDecimal into String when I try to edit the compute to opt.to_s + preferred_multiplier – nil Dec 09 '13 at 20:35
  • which I guess becomes a whole other issue – nil Dec 09 '13 at 20:36
  • You're losing me here. I have no idea how Spree customization/configuration works. What are you doing to enable use of the engraving calculator? In any event, I think you need to see what the value of `product_customization` is that is getting passed in to this `compute` method when it fails. For instance, you could add a line `puts product_customization.inspect if opt.nil?` right before the `opt.value ...` line. – Peter Alfvin Dec 09 '13 at 20:39
  • Well if i run that before the compute block i receive: The single-table inheritance mechanism failed to locate the subclass: 'Spree::Calculator::Engraving'. This error is raised because the column 'type' is reserved for storing the class in case of inheritance. – nil Dec 09 '13 at 20:59
  • I'm looking into that more now – nil Dec 09 '13 at 20:59
  • What do you mean by "before the compute block"? Did you place it where I suggested (i.e. right before the line that raised the error)? – Peter Alfvin Dec 09 '13 at 21:05
  • i did put it there, but it didn't change anything – nil Dec 09 '13 at 21:10
  • Did it not print out the value of `product_customization`? – Peter Alfvin Dec 09 '13 at 21:16
  • Sorry, but that just doesn't make sense. Why don't you go ahead and remove the `if obj.nil?` clause and just make it `puts "In compute, obj = #{obj.inspect}"` – Peter Alfvin Dec 09 '13 at 21:43
  • hey man thanks for all your insight. I just got done with what I was trying to achieve! =) – nil Dec 10 '13 at 14:49