Rails 4 trouble using module in controller - ruby-on-rails

In my rails 4 app I'm having trouble extracting the twitter gem config from my controller to a module, getting
undefined method `include' for #<UsersController:0x007ff7d566df08>
Users_controller.rb
def show
include Twitconfig
...
end
controllers/concerns/Twitconfig.rb
require 'twitter'
module Twitconfig
#client = Twitter::REST::Client.new do |config|
...
end
end
I've tried moving the "include Twitconfig" to out of the new action like so
class UsersController < ApplicationController
include Twitconfig
but that just gave an undefined method error when calling #client.
This is my first time including a module in rails 4 and I've been trying for a while so any help would be really appreciated.

The problem is your module not the way you include it, you cannot write code outside a method.
Include will add instance method to a class, so you should try with :
require 'twitter'
module Twitconfig
def client
client = Twitter::REST::Client.new do |config|
...
end
end
end
And in your controller :
class UsersController < ApplicationController
include Twitconfig
def show
puts "#{client.inspect}
end
It should display your client

Related

Rails Grape API include module - Zeitwerk::NameError - expected file to define constant, but didn't:

I want to make a small code refactor and extract client external client from gem to a separate module (it's use to connect to the DatoCMS API via gem 'dato'). My standard class, which works well, look like:
app/services/receive_webhook/fetch_model_name.rb
module ReceiveWebhook
class FetchModelName
def initialize(model_id)
#model_id = model_id
end
def call
fetch_model(#model_id).dig('name')
end
private
def client
#client ||= Dato::Site::Client.new(Rails.application.credentials.datocms_api_token)
end
def fetch_model(model_id)
client.item_types.find(model_id)
end
end
end
I want to separate client method to a different module and include it in FetchModelName class (like in standard Rails app). To do so I use below code:
app/dato_cms_api/dato_client.rb
module DatoCmsApi
module DatoClient
def client
#client ||= Dato::Site::Client.new(Rails.application.credentials.datocms_api_token)
end
end
end
With updated FetchModelName class:
app/services/receive_webhook/fetch_model_name.rb
module ReceiveWebhook
class FetchModelName
include ::DatoClient
def initialize(model_id)
#model_id = model_id
end
def call
fetch_model(#model_id).dig('name')
end
private
def fetch_model(model_id)
client.item_types.find(model_id)
end
end
end
But I'm getting an error:
Zeitwerk::NameError - expected file app/dato_cms_api/dato_client.rb to define constant DatoClient, but didn't:
app/services/receive_webhook/fetch_model_name.rb:5:in `<class:FetchModelName>'
app/services/receive_webhook/fetch_model_name.rb:4:in `<module:ReceiveWebhook>'
app/services/receive_webhook/fetch_model_name.rb:3:in `<main>'
app/controllers/api/v1/webhooks/dato_cms/receive_webhook.rb:29:in `block in <class:ReceiveWebhook>'
Does Grape API not support include module practice?
Did you try to downgrade your autoloader to classic?
In your application.rb file, add this:
config.autoloader = :classic

uninitialized constant Admin::ModeratorsController::ModeratorInteractor

Hi i am working on a RoR project with ruby-2.3.0 and rails 4. I am trying to call a method of interactor from controller. My controller is inside the Admin directory as follows:
class Admin::ModeratorsController < Admin::ApplicationController
include Interactor
def index
ModeratorInteractor.find_abc(params)
end
end
My interactor is:-
# frozen_string_literal: true
class ModeratorInteractor
def self.find_abc(params)
User.all
end
end
When i run my code i got an error uninitialized constant Admin::ModeratorsController::ModeratorInteractor.
I also try to include the Interactor:-
include Interactor
Please help how to fix it.Thanks in advance.
You need to define ModeratorInteractor as module to include it in your controller:
module ModeratorInteractor
def self.find_abc(params)
User.all
end
end
Then you need to ensure that the module is loaded properly:
# in application.rb
config.autoload_paths += %W("#{config.root}/lib") # path to your module
Or you can also use require instead of autoload_paths:
require "#{Rails.root}/lib/modeator_interactor"
Then in your controller, you can include it:
include ModeratorInteractor
First, you need to include Interactor in your ModeratorInteractor, also you need to define a call method, not find_abc which will not work and it will throw and error of undefined method, so your final interactor will look like this
# frozen_string_literal: true
class ModeratorInteractor
include Interactor
def self.call
params = context.params
end
end
and you will call it as
ModeratorInteractor.call(params: params)
Voila.

ClassMethods in Controller Concern returning NoMethodError

I have created a concern in controllers/concerns called reports.rb
In it I created the ClassMethods module.. It looks like this
module Reports
extend ActiveSupport::Concern
included do
require 'peddler'
require 'csv'
end
module ClassMethods
def report_details(token, marketplace_id, merchant_id)
#...
end
I included this concern in my Merchants controller like this:
class MerchantsController < ApplicationController
include Reports
And then tried to call the report_details method in an action on the Merchants controller like so:
def pull_from_amazon
me = Merchant.find(params[:merchant_id])
marketplace = me.marketplace
token = me.token
Merchant.report_details(token, marketplace, params[:merchant_id])
redirect_to root_path
end
According to this post Rich on Rails I should be able to call:
Merchant.report_details(xx,xxx,xxxx)
But I get a NoMethodError when I try.. I also tried:
me.report_details(xx,xxx,xxxx)
And got the same NoMethodError
What did I do wrong?
Try this
MerchantController.report_details(xx,xxx,xxxx)
But you should better include this concern in model.

How to keep my gem self-contained without having to edit any core source Rails?

I want to add a filter to the ApplicationController but I want to do it within my gem.
What I want to avoid is the following:
class ApplicationController < ActionController::Base
include MyGem
end
I do not want that. I don't want to have to include my module in the source code.
I am having issues though.
Here is the relevant code:
lib/correlation_id/controller_extension
module CorrelationId
module ControllerExtension
def self.included(klass)
klass.class_eval do
after_filter :pass_correlation_id
end
end
def pass_correlation_id
correlation_id = request.headers['Correlation-ID'] || SecureRandom.uuid
headers['Correlation-ID'] = correlation_id
end
end
end
ApplicationController.send :include, CorrelationId::ControllerExtension
lib/correlation_id.rb
require 'correlation_id/controller_extension'
module CorrelationId
end
Now, when I'm in the test/dummy directory, which is a test rails app for my gem, I try to boot up the server using rails s and I get the following error:
/correlation_id/lib/correlation_id/controller_extension.rb:17:in `<top (required)>': uninitialized constant ApplicationController (NameError)
I'm clearly having problems with referencing ApplicationController to monkey-patch it.
How would I manage this? I want my gem to be self-contained.
The following code works. What I did was prematurely create ApplicationController with the appropriate inheritance. Note, many people use the rails-api gem, so I factored in them to ensure the fact that it would work.
Also, note: You must inherit from a class because otherwise ApplicationController will be a usual class that doesn't understand what after_filter is.
module CorrelationId
module ControllerExtension
def self.included(klass)
klass.class_eval do
after_filter :pass_correlation_id
end
end
def pass_correlation_id
correlation_id = request.headers['Correlation-ID'] || SecureRandom.uuid
headers['Correlation-ID'] = correlation_id
end
def self.base_controller_inheritance
if Gem::Specification.find_all_by_name('rails-api').any?
ActionController::API
else
ActionController::Base
end
end
end
end
class ApplicationController < CorrelationId::ControllerExtension.base_controller_inheritance
include CorrelationId::ControllerExtension
end
I imagine there might be a better way to check if they are using ActionController::API and if so, please do share, but as of now, this seems like the most solid way to do it.

Why is my model being recognized as a module?

I have a controller that calls a model method:
class WelcomeController < ApplicationController
item_num = params[:item_num] || "0001"
#product = Scraper.lookup_item(item_num)
end
Here is the Scraper model:
class Scraper < ActiveRecord::Base
require 'nokogiri'
require 'mechanize'
def self.lookup_item(item_num)
# code goes here
end
end
Why am I getting this error?
NoMethodError: undefined method 'lookup_item' for Scraper:Module
I have run into this error before. grep your project to see if module Scraper is defined anywhere. If it is, remove it, or change it to class instead of module.

Resources