calling render raises "Undefined method 'logger' for true class" - ruby-on-rails

I'm at a loss trying to figure out what is causing this issue. If I call any variation of render in my controller it raises the following:
NoMethodError: undefined method `logger' for true:TrueClass
from /Users/username/.rvm/gems/ruby-2.3.4/gems/activesupport-5.1.3/lib/active_support/configurable.rb:113:in `logger'
I checked active_support/configurable.rb:113 and I don't quite understand what it's comparing and raising for. I have other controllers that which both share the same base controller, that is not throwing this error when I render.
What am I not seeing here?
EDIT
Calling render from
class Device::V1::DeviceController < ApplicationController
def status
render json: { foo: 'bar' }, status: :ok
end
end
Below is my application controller
class ApplicationController < ActionController::API
include ActionController::HttpAuthentication::Token::ControllerMethods
before_action :authenticate!
private
def authenticate!
authenticate_or_request_with_http_token do |token, options|
token == SECRET[:api_key]
end
end
end
Rails 5.1.3
Ruby 2.3.4
UPDATE
I had a method in this controller called config. Apparently this is a reserved namespace that conflicted with ActiveSupport

I had a controller method named config. This is a reserved name.

Related

raising NotAuthorized exception in application controller

I am trying to raise an exception from application_controller file for any actions other than read
class ApplicationController < ActionController::API
before_action :authenticate_request
attr_reader :current_user
private
def authenticate_request
#current_user = AuthorizeApiRequest.call(request.headers).result
render json: { error: 'Not Authorized' }, status: 401 unless #current_user
end
def authorize!(action)
raise NotAuthorized if action != :read && !current_user.admin?
true
end
end
But when I am making a POST request, the exception itself is throwing error. The following is the error.
NameError (uninitialized constant ApplicationController::NotAuthorized):
How can I fix this without having to add any new modules?
In rails there is no in-built exception called NotAuthorized, so when you try to raise this, rails doesn't know what to do. You can do this in two ways:
You can raise directly using built-in exceptions or create your own. Ex:
raise ActionController::RoutingError.new('Not authorized')
# or
raise ActionController::BadRequest.new('Not authorized')
# or
raise ActionController::MethodNotAllowed.new('Not authorized')
I recommend creating an external module and including it here, it keeps you code clean.

Ruby/Rails: Why is render json: {hello: 'world'} hitting my database?

I have an action:
def test
_process_action_callbacks.map { |c| pp c.filter }
render json: {hello: 'world'}
end
That for some reason is calling my current_user function defined in my application controller.
At first I thought it was a before action that was calling my current_user function (hence _process_action_callbacks). But after stripping away all of my before actions the call remained. The only two before actions are part of rails:
:clean_temp_files
:set_turbolinks_location_header_from_session
I used caller to see where my method was getting called from. Here's the stacktrace (and method declaration):
def current_user
pp caller
# get the current user from the db.
end
As you can see, the current_user function is being called by the serialization_scope method in the serialization class. How do I prevent it from calling my current_user function?
Your tag indicates you are using active-model-serializers. By default current_user is the scope. To customize the scope, defined in the application-controller, you can do something like
class ApplicationController < ActionController::Base
serialization_scope :current_admin
end
The above example will change the scope from current_user (the default) to current_admin.
In your case, you probably just want to set the scope in your controller (I assume it is called SomeController ;) ) you can write
class SomeController < ApplicationController
serialization_scope nil
def test
render json: {hello: 'world'}
end
end
See for complete documentation: https://github.com/rails-api/active_model_serializers/tree/0-9-stable#customizing-scope

How to access a controller method from a jbuilder template

