i have a method that uses devises user_signed_in? and current_user helpers. given that this is needed for almost all controllers in the project... it seemed like a great candidate for becoming a rails concern. however, when I move the relevant code into a concern i get:
undefined method 'user_signed_in'?
I thought maybe adding include Devise::Controllers::Helpers would help... but that was to no avail.
I trimmed this down to an example that has the mentioned issue and in a controller you would need this:
include CheckIt
and in the controller concerns directory a check_it.rb that looks like this:
module CheckIt
extend ActiveSupport::Concern
include Devise::Controllers::Helpers
included do
before_action self.checkit
end
module ClassMethods
def checkit
puts "user_signed_in? #{user_signed_in?}"
end
end
end
and then, as soon as you access some aspect of that controller it will say undefined method 'user_signed_in?'
Related
I have a module ApplicationHelper in app/helpers/application_helper.rb
defined like this
module ApplicationHelper
def some_method(arg)
end
end
and i have my view file is here
app/views/v1/admin/messages/show.json.jbuilder
So i am trying to access the
some_method()
in view file but it doesn't reflect!
Is this due to namespacing? or what i am not able to understand.
It would be Great if someone explains the concept.
Thanks in advance!
it says undefined method error
what could be the reason?
You didn't include your controller code, but we'll assume it ultimately inherits from ActionController::API (as it should it if it is an API controller). If so, that is the root of it rather than namespacing, etc. Per the ActionController documentation:
An API Controller is different from a normal controller in the sense
that by default it doesn't include a number of features that are
usually required by browser access only: layouts and templates
rendering, flash, assets, and so on. This makes the entire controller
stack thinner, suitable for API applications. It doesn't mean you
won't have such features if you need them: they're all available for
you to include in your application, they're just not part of the
default API controller stack.
One of the side effects of the thinner API controller is that they don't automatically include helpers like a standard Rails controller. You can easily add that back in, though.
messages_controller.rb
class Api::V1::MessagesController < ActionController::API
include ActionController::Helpers
helper ApplicationHelper
def show
# whatever
end
end
app/helpers/application_helper.rb
module MessagesHelper
def some_method(arg)
# whatever
end
end
app/views/messages/show.json.jbuilder
json.bogus do
thing1: some_method('banana')
end
If you have lots of API controllers, you can of course stick it in a base controller class they all inherit from like so:
class Api::V1::ApiController < ActionController::API
include ActionController::Helpers
helper ApplicationHelper
end
In my rails app I have a method that will be used in different Views, Controllers and in different Workers as well so what is best place to define this method such that code would not be get repeated.
In lib directory you can create module and define a method over there so you can access that method anywhere.
Best place is Helper, define it in application_helper.rb
module ApplicationHelper
def printing
"Printing..."
end
end
and include it in ApplicationController
class ApplicationController < ActionController::Base
include ApplicationHelper
end
In Rails, how do you use a specific method from a module. For eg,
# ./app/controllers/my_controller.rb
class MyController < ApplicationController
include MyModule
def action
MyModule.a_method
end
private
def a_method
...
end
end
# ------------------------------------------------ #
# ./app/helpers/my_module.rb
module MyModule
def a_method
...
end
end
MyController includes MyModule. And in action ,I want to use MyModule.a_method (Please note I also have a private a_method in MyController and I don't want to use this.)
Things I've tried :
1) Defining the method in the module as self.
def self.a_method
end
2) Using the :: notation in controller (MyModule::a_method)
The error that I keep getting is
Undefined method:a_method for MyModule:module
For now, I've resorted to using a different name for the modules method. But I'd like to know how to namespace the function with either the Module:: or Module. notation
[UPDATE - 11/24/2014]
adding file structure in code, since Rails heavily relies on convention.
So I am not really sure what you are trying to accomplish with your module but a quick solution to get it working is below.
Move my_module.rb out of helpers and into lib/my_module.rb. The helpers directory is for methods that you use in your views. The convention is to utilize helpers that are namespaced after their respective controller or the application_helper.rb for global methods for your views. Not sure if that's what you are trying to accomplish with your module but wanted to throw that out there.
Create an initializer (you can all it whatever) in config/initializers/custom_modules.rb and add require 'my_module'
Update the a_method back to be self.a_method
You can now call MyModule.a_method in your app
Don't forget to restart your server for changes to lib/my_module.rb to take effect.
Also, a lot of people reference this post by Yehuda Katz as guidance on where to store code for your app. Thought it might be a helpful reference.
if you include MyModule into MyController, all the "instance methods" of the first will be mixed-in into the 2nd.
So if you only want to call MyModule.a_method, no need to include your module.
Then you'd want to require (or better autoload) your module before using it. To do so place it in controllers/concerns/my_module.rb, rails (4 at least) should autoload it, otherwise require its file in an intializer
# my_module.rb
module MyModule
def self.a_method
...
end
end
should work, but doing
# my_module.rb
module MyModule
extend self
def a_method
...
end
end
is more clean to me. You'd like to have a look to rails active support concern to understand the "rails way" on this topic.
I am trying to make an ActiveRecord call to get information for the application layout (the default application.html.haml layout). I know I am not supposed to put logic into the layout itself, but I am unsure of where to put it.
The line of code I need run in the layout is just a simple Model call:
Client.find_by(:id => current_user.client_id)
I would suggest throwing it in helpers/application_helper.rb. I've used this in the past for things such as title helpers and body class helpers.
# helpers/application_helper.rb
module ApplicationHelper
def body_class
[controller_name, action_name].join(' ')
end
end
# views/layouts/application.slim
body class=body_class
= yield
The ApplicationController isn't for such helpers. It's mainly as support for your controllers, not your views.
It's okay if you put it in ApplicationController. And you can put controller related code to controllers/concerns folder.
'concerns/concern.rb':
module Concern
def method
# Your code here
end
end
To use a module from concerns folder include it in the controller: include Concern
I am upgrading my Rails plugin to be an engine that works with the latest 3.0RC1 release and I'm having a bit of trouble figuring out the best (and most correct) way to extend ActionController. I've seen this post by DHH and this question here on SO, but my question is more about how to properly call code within the ActionController.
For instance, I need to call the following within my engine's controller:
class ApplicationController < ActionController::Base
helper :all
before_filter :require_one_user
after_filter :store_location
private
def require_one_user
# Code goes here
end
def store_location
# Code goes here
end
end
I know how to properly include my two private functions, but I can't find a way to get it to properly call helper, before_filter and after_filter.
I would greatly appreciate some links or a way to make this work. I have tried naming my controller something other than ApplicationController and having the real ApplicationController extend it, but that doesn't seem to work either. I'm really up for any solution that makes the life of the engine user as easy as possible. Ideally, they wouldn't have to extend my class, but they'd have all of the functionality built into their own ApplicationController.
You may also want to look into the initializers inside your engine subclass, so you don't have to include view helpers inside your controller class. And this will give you control over the load order of these modules.
Here is what I have been using:
module MyEngine
class Engine < Rails::Engine
initializer 'my_engine.helper' do |app|
ActionView::Base.send :include, MyEngineHelper
end
initializer 'my_engine.controller' do |app|
ActiveSupport.on_load(:action_controller) do
include MyEngineActionControllerExtension
end
end
end
end
Also, another option for the action controller extension is using a mixin module. This will let you use the before_filter, after_filter, etc..
module MyEngineActionControllerExtension
def self.included(base)
base.send(:include, InstanceMethods)
base.before_filter :my_method_1
base.after_filter :my_method_2
end
module InstanceMethods
#...........
end
end
One other thing... if you create the default rails directories at the top level of your gem, you don't have to worry about requiring the helpers or controllers. Your engine subclass has access to them. So I add my application controller and application helper extensions here:
/myengine/app/helpers/myengine_application_helper_extension.rb
/myengine/app/controllers/my_engine_action_controller_extension.rb
I like this setup because it looks similar to the application_controller and application_helper in your rails app. Again, this is just personal preference, but I try to keep anything that is directly rails related, such as controllers, helpers and models inside /my_engine/app and anything that is related to the plugin in general inside /my_engine/lib
Check out this tutorial by Jose Valim for more info on initializers:
https://gist.github.com/e139fa787aa882c0aa9c (engine_name is deprecated now, but most of this doc seems up-to-date)
So, I finally figured out the solution and I hope it helps someone else.
You need to create a file in your lib directory because you are actually going to extend the class. I did myplugin/lib/extensions/action_controller_base.rb.
Then, inside of your myplugin/lib/myplugin.rb file, do the following:
require 'extensions/action_controller_base.rb'
Inside of myplugin/lib/extensions/action_controller_base.rb put the following:
require 'action_controller' # Make sure ActionController::Base is defined
ActionController::Base.class_eval {
private
def my_method_1
# Code Goes Here
end
def my_method_2
# Code Goes Here
end
}
ActionController::Base.instance_eval {
helper_method :my_method_1, :my_method_2
before_filter :my_method_1
after_filter :my_method_2
}
If you need to have view helpers, create them in the myplugin/lib/helpers directory (or anything inside of lib, the name "helpers" doesn't matter) also and add the following to the bottom of myplugin/lib/extensions/action_controller_base.rb:
require 'helpers/helper_file_1'
require 'helpers/helper_file_2'
ActionView::Base.send :include, MyHelper1
ActionView::Base.send :include, MyHelper2