NoMethodError - Private method 'my_stats' called ... in rails console - ruby-on-rails

Rails Console has been working fine until now. Suddenly I cannot call methods, neither class methods nor instance methods. But the app works fine.
Rails console
Catalog.my_stats
NoMethodError (private method `my_stats' called for #<Catalog:0x0000560a3796c9a8>)
If I try a method that does not exist it says "undefined method" instead of "private method", so it is able to see that the method exists. However - the method is NOT defined as private, and it has been working fine before. Built in Catalog.all works fine. Running on Ubuntu.
Example code for catalog.rb
def self.my_stats
puts "Hello!"
end
Update
I have another function in catalog.rb called string_to_array. This function responds well. And I can change it to a class function, and it works without problem. But if I create new functions they don't respond... also other, older functions responds well. Weird.

Short answer
The file had one "end" too much
Long answer I discovered that one of the functions above the troublesome ones had one "end" too much. Thanks to VS Code's vertical stripes I could identify that this particular "end" closed the class definition. This is why the functions were considered private, even without the word "private", because Rails gladly allowed them to be defined outside of the class. So the syntax checker did not consider this as an error. I also tried to add a lot of "end" words in the middle of the file, and in the end of the file, but the syntax was considered valid, still. This also explains why the GUI still worked, but the console had trouble accessing indirect "private" functions... maybe someone has a better name for these.. but now I've but them all inside the class where I think they belong. Thanks for your inputs.
Footnote
The stats code was tested temporarily in a particular branch that matched a spesific customer. The customer pasted this code into the catalog.rb file himself as a quick addon feature, and it worked for both of us. I then wanted this same code to be part of a new branch / version that was already in progress. I must have pasted it wrong, so that I did not get a fully functional checked-in version at my side - until now. Thats some time ago. So the "worked before - not now" was a little more tricky this time.

Related

Trying to test my nested Rails 5 form (mintest)

The actual nested form itself works fine, but i'd like to be able to have a test covering it to make sure I don't screw it up later. I also have more nested forms planned so I'd really like to figure this out.
I'm getting this failing test in my ListControllerTest:
"ListItem.count" didn't change by 1.
Expected: 1
Actual: 0
With this code:
https://pastebin.com/BRdtZW2T
Note that the "List.count" bit does pass. Again, this does actually work exactly as it's supposed to. I can create lists with lists items no problem when I actually submit forms on my app.
Lists are created with form_for
ListItems are created with fields_for
Figured it out. First off, I removed 'list_item_attributes' from the params being posted in my test. It seemed redundant, and I wasn't sure why I added it in there until I removed it, and my tests raised a different error:
TypeError: no implicit conversion of Symbol into Integer
app/controllers/lists_controller.rb:15:in `[]'
No idea what this was about, but some google searches turned up this:
http://billpatrianakos.me/blog/2013/09/29/rails-tricky-error-no-implicit-conversion-from-symbol-to-integer/
Which as it turns out is exactly my problem. So I added some extra square [] brackets to my params:[:list][:list_item], and presto it worked. See the revised pastebin as well as the article because that probably wasn't clear:
https://pastebin.com/uxRjsctK

How to analyze quickly the code definition from a given code

Let's say I'm in a really huge project and am curious how this line works:
authorize! :read_pipeline_schedule, user_project
authorize! is supposed to be method name. Is it a private function in the class, or DSL provided from a parent block, or including, or declared in a gem? Or maybe none of them?
I was using grep to find internal code and Google for external code such as gems, however I guess it's useful if I can see the call stack of the method. puts caller is printing from the place where I am although it can not be used for analyzing the above case.
I'd like to know the best practice.
You can grep your code and installed gems and, if name is unique enough, you'll quickly locate its definition and associated usages. However, if a name is a common one, like call, then this approach is useless.
Ruby is a dynamic language and, as such, is a nightmare for static analysis. You may guess where this comes from, but you just can't know for sure.
The only way to know is runtime introspection. So, in your example, put a breakpoint right before that line
binding.pry
authorize! :read_pipeline_schedule, user_project
You'll drop out to pry shell. Now you can do
show-source authorize!
And see where exactly this method is defined.
The easiest way is to ask the method itself:
method_object = method(:authorize!)
method_object.owner
# => returns module in which the method resides
method_object.source_location
# => returns file name and line number of source code where the method is defined
Note that source_location may return nil for methods which have no Ruby source code, e.g. dynamically generated methods or methods implemented in the interpreter internals (C functions in YARV, Java methods in JRuby, etc.)
I like caller(0), caller_locations, and the ever-incredible show-source

Rails 5 override dom_id helper method

I have encountered a strange problem. We have a project, in which - for security reasons - we wanted to avoid displaying the id for most of the models. So, instead of having a dom id user_12, we wanted to use the serial (id="user_adsi94zurew"). First we gave it all manually (like in these two haml lines):
.user_line{id: "user_#{#user.serial}"}
= form_for #user, url: user_path(#user), id: {"edit_user_#{#user.serial}"}
It is just not nice, we didn't like it. Then I found the helper method dom_id, which I overrode in the application_helper the following way:
def dom_id(record, prefix = nil)
if record.respond_to?(:serial)
"#{dom_class(record, prefix)}_#{record.serial}"
else
super
end
end
It just worked fine for most of the situations, though I didn't have the time for a thorough testing, because - as our application grew larger - we needed to rewrite it. We changed to Rails 5.0.0.1 and started to sort our controllers in modules (folders). I copied the code to our new application_helper.rb, and I found it was not working (it returned the good old user_12). And then I found, it WAS working, and then again, it wasn't. And that was it: it was almost totally random, when or where it worked. I made some tests and found that, when not working, my code was not even run (so it was not that the condition evaluated to false), the method went straight into the original dom_id, as if mine hadn't existed at all!
Then I found some rules against my theory of random, but these were even stranger:
1.) In the file /app/views/company_manager/companies/edit.html.haml, as well as in the new.html.haml (same folder) it never works. My first thought was that it is due to the module CompanyManager.
2.) In the root (/app/views/landings/landing_page.html.haml) it worked. Then it didn't! But if I made any change in the helper method (adding a p 'here', or even an empty new line(!)), it worked again!
3.) In the partial /app/views/company_manager/regions/_region.html.haml (.region_line{id: dom_id(region)}) it didn't work, but in the ajax response update.js.erb (same folder) it did (at least occasionally). I had some tough ten minutes due to that, because I tried to update region line in the DOM with the following jQuery code: $('#<%= dom_id(#region) %>').replaceWith('<%= j(render #region) %>');, and since the dom_id returned region_6 first and region_hd5j8g6 second, jQuery couldn't find the line to update.
4.) Lastly, we use the old way to access helper methods from controllers (which means include ApplicationHelper in the ApplicationController). When the method returned company_31, I tried to reference it from the controller, and it raised a NoMethodError, whereas other helper methods from ApplicationHelper were still accessible.
Conclusion: it seems to me that as Rails merges the helper methods it is sometimes my method that overrides the original, and sometimes it is vice versa. If the server is already running, and I make some changes in my method, Rails seems to reload just application_helper.rb, so it is my method that is above the original (though it still has no effect on companies/edit or regions/_region)...
Any ideas? Other explanations? Something, I missed? Any hints?
(Note: With alternatives, thank you, I am well equipped. If there is no solution, I will rename my method to dom_id_serial and try to convince form_for to use it instead of dom_id, or anything. So I am interested in anything that overrides dom_id and works, or any reason why it does not, and nothing else.)
Thanks in advance!

