Home > Mobile >  Rails 7: I want to put code in /lib/ instead of writing a gem, but I'm getting NoMethodError
Rails 7: I want to put code in /lib/ instead of writing a gem, but I'm getting NoMethodError

Time:11-02

I added some code to the /lib/ directory in my rails app, which was not even recognised by rails probably due to loading, so I moved it to /app/lib/ then it was at least recognised, but not I get a NoMethodError when calling a method inside a module. Here is some of the code I placed in app/lib

# frozen_string_literal: true

module Github
  module Auth

    def connection
      Faraday.new(
        url: 'https://github.com'
      )
    end

    def authorize
      connection.get(
        '/login/oauth/authorize',
        params: {
          client_id: '<My client id here>',
          redirect_uri: '<My callback here>'
        }
      )
    end

  end
end

I then have an AuthorizeController class, from which I want to call this code;

class AuthorizeController < ApplicationController

  def index
    response = Github::Auth.authorize
    redirect_to response[:location] , allow_other_host: true
  end

end

For which I get the following error:

enter image description here

Like I said, I moved the code from /lib/ to /app/lib/ which made Rails at least recognise the code, but this feels hacky to me and probably isn't the best way to do this. I also don't want to write an entire gem just for this functionality

I previously had this code inside the controller, but I want it to be in lib. What is the best practice to achieve this?

Thank you from a Rails noob! :)

CodePudding user response:

The error has nothing to do with the file location - rather if you want to define a "module method" you need to define it with self:

module Github
  module Auth
    def self.connection
      Faraday.new(
        url: 'https://github.com'
      )
    end

    def self.authorize
      connection.get(
        '/login/oauth/authorize',
        params: {
          client_id: '<My client id here>',
          redirect_uri: '<My callback here>'
        }
      )
    end
  end
end

Instance methods of a module are only available within encapsulating objects - for example an instance of a class that includes the module.

You can also provide access to instance methods of a module from the singleton with the oddly named Module#module_function method:

module Github
  module Auth
    def connection
      Faraday.new(
        url: 'https://github.com'
      )
    end

    def authorize
      connection.get(
        '/login/oauth/authorize',
        params: {
          client_id: '<My client id here>',
          redirect_uri: '<My callback here>'
        }
      )
    end
    module_function :connection, :authorize
  end
end
  • Related