0

I'm struggling to find the best way to implement the following class in my Rails 4 application. I only need to use this class in one controller and it's very lengthy.

class Yelp
   ##
   # Performs query on Yelp Search or Business API
   ##
   def query(business, term = 'lunch', cuisine = 'restaurants', limit = restaurant_limit, location = get_city)
     # ..
   end

   ##
   # Extracts a list of cuisines formatted for the view
   # @param  array of restaurant objects
   # @return hash of cuisines
   ##
   def get_cuisines(restaurants)
      # ..
   end

   ##
   # Creates [non-ActiveRecord] model objects from an array of restaurant data
   # @param  array of hashes containing restaurant data
   # @return array of objects containing restaurant data
   ##
   def parse_restaurants(restaurants)
      # ..
   end

   ##
   # Creates Gmaps pins from restaurant objects
   # @param  array of restaurant objects to become pins
   # @return Gmaps pins
   ##
   def get_pins(restaurants)
      # ..
   end
end

I've looked into helper modules but I understand they are for view logic.

I'm hesitant to put this logic into my application_controller.rb because, like I said, I only use it in one of my controllers.

I've tried putting this class in the lib directory but had no success. I followed this SO post but I keep getting: undefined method 'my_method' for <MainController>.

Community
  • 1
  • 1
phpete
  • 318
  • 3
  • 12
  • Have you tried including the module in the controller? – dandlezzz Nov 13 '14 at 20:15
  • 1
    I'm not sure I understand what the issue is. Why are you trying to add it to the controller at all? You can use an instance of a class without mixing it in to anything. – Dave Newton Nov 13 '14 at 20:17
  • Don't make your controller fat, but instead, make its logic testable and consider using [services](http://brewhouse.io/blog/2014/04/30/gourmet-service-objects.html) – blelump Nov 13 '14 at 20:21
  • @DaveNewton how? My intention is to **use** rather than include this logic into my controller. – phpete Nov 13 '14 at 20:40
  • Instantiate an instance and use it, like any other class. – Dave Newton Nov 13 '14 at 22:42
  • So you're talking about a singleton @DaveNewton, right? Where would I put this class and how would I include it into a controller for use? – phpete Nov 14 '14 at 17:24
  • @phpete No, a singleton has only a single instance. The number of instances of this doesn't really matter in this case, unless there's more here than meets the eye. I'm talking about writing `yelp = Yelp.new` and using it. – Dave Newton Nov 14 '14 at 17:25

1 Answers1

1

Create a module with ActiveSupport::Concern in your app/controllers/concerns/ directory, let's call it yelp_searcher.rb:

module YelpSearcher
  extend ActiveSupport::Concern
  ##
  # Performs query on Yelp Search or Business API
  ##
  def query(business, term = 'lunch', cuisine = 'restaurants', limit = restaurant_limit, location = get_city)
    # ..
  end

  ##
  # Extracts a list of cuisines formatted for the view
  # @param  array of restaurant objects
  # @return hash of cuisines
  ##
  def get_cuisines(restaurants)
     # ..
  end

  ##
  # Creates [non-ActiveRecord] model objects from an array of restaurant data
  # @param  array of hashes containing restaurant data
  # @return array of objects containing restaurant data
  ##
  def parse_restaurants(restaurants)
     # ..
  end

  ##
  # Creates Gmaps pins from restaurant objects
  # @param  array of restaurant objects to become pins
  # @return Gmaps pins
  ##
  def get_pins(restaurants)
     # ..
  end
end

Use it in your ThatOneController:

class ThatOneController < ApplicationController
  include YelpSearcher
  # more code here..
end

More reading on the topic here.

Surya
  • 15,703
  • 3
  • 51
  • 74