Rails error while trying to load a Service in a controller
Asked Answered
S

1

2

My controller is defined as follows with a create method.

class AtestController < BaseController
def create
    result = create_something(params)
    @connection = Bunny.new
    @connection.start
    @channel = @connection.create_channel
    bunny = RabbitPublisherService::RabbitPublisher.new(@channel,@connection) 
    render :json => trigger, :status => :created
  end
end

My Rabbit Publisher Service is defined as follows

module RabbitPublisherService
  class RabbitPublisher

    private
    attr_accessor :channel, :connection

    def initialize(channel, connection)
      puts "I reached here"
      @channel = channel
      @connection = connection
    end

    def publish(message)
      q    = @channel.queue("task_queue", :durable => true)
      q.publish(message, :persistent => true)
      puts "Message is Published..."
      sleep 1.0
      @connection.close
    end
  end
end

When I try calling this service from the controllers create method, RabbitPublisherService::RabbitPublisher.new, I get an uninitialized constant error saying :error_message=>"uninitialized constant AtestController::RabbitPublisherService"

Can someone please help me find out what I am doing wrong?

Seneschal answered 7/7, 2017 at 17:1 Comment(1)
Try adding include RabbitPublisherService to the controllerAlgae
B
3

Generally, this is probably a problem with where you've put your files and where Rails expect them. An in-depth guide can be found here: http://guides.rubyonrails.org/autoloading_and_reloading_constants.html.

To solve it, there are three options:

  • put the module and class where Rails autoloading expects them (IMO this is the preferred solution)
  • require the file where the class is defined
  • add the folder where the file containing the class is located to the autoload paths

1: You need to make sure that RabbitPublisherService and RabbitPublisher are in a location that Rails can autoload them, for instance app/services/rabbit_publisher_service.rb and app/services/rabbit_publisher_service/rabbit_publisher.rb.

2: Use require or (probably better) require_relative.

3: Alternatively you can explicitly add the path to the autoload/eager load paths.

In my opinion, you should stick with option 1 unless you have a very good reason not to. Using Rails' defaults keeps the code to a minimum and prevents surprises for fellow developers who expect Rails defaults. Number 2 is OK as well since it's explicit. I'd definitely avoid option 3 because it sooner or later always creates a mess when you put loads of files in unexpected locations and it makes it harder for other developers who are used to Rails defaults and expect them.

Brei answered 7/7, 2017 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.