Ruby get methods defined in codebase - ruby-on-rails

I'm trying to get a list of the methods defined in our Rails codebase, without including anything defined in superclass or dynamically defined at runtime. I've tried instance_methods(false), but a ton of methods are returned:
> User.instance_methods(false).length
=> 310
I'm guessing this is because Rails defines a bunch of methods at runtime. Is there any way to get a list of the methods only defined in the files in our app? Hoping there's a Ruby way and not just running a grep across all of the files. Bonus points for class methods as well...

User.instance_methods will show all the inherited methods as well, so you should run something like that
User.instance_methods - User.superclass.instance_methods
Be ware thought that it will show heaps of other methods that are generated by AR when you inherited the ActiveRecord::Base class

Use MyClass.instance_methods(false), but make sure to pass false as an argument if you don't want it to return the methods defined in the superclasses.
Additionally, use MyClass.singleton_methods(false) for class methods.
More info:
https://apidock.com/ruby/Object/singleton_methods
https://apidock.com/ruby/Module/instance_methods

Related

Inheritance services Ruby on Rails

So I'm learning RoR and I have to 3 services that calls an API with the same structure and i want to know if i can do it with a parent class and then work with the parent class to save code.
Thanks!
Yes. This may work if you can define a method with fewer arguments, which builds that structure for the API call.
Approaches are:
Put that common method in a base class which the other classes inherit from.
Put that common method in a module as a mix in.
Write a class to handle the call to the API, which builds the structure.
I don't think you have an "isa" relationship from the sound of it. So unless you do, 2 is preferred to 1. You can only inherit from one class, so mixins are more flexible.
Approach 3 is a good idea. You can have internal methods for the hostname and other constants for your API call.
This can be combined with the other approaches as you can use the Aggregation pattern to aggregate the API object in the other classes. That might or might not make sense. It might be just as well as the other classes have methods which instantiate the class in approach 3 and call it.

Rails/ActiveRecord .where method naming collision with Ruby Gem class method

I am working on a Ruby gem that will be a REST API wrapper.
What I would like to do is have a class that can be instantiated from the gem with a method similar to Rails/ActiveRecord 'where' method such that I can pass a SQL-like syntax in the method and have some JSON returned. Something like:
include 'my-gem'
test = MyGem::ClassExample.where('name like %test%')
# returns JSON object from REST API
My concern is if I were to include this gem into a Ruby on Rails application, would this 'where' method have a naming collision with ActiveRecord's 'where' or would the 'where' method be the one that I had defined in my class?
Basically, I think it should be okay, but I am scared of having to refactor a bunch of tests and rename a bunch of methods because of Rails magic/my ignorance.
By the way, I am not worried about sanitizing input, the REST API does not provide direct SQL/database access and it is a closed-source product. There is some configuration that needs to be done upfront that I have not included in this example, I just wanted to know if I could use this method name or if there were best practices/potential issues that I may be in conflict with.
Classes are namespaces.
If you define where on your own class and Rails defines where on another class you will not have a conflict. This is the case for both instance methods and class methods, which after all are just instance methods on the singleton class of the class.
However, if you were to define where on Object or another top-level class then you'll run into plenty of conflict because all classes are subclassing these classes.

Code shared by multiple controllers and models -- where is the best place to keep it?

So this is a newbie rails design question. Lets say I want some of my common functionality to be sitting in a set of helper classes (either as class methods or instance methods).
And I want to use these helper objects inside controller (not view) or even may be a model. can I do that? how? Does it have to be a module or class or can be anything?
Is there rails specific pattern for this?
If their are not tied to one of the three tiers, you should place them in the /lib directory.
The convention under /lib is that you should name your folders as modules, and files and classes, and that you should always try to encapsulate your additional behavior in modules. Let's say, you have some class
module MyModule
class MyHelperClass
end
end
You should put it into /lib/my_module/my_helper_class.rb

Helpers, methods and classes organization

When my project is growing up, I need to write some methods, but application_controller's private methods and helpers aren't provide enough space to store all extensions.
So I have looked at custom classes and methods, which are stored in the /lib folder.
But i still have some questions, which i can't solve:
-When should I use "class << self"? I have a class, to calculate difference between two arrays of numbers, and then return new array with a middle values of that numbers. I used to such code:
x = MyClass.new
x.calculate(array1, array2)
And then I have placed my class' methods into "class << self; end" to use class without initialization. Is it right solution?
-When should i use custom modules? Is it always need to 'include' or 'require' them? Please tell me about your modules in your projects, when do you use them?
-How can I call helper's method in the controller? I want to use in in ajax responce. For example I use helper method 'users_for_output', and if there was ajax call, my app should render only users as text, to process it with javascript after.
1) You don't have to instantiate the class to invoke a static method, i.e.
MyUtil.do_something
Vs.
MyUtil.new.do_something
In my project I keep such methods static.
2) You can use modules when want to share a set of functionality across classes. Read this mixin vs inheritance discussion. You will get a good idea about when to use modules.
2.1) The included method is intended for initializing the module variables. You don't need to use it if you don't have anything initialize.
3) If you want to expose a controller method as a helper method use the helper_method call in your ApplicationController class.
class ApplicationController < ActionController::Base
helper_method :user_for_output
end

call a helper from another view

I know that if I want to call a helper of another controller, I can do something like:
helper :other_controllers
But I was wondering why I can't do something like OtherControllersHelper.method inside the view?
Due to the way that Rails loads your modules, you cannot do this without modification.
Rails includes the associated helper models into the ActionView::Base instance used to render a template. ActionController::Helpers#helper (used in the example above) adds more helper modules to the list of those to be included. The helper methods that are used in views are written as instance methods. Modules in Ruby do not provide any good ways of getting at instance methods without using a constructor. Which is one of the big things that separates modules from classes.
To access your helpers from another controller with just OtherControllersHelper.method, you will need to redefine method as a class method. However, redefining those methods as class methods would make them inaccessible from your views.
You could duplicate all instance methods in your helpers as class methods, but that's definitely not a better solution that adding helper :other_controllers. There are ways to define wrappers pragmatically, but again, it's not the best way to handle the situation.
If you've got a lot of helpers that are likely to be used in multiple controllers/views maybe you're better off putting them somewhere else. Somewhere like app/helpers/application_helper.rb. Or another helper module that could be loaded only in the controllers that need it.

Resources