I call a method on controller A that renders a jbuilder template (a file called signed_in.json.jbuilder). Inside the template I want to call a method, friendsCount, that is in controller B. I'm getting an error when I try to access the controller B method inside the template. The error is:
NameError - undefined local variable or method `friendsCount' for #<#<Class:0x007f90a09994f8>:0x007f90a0998788>:
app/views/api/sessions/signed_in.json.jbuilder
I thought that adding helper_method: friendsCount to controller B should solve exactly the type of issue I want to solve: making a controller method available in views.
Actually, when I try to access a method from my ApplicationsController in my jbuilder template (controller C below), I have no issue.
Here is my code:
CONTROLLER A:
class Api::SessionsController < ApplicationController
def create
#user = User.find_by_credentials(session_params[:username], session_params[:password])
if #user.nil?
render json: ["couldn't find user"], status: 404
else
sign_in!(#user)
render :signed_in
end
end
private
def session_params
params.require(:session).permit(:username, :password)
end
end
JBUILDER TEMPLATE: signed_in.json.jbuilder
json.friendsSorted sortFriends
json.friends friendsCount
CONTROLLER B
class Api::FeedsourcesController < ApplicationController
helper_method :friendsCount
def friendsCount
friendsCountHash = {}
# ... populate friendsCountHash
render json: friendsCountHash
end
CONTROLLER C
class ApplicationController < ActionController::Base
helper_method :sortFriends
def sortFriends
#...
return sortedFriendsArray
end
end
I do not want to have the friendsCount method in the helpers folder because I also need to be able to have a direct controller route to this method for other purposes.
You need to have helper methods in the calling controller or its superclass.
In your case it's SessionsController and ApplicationController.
FeedsourcesController is not superclass for SessionsController, so view renderer do not know about any methods in it.

The ":nothing" option is deprecated and will be removed in Rails 5.1

This code in rails 5
class PagesController < ApplicationController
def action
render nothing: true
end
end
results in the following deprecation warning
DEPRECATION WARNING: :nothing` option is deprecated and will be removed in Rails 5.1. Use `head` method to respond with empty response body.
How do I fix this?
According to the rails source, this is done under the hood when passing nothing: true in rails 5.
if options.delete(:nothing)
ActiveSupport::Deprecation.warn("`:nothing` option is deprecated and will be removed in Rails 5.1. Use `head` method to respond with empty response body.")
options[:body] = nil
end
Just replacing nothing: true with body: nil should therefore solve the problem.
class PagesController < ApplicationController
def action
render body: nil
end
end
alternatively you can use head :ok
class PagesController < ApplicationController
def action
head :ok
end
end

Rails Engine creating a before_filter like method for all parent controllers

I'm attempting to build a Rails Gem somewhere between Devise and CanCan. Not nearly as complex as Devise, but having views and a controller.
I've created a method to be added to the top of any controller of the parent app that needs it almost exactly like Devise's before_action :authenticate_user! and CanCan's load_and_authorize_resource
I need the method to redirect_to a path in my mounted routes if the requirements are not met.
module MyEngine
module ControllerAdditions
extend ActiveSupport::Concern
module ClassMethods
def pin_verified
current_user ||= nil
#pinned = current_user.nil? ? nil : current_user
redirect_to setup_mobiles_path unless #pinned && #pinned.verified?
end
end
end
end
and in my spec/dummy/app/controllers/users_controller.rb
class UsersController < ApplicationController
pin_verified
def index
#users = User.all
end
end
pin_verified is getting called as it's supposed to but I get the following error:
undefined local variable or method `setup_mobiles_path' for UsersController:Class
Any thoughts on how I should be doing this?
==== edit ====
I altered this now to raise a custom exception, but now I need to rescue that exception some how and redirect to the needed path.
def pin_verified
current_user ||= nil
#pinned = current_user.nil? ? nil : current_user
unless #pinned && #pinned.verified?
raise ValidatedPinExpired
end
end
I tried adding this to the ApplicationController of my gem, but it doesn't seem to be hitting Controller at all.
module MyEngine
class ApplicationController < ActionController::Base
rescue_from Exception do |exception|
Rails.logger.info "==== exception: #{exception} ===="
redirect_to setup_mobiles_path
end
end
end

Resources