how to solve NoMethodError efficiently (rails)?

I am new to rails and notice a very odd pattern. I thought some error messages in Django were obscenely cryptic, but building my second app in rails I notice my errors come up NoMethodError more than 90% of the time.
How do rails people tell the difference between all these errors with the same name?
What does NoMethodError mean at it's core? It seems like what you're calling in the template is misspelled, or you're accessing attributes that don't exist?
Where can this error happen? Is the only possible cause in the template/view (the html.erb file)? Or can a bad call in the controller and whatnot cause same error?
Also, what is the best debugger gem to alleviate these issues? Reading the full trace isn't too helpful for beginners at least for a while, I;d like a first hand account of what debugger someone uses instead of reading hype
Thank you kindly
NoMethodError means you are calling a method on an object, but that object doesn't provide such method.
This is a quite bad error in the sense that is reveals a poorly designed and tested application. It generally means your code is not behaving as you are expected.
The way to reduce such errors is:
Make sure that when you are writing the code you are taking care of the various edge cases that may happen, not just the correct path. In other words, you need to take care of validating what's going on and making sure that if something is not successful (e.g. the user is not supplying all the input requested) your application will handle the case gracefully.
Make sure you write automatic test cases that covers the behavior of each method in your codebase
Keep track of the errors. When an error occurs, write a test to reproduce the behavior, fix the code and check the test passes. That will reduce the risk of regression.
This is not a Rails specific error actually. I'll try to explain what's happening at its core.
Ruby is a language that functions through message passing. Objects communicate by sending messages to each other.
The message needs to be defined as a method on the object to respond to it. This can be directly defined on the object itself, the object's class, the object's class's parents/ancestors or through included modules.
class MyObject
def some_method
puts "Yay!"
end
end
> MyObject.new.some_method
Yay!
Objects can define method_missing to handle unexpected messages.
class MyObject
def method_missing(name, *args, &block)
puts name
end
end
> MyObject.new.some_undefined_method
some_undefined_method
Without the method_missing handler, the object will raise a NoMethodError
class MyObject
end
> MyObject.new.some_undefined_method
NoMethodError: undefined method 'some_undefined_method' for #<MyObject...>
So what does this look like in Rails?
$ rails generate model User name:string
Produces this
# models/user.rb
class User < ActiveRecord::Base
end
Which has the following methods implemented among others (by ActiveRecord)
def name
end
def name=(value)
end
When you do the following:
# create a new User object
> user = User.new
#<User ... >
# call the 'name=' method on the User object
> user.name = "name"
"name"
# call the 'name' method on the User object. Note that these are 2 different methods
> user.name
"name"
> user.some_undefined_method
NoMethodError: undefined method 'some_undefined_method' for #<User...>
You'll see the same results whether you're calling it in your console, your model, your controller or in the view as they're all running the same Ruby code.
ERB view templates are slightly different in that what you enter is only evaluated as Ruby code when it's between <% %> or <%= %>. Otherwise, it gets written out to the page as text.
How do rails people tell the difference between all these errors with
the same name?
We usually look at the stack trace that comes back with the response (in development mode) as well as looking in the logs. In a dev environment, I am running my server in a console where I can scroll through the request.
What does NoMethodError mean at it's core? It seems like what you're
calling in the template is misspelled, or you're accessing attributes
that don't exist?
Due to dynamic coupling nature of Ruby. When Ruby determines that an object doesn't have a method by the name of the one that was called. It looks for a method by the name of "method_missing" within that object. If it's not defined then the super one is called which has the default behaviour of raising an exception. Rails leverages this mechanism heavily in it's internal dispatching
Where can this error happen? Is the only possible cause in the
template/view (the html.erb file)? Or can a bad call in the controller
and whatnot cause same error?
This error can happen wherever you have Ruby code, It has nothing to do with rails
Also, what is the best debugger gem to alleviate these issues? Reading
the full trace isn't too helpful for beginners at least for a while,
I;d like a first hand account of what debugger someone uses instead of
reading hype
An Invaluable tool for debugging is the gem 'pry'. It has many useful plug-able tools that greatly simplify debugging

