Tagged: rails Toggle Comment Threads | Keyboard Shortcuts

  • ThomasPowell 9:37 am on April 6, 2022 Permalink | Reply
    Tags: rails, ,   

    RSpec::Mocks::VerifyingMessageException does not implement method 

    Why am I trying to call RSpec::Mocks::VerifyingMessageException?

    The problem started with an attempt to create a stub like the following:

        new_net=allow(Net::SFTP).to receive(:start).and_return(double('sftp'))
        allow(new_net).to receive(:upload_file!).and_raise('Broken')
    

    Which resulted in the following failure

         Failure/Error: allow(new_net).to receive(:upload_file!).and_raise('Broken')
           #<RSpec::Mocks::VerifyingMessageExpectation Net::SFTP.start(any arguments)> does not implement: upload_file!
    

    It’s a pretty obscure error to look up because RSpec::Mocks::VerifyingMessageException is not a class you would normally explicitly interact with. So what happened?

    RSpec::Mocks::VerifyingMessageException is the class of an allow call

    new_net=allow(Net::SFTP).to receive(:start).and_return(double('sftp')) isn’t saving off the double, but the result of the allow call. While at a fresher point in the day, I would have noticed that, I was somehow expecting the double itself to be returned. However, usually when an object is returned, it’s part of the method chain, not an argument in a part of the chain.

    The proper setup would have been to save the double, set it as a return value, and stub a method on it:

            new_net=double('sftp')
            allow(Net::SFTP).to receive(:start).and_return(new_net)
            allow(new_net).to receive(:upload_file!).and_raise('Broken')
    

    (The above example is a bit contrived for illustration purposes and is also not necessarily the best approach for a given circumstance.)

    A related error when using and_wrap_original

    If you’re wrapping the original new of a class and then want to add stubs, you can use and_wrap_original, but beware a pitfall (again, contrived example):

            allow(String).to receive(:new).and_wrap_original do |m, *args|
              string = m.call(*args)
              allow(string).to receive(:downcase).and_return('downcase')
            end
    

    Which will generate an error like:

         1.2) Failure/Error: String.new('hi').downcase
    
              NoMethodError:
                undefined method `downcase' for #<RSpec::Mocks::VerifyingMessageExpectation:0x00007fede75f9380>
    

    Fortunately, this is a simple case of not having the subject object (that needs to be returns by the method) as the last thing evaluated in the block:

            allow(String).to receive(:new).and_wrap_original do |m, *args|
              string = m.call(*args)
              allow(string).to receive(:downcase).and_return('downcase')
              string
            end
    

    Conclusion

    I hope that you don’t back yourself into these corners with stubbing methods, but if you manage to get this error, I hope you either find this post or have remembered it for the future.

     
  • ThomasPowell 7:58 am on October 9, 2021 Permalink | Reply
    Tags: , , m1 mac, node-sass, rails   

    Error on an M1 Mac loading Rails: node-sass refusing to compile. 

    M1 Mac specific error

    In trying to transfer and restart development on a Rails 6.1.3 app and get it up-to-date, I got an error on an M1 Mac about node-sass not supporting my current environment (the M1 Mac’s ARM 64 architecture).

    ERROR in ./app/assets/stylesheets/application.scss (./node_modules/css-loader/dist/cjs.js??ref--6-1!./node_modules/postcss-loader/src??ref--6-2!./node_modules/sass-loader/dist/cjs.js??ref--6-3!./app/assets/stylesheets/application.scss)
    Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
    Error: Node Sass does not yet support your current environment: OS X Unsupported architecture (arm64) with Unsupported runtime (93)

    Just yarn install?

    Unsurprisingly, this didn’t work, but my first instinct was a yarn install: and a few errors presumably unique to the M1 Mac (or maybe Big Sur’s Xcode environment) showed up:

    ../src/libsass/src/ast.hpp:1616:14: note: use reference type 'const std::basic_string &' to prevent copying
    for (const auto denominator : denominators)
         ^~~~~~~~~~~~~~~~~~~~~~
    
    .
    .
    
    /Users/tpowell/.node-gyp/16.10.0/include/node/v8-internal.h:489:38: error: no template named 'remove_cv_t' in namespace 'std'; did you mean 'remove_cv'?
                !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
                                    ~~~~~^~~~~~~~~~~
    .
    .
    1 error generated.
    make: *** [Release/obj.target/binding/src/binding.o] Error 1
    gyp ERR! build error
    gyp ERR! stack Error: `make` failed with exit code: 2
    gyp ERR! stack     at ChildProcess.onExit (/Users/tpowell/projects/blog-post-debug/self-journal/node_modules/node-gyp/lib/build.js:262:23)
    gyp ERR! stack     at ChildProcess.emit (node:events:390:28)
    gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
    gyp ERR! System Darwin 20.6.0
    gyp ERR! command "/opt/homebrew/Cellar/node/16.10.0_1/bin/node" "/Users/tpowell/projects/blog-post-debug/self-journal/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
    gyp ERR! cwd /Users/tpowell/projects/blog-post-debug/self-journal/node_modules/node-sass
    gyp ERR! node -v v16.10.0
    gyp ERR! node-gyp -v v3.8.0
    gyp ERR! not ok
    Build failed with error code: 1

    Upgrade to node-sass compatible with the M1 Mac via @rails/webpacker

    The const auto denominator error led me to this StackOverflow answer. The last time I had downstream dependency issues, the cleanest resolution was upgrading the @rails/webpacker using outdated dependencies in package.json. The current version is 5.4.3:

    9c9
    <     "@rails/webpacker": "5.2.1",
    ---
    >     "@rails/webpacker": "5.4.3",
    

    After this a yarn install should work fine. (Your need to delete node_modules may vary). Now the assets are compiling and page rendering properly:

    M1 Mac now rendering Bootstrap
    I guess I’ve never been so happy to see Bootstrap-style buttons.
     
  • ThomasPowell 9:48 pm on August 25, 2021 Permalink | Reply
    Tags: , , group, rails,   

    Getting a Count of Occurrences of Items in a Ruby Array (and a Caveat for Rails) 

    I feel like I’m often wanting to count occurrences of items in an array (Rails has its own special case as well), and I’m always trying to do it the “long way.”

    I finally stumbled upon this answer on StackOverflow that details the version-by-version options:

    • Ruby 2.7+ use .tally directly on the array:
    irb(main):006:0> %i{a b c c d c e b a a a b d}.tally<br>=> {:a=>4, :b=>3, :c=>3, :d=>2, :e=>1}
    
    irb(main):011:0> %i{a b c c d c e b a a a b d}.group_by(&:itself).transform_values(&:count)
    => {:a=>4, :b=>3, :c=>3, :d=>2, :e=>1}
    
    irb(main):012:0> %i{a b c c d c e b a a a b d}.group_by(&:itself).map { |k,v| [k, v.length] }.to_h<br>=> {:a=>4, :b=>3, :c=>3, :d=>2, :e=>1}
    

    The Rails Exception

    It’s a pretty common temptation, especially once you start thinking in terms of the list of items you want to count, to try to use a pure Ruby solution for things. But what if your source is from the your database?

    The key here is the database. You probably don’t want to load all of the records from the database just to count them using the above methods, and SQL has a GROUP BY clause which is just called .group.

    irb(main):013:0> Entry.group(:user_id).count
    D, [2021-08-26T02:49:43.996743 #4] DEBUG -- :    (1.2ms)  SELECT COUNT(*) AS count_all, "entries"."user_id" AS entries_user_id FROM "entries" GROUP BY "entries"."user_id"
    => {1=>231, 4=>15, 2=>2}
    

    This output is tallying entries by what User (via user_id) entered them. More importantly, the SQL used did the counts within the database without retrieving any data contained into the application except what was counted. (This used to be a pun on the :what column in the entries table, but apparently we’re not there with proper rendering and cutting and pasting of emojis between apps and OSes and well, I enter emoji as part of my entries in this app.

    This original example in extreme wide screen glory
     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
%d bloggers like this: