1

I'm trying to create a very simple "compute" method, but when loading the page with params "?op1=20&op2=30&operation=plus", I get this error:

NoMethodError in CalcController#compute

undefined method `empty?' for 50.0:Float.

My method:

def compute
        operation = params['operation']
        op1=params['op1']
        op2=params['op2']
        if operation==nil or op1==nil or op2==nil
            render plain: 'Error:invalid params...'
            return
        end
        if operation=='plus'
            render plain: op1.to_f+op2.to_f
            return
        end
end

The extracted source:

body.each do |part|
    parts << part
    (digest ||= Digest::SHA256.new) << part unless part.empty?
end

[digest && digest.hexdigest.byteslice(0, 32), parts]

The complete error stack:

rack (2.0.7) lib/rack/etag.rb:68:in `block in digest_body'
actionpack (5.1.7) lib/action_dispatch/http/response.rb:145:in `each'
actionpack (5.1.7) lib/action_dispatch/http/response.rb:145:in `each_chunk'
actionpack (5.1.7) lib/action_dispatch/http/response.rb:126:in `each'
actionpack (5.1.7) lib/action_dispatch/http/response.rb:74:in `each'
actionpack (5.1.7) lib/action_dispatch/http/response.rb:473:in `each'
rack (2.0.7) lib/rack/etag.rb:66:in `digest_body'
rack (2.0.7) lib/rack/etag.rb:29:in `call'
rack (2.0.7) lib/rack/conditional_get.rb:25:in `call'
rack (2.0.7) lib/rack/head.rb:12:in `call'
activerecord (5.1.7) lib/active_record/migration.rb:556:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/callbacks.rb:26:in `block in call'
activesupport (5.1.7) lib/active_support/callbacks.rb:97:in `run_callbacks'
actionpack (5.1.7) lib/action_dispatch/middleware/callbacks.rb:24:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/debug_exceptions.rb:59:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.1.7) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.1.7) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.1.7) lib/active_support/tagged_logging.rb:69:in `block in tagged'
activesupport (5.1.7) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.1.7) lib/active_support/tagged_logging.rb:69:in `tagged'
railties (5.1.7) lib/rails/rack/logger.rb:24:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/request_id.rb:25:in `call'
rack (2.0.7) lib/rack/runtime.rb:22:in `call'
activesupport (5.1.7) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.1.7) lib/action_dispatch/middleware/static.rb:125:in `call'
rack (2.0.7) lib/rack/sendfile.rb:111:in `call'
railties (5.1.7) lib/rails/engine.rb:522:in `call'
puma (3.12.1) lib/puma/configuration.rb:227:in `call'
puma (3.12.1) lib/puma/server.rb:660:in `handle_request'
puma (3.12.1) lib/puma/server.rb:474:in `process_client'
puma (3.12.1) lib/puma/server.rb:334:in `block in run'
puma (3.12.1) lib/puma/thread_pool.rb:135:in `block in spawn_thread'
Desaiz
  • 13
  • 6

1 Answers1

2

The error occurs because you're trying to check if a Float object is empty?. empty? is a method defined for objects of the enumerable type(Arrays, hashes etc.). To check if an object contains some value or not, you could use .blank?. In your code, (digest ||= Digest::SHA256.new) << part unless part.empty? this line, could be changed to (digest ||= Digest::SHA256.new) << part unless part.blank?

Rails provides a few very similar methods, which are briefly described below:

empty?: Is a method defined for enumerable objects (Arrays, hashes etc.)
blank?: This is defined for objects which are initialized with an empty value or are null. So "".blank? will return true, as well as nil.blank? .nil?: This is a method to specifically check if the value of a variable is nil. "".nil? will return false, but nil.nil? will return true.

For more details, you could check out this blog

UPDATE:
As mentioned in the update in the question, this error seems to occur at a Rack level, and not in the main source code. The reason for that is that the Rack middleware expects to handle strings, and not other types of objects.
In the compute action, we render a float object in the line render plain: op1.to_f+op2.to_f. This causes Rack to raise an error since it expects to receive only strings for rendering. This could be resolved by typecasting the matter to be rendered to a string as follows:
render plain: (op1.to_f+op2.to_f).to_s Kudos to @Emil Kampp for this answer that helped in debugging.

Anuj Khandelwal
  • 1,214
  • 1
  • 8
  • 16
  • Sorry, I didn't clarify that that "extracted source" is not inside my code. – Desaiz Apr 05 '19 at 10:27
  • Where exactly does it reside and how is it getting invoked? Is it a part of some gem that you're using? – Anuj Khandelwal Apr 05 '19 at 10:30
  • I'm not really sure... I added the error stack if it can help. – Desaiz Apr 05 '19 at 10:41
  • It seems to occur because the `lib/rack/etag.rb` file receives the float directly instead of a string, that it expects. – Anuj Khandelwal Apr 05 '19 at 10:54
  • 1
    Actually, I just read this answer which seems to have cleared up the issue: https://stackoverflow.com/a/40883029/5362761 Basically, when we render, we need to render a string, not an object. Changing `render plain: op1.to_f+op2.to_f` to `render plain: (op1.to_f+op2.to_f).to_s` should solve it. I'll update the answer as well if that works. – Anuj Khandelwal Apr 05 '19 at 10:55
  • Perfectly working now, thanks for the help! – Desaiz Apr 05 '19 at 11:32