Navigating through source code efficiently in Ruby

I was trying to find the method being called when Item.where(dst: "video") is called (Item being a Mongoid model). Looking up in the source code, I see that criteria.rb is the place to go to. However, def where calls super. Then Origin::Selectable (included inside Origin::Queryable) defines it:
def where(criterion = nil)
criterion.is_a?(String) ? js_query(criterion) : expr_query(criterion)
end
Now, I would have to see where js_query and expr_query are, see what they do and so on.
It gets tough going through all this source code and modules, finding all the methods and then trying to figure out how it works.
Is there a better way to do this process to find out how things work?
You probably need to improve your editor experience. There are three remarkable abilities (besides many others like Eclipse/Aptana, NetBeans, etc):
RubyMine — not free, but probably the best one;
Atom Editor with RSense plugin — free (plugins are also available for SublimeText and TextMate2;
vim/emacs with [c|e]tags.
Depending on your choice you yield an ability to quickly navigate through your code with either Ctrl+Click or with your preferred keyboard shortcut.
Here on SO this question was asked an amount of times as well: https://stackoverflow.com/search?q=best+ruby+editor
Hope it helps.
If you know the class of the receiver (say A) and the method name (say foo), then you can do:
A.instance_method(:foo).source_location
That will give the file name and the line number in most cases. If it returns nil, then it is likely a C-defined method, which does not rely on other Ruby methods.
Another way is to use the pry gem or the method_source gem.

Resources