Redmine/Ruby/Rails - Use custom helper methods inside of another custom helper - ruby-on-rails

I don't know Ruby&Rails, but I would like to build a small custom Redmine plugin for my personal needs.
And I have faced with the problem which might look quite straightforward for Ruby experts.
I have two helpers (modules):
helper1
helper2
And I would like to use helper1.method1 inside of helper2.method3.
I have tried following to achieve this:
simply call method helper1.method1 inside helper2.method3, with thoughts that relations resolved automatically - didn't work;
require helper1 inside helper2 by require '../../relative/path'- didn't worked;
require helper1 inside helper2 by require '../../relative/path'- didn't worked;
included helper1 inside helper2- didn't worked
I have tried to find information how proper to call a method from one custom helper inside of another custom helper but didn't found any relevant results. The most of results were about how to call custom helper method inside view, controller, settings view.
So, could somebody explain to me how properly use methods from one custom helper inside of another one?
Best, regards.

For common functionality I would suggest to
create a module in the lib folder (e.g. lib/my_plugin/common_code.rb)
require it in the plugins init.rb:
ActionDispatch::Callbacks.to_prepare do
require 'my_plugin/common_code'
end
include it in each helper it is needed
include MyPlugin::CommonCode

Related

Ruby getting undefined Method error, and i am not sure if i fully understand how methods are working for my plugin

i am trying to create a plugin for Discourse, which is written in Ruby. As normal blank files my program is working perfect and without errors, but when i try to adapt my code into the plugin context i run into issues and i am not sure if i really understand how the whole idea with functions is meant to be.
I thought it would be smart to have more than just one file, to outsource functionality in different methods and require them in a kind of "main" file. For example getting tweets is one method in an extra file, sending tweets a different method in another file. In blank ruby code its working fine but when i try to integrate that into the plugin file structure i get the error
undefined method `my_method' for #<Plugin::Instance:0x00007f9004012fc0> (NoMethodError)
the files with the methods are in a lib directory and the "main" file which is called the plugin.rb is in the mainfolder
so i tried
require_relative 'lib/my_method'
and the other way
require_relative File.expand_path('../lib/my_method.rb', __FILE__)
but i still run into that error.
i have not defined any kind of classes or modules or something like that so the "method files" are literally starting with
def self.my_method
#my code here
end
Could that be the reason why i run into the error above? Why is it working as blank ruby code, but not when i try to run the plugin with rails s on my discourse instance?
I am still pretty new into ruby programming, so maybe my question seems a bit silly.
Here is the link which lead me threw the plugin creation:
https://meta.discourse.org/t/beginners-guide-to-creating-discourse-plugins-part-1/30515
Unfortunately, your understanding of methods is shallow. Basically, any method you declare in the global scope is added to the Object class as private method, so it is accessible everywhere in your objects cause they derive from Object class and in global scope because it is the scope of the Object class. If you declare method as self.method, you make it a method of main Object, because self refers to main, which is not the desired behaviour for you. To fix that issue, you should just remove self and write it like that:
def my_method
end
This way this method will be added to the Object class itself, not the main Object. There is a link on the article about methods in general. And another one on the toplevel scope behaviour. In this codepen you may observe the difference. Also, it may be useful for you to learn some Ruby before going on with your development. I suggest rubymonk. Another issue is your one-method files which is not the best practice for ruby code organization. Ruby is truly object-oriented language and if you need to have a bunch or even one general-purpose method, it is better to put it in a module or class to define its purpose and role in application, make it reusable and trackable, without global scope pollution.

How do I create global utility functions in rails

I need a place to stick global referentially transparent utility methods. These should be accessible from everywhere in rails (Models, Views, Controllers, and everywhere else). e.g.:
bool = GlobalUtilities.to_bool "false"
unicorn = GlobalUtilities.make_me_a "unicorn"
What's the best way to do this?
You could always stick these in /lib and require them. See bricker's answer -- you can require these modules to be loaded from your application.rb, which will make them accessible everywhere.
See: Rails lib directory
I would make a descriptively-named file for each behavior that your are hoping to achieve, and collect them in /lib (or, better yet, an engine). Then, mix your desired functionality into the class you hope to extend. For example, in the scenario you described, you could add a parse_boolean method directly to String. Pretty slick stuff.
/lib/add_parse_boolean_to_string.rb
class String
def parse_boolean
self == 'true' # or whatever...
end
end

Using restful path helper methods in a separate lib

In a certain module that I am using in my application, I would like to use the method alarm_path(alarm). How can I include this method in my current module?
I already tried to include ActionView::Helpers::UrlHelper, though, it still complain that this method does not exists.
Simply add this instead of your current include:
include Rails.application.routes.url_helpers

If I want to require a lib just once, should it be in application_controller?

If I want to require a lib just once, so I can use it everywhere, should I do this in app_controller.rb?
Put it in a custom initializer because you might need this library outside a controller scope.
I think the application_controller.rb is a reasonable place to put the require statement.
Now, using rails 3, either you place the gem inside your Gemfile, which will automatically require it. If it is a file under the lib-folder, it normally is required automatically. Both these would cover most cases automatically imho.
If you still want to require something explicitly, I would not use the initializers, but I would recommend adding the require-line to your application.rb.
Hope this helps.

How do I invoke a method from a custom module?

I've created a module in the /lib folder:
Module CookieHelper
$str = cookies["shoppingcart"]
def get_all_cookie_info()
end
end
But this isn't working. If I move the code into a controller it works fine.
Also, I'm trying to invoke the method within this module. I've tried:
require CookieHelper
CookieHelper::get_all_cookie_info()
to use methods from a module inside of an other class (such as a controller), you do something like this:
include CookieHelper
Once you do that inside of your controller's class, you can call get_all_cookie_info() with just the method name.
It sounds like you might be trying to something odd, so if you want to spell out what get_all_cookie_info is supposed to do, then maybe I can offer more advice.
CookieHelper::get_all_cookie_info is the correct way to call this method.
include CookieHelper
get_all_cookie_info
is another valid way, if you want include all of the methods in cookie helper available without having to namespace them (once the file lib/cookie_helper has been loaded).
What the issue probably is, is that the lib file isn't even required yet, this is because rails3 doesn't automatically load files in lib anymore. You can tell it to do so by editing your application.rb file, and setting inside class Application < Rails::Application
config.autoload_paths += %W( #{config.root}/lib )

Resources