0

I'm creating a ruby gem with rails 6. This is my main ruby gem file:

#lib/ruby_gem_name.rb

require 'active_support'
require 'active_record'
require 'ruby_gem_name/version'
require 'ruby_gem_name/class_methods'

# frozen_string_literal: true

puts 'The gem was loaded'

module RubyGemName; end

This is lib/ruby_gem_name/class_methods.rb

module RubyGemName
  module ClassMethods
    def self.ruby_gem_name_class_method
      puts 'Hello'
    end
  end
  extend ClassMethods
end

i enter in irb console and i can see:

ruby-gem-name$ irb
2.7.1 :001 > require 'ruby-gem-name'
The gem was loaded
 => true 
2.7.1 :002 > RubyGemName::ClassMethods.ruby_gem_name_class_method
Hello
 => nil

Now....I've added my gem to the gemfile in my rails project:

gem 'ruby_gem_name', path: 'path_to_ruby_gem_name'

I can see the installed gem in Gemfile.lock:

PATH
  remote: 'path_to_ruby_gem_name'
  specs:
    ruby_gem_name (0.1.0)
      activerecord (~> 6)
      activesupport (~> 6)
      rails (~> 6)

GEM
  remote: https://rubygems.org/
  specs:
    actioncable (6.0.3.5)
      actionpack (= 6.0.3.5)

Now, i want to use this class method in models of my rails project: i have this code:

class Cart < ApplicationRecord
  extend RubyGemName::ClassMethods
end

and when i try to use this class method from my rails project console, i see:

shopping-cart$ bundle exec rails c
Running via Spring preloader in process 32494
Loading development environment (Rails 6.0.3.5)
2.7.1 :001 > Cart.ruby_gem_name_class_method
Traceback (most recent call last):
        1: from (irb):1
NoMethodError (undefined method `ruby_gem_name_class_method' for Cart (call 'Cart.connection' to establish a connection):Class)
1pct
  • 65
  • 1
  • 6
  • Does this answer your question? [Ruby: Use module method inside a class method](https://stackoverflow.com/questions/52225820/ruby-use-module-method-inside-a-class-method) – vmank Feb 28 '21 at 12:46
  • Noo, issue is not solved with extend. Same issue with extend instead of include. I'll update the code! Thanks – 1pct Feb 28 '21 at 13:45

2 Answers2

1

In order to use the method ruby_gem_name_class_method as a class method you need to use extend as eugen points out in their example. If you use extend then the Module's methods are already Class methods, therefore the self on your ruby_gem_name_class_method is redundant.

Your module's code should change to this:

module RubyGemName
  module ClassMethods
    def ruby_gem_name_class_method
      puts 'Hello'
    end
  end
end

The other approach is to use include which will make the Module's methods available on the instance of the Class and you can achieve this by modifying your Class:

class Cart < ApplicationRecord
  include RubyGemName::ClassMethods
end

and then instantiate the object and call the instance method:

Cart.new.ruby_gem_name_class_method

You can omit self on the Module's method as it refers to the newly created instance.

vmank
  • 773
  • 2
  • 7
  • 22
  • Same error with no `self.ruby_gem_name_class_method` thanks! – 1pct Feb 28 '21 at 15:14
  • @1pct Have you tried reloading the irb? Also did you try running this outside of the irb, for example to place it inside a controller and start the server? – vmank Feb 28 '21 at 15:42
  • vmank yes i have tried, as i said, irb console from ruby gem folder is working well, the problem is in rails console of the rails project, where this gem is installed. I've removed the gem and reinstalled and i went out of the console and reload! the console again and the issue persists. I think is a issue with the connection to the database or somhow gem is not imported properly. Why do you think is going to work in any controller file and is not going to work in an active_record model? thanks! – 1pct Mar 01 '21 at 10:00
  • @1pct It was a misunderstanding from my side, I didn't see the part where you tried executing the method through rails console. If you have a github repo post the link so I can take a look. – vmank Mar 01 '21 at 16:36
  • vman sorry for the delay. I don't have a github repo, you can set two folders. The first one is the folder gem, and the second one is a folder with a simple rails project with sqlite3. This rails project have a model Product and you can try to extend these class methods- I'm using rails 6.0.3 for the folder gem and rails project. Thank you! – 1pct Mar 04 '21 at 12:55
  • @1pct I would prefer to avoid this process of creating the project myself due to lack of time but also to avoid having different files/versions/structure. Please if it's possible, create a github repo or some other code sharing service so I can clone it. – vmank Mar 04 '21 at 14:15
0

You'll probably want to use extend instead of include, as in

class Cart < ApplicationRecord
  extend RubyGemName::ClassMethods
end

extend will add the methods from RubyGemName::ClassMethods, as opposed to include, which will add them as instance methods.

For a more detailed explanation of extend vs. include, see https://stackoverflow.com/a/5008349/163640

eugen
  • 8,916
  • 11
  • 57
  • 65
  • Issue is not solved with extend. Same issue with extend instead of include. I'll update the code! Thanks – 1pct Feb 28 '21 at 13:46