I am referring to this blog for token based authentication. I am trying to access the jsonwebtoken.rb methods as specified in the above blog in my app/controllers/api/v1/registrations_controller.rb.
class Api::V1::RegistrationsController < Api::V1::BaseController
def create
auth_token = JsonWebToken.encode({user_id: user.id})
end
end
end
My jsonwebtoken.rb file is inside app/lib folder as specified in the blog mentioned above. I have no idea how to use the methods of jsonwebtoken.rb in my different controllers.
Also I have added config.autoload_paths << Rails.root.join('lib') to autoload the file in config/application.rb. Please help me. Somewhere, I am missing the concept.
I think the issue is in the file naming convention see your file name is jsonwebtoken.rb but the class is JsonWebToken so the file name will json_web_token.rb look at the console
2.3.4 :019 > "JsonWebToken".underscore
=> "json_web_token"
Rails UnderScore method.
Restart the server after made any changes.
Here is the very nice tutorial for RESTful JSON API With Rails 5, you can check this.
Related
The title is my question.
devise provide us many useful methods like current_user, authenticate_user!, and so on. I want to know why is it possible to use them without including any module like below.
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
Those method's definition is here
Somebody please help me!
The answer is devise included its helper methods into ActionController on behalf of you when Rails on_load
# devise/rails.rb
module Devise
class Engine < ::Rails::Engine
# ...
initializer "devise.url_helpers" do
Devise.include_helpers(Devise::Controllers)
end
# ...
end
# devise.rb
# ...
def self.include_helpers(scope)
ActiveSupport.on_load(:action_controller) do
include scope::Helpers if defined?(scope::Helpers)
include scope::UrlHelpers
end
ActiveSupport.on_load(:action_view) do
include scope::UrlHelpers
end
end
# ...
I saw many 3rd gems using on_load to include their methods (or themselves) into Rails core, maybe it's a typical way to do that (allows Rails to lazily load a lot of components and thus making the app boot faster). If you install some gems and you could use their methods on your model/controller/view then those gems did the same thing devise did above.
About those methods current_user, authenticate_user! ... they are dynamic methods devise will generate when it did include scope::Helpers into Rails (see code above and the link).
So one very good thing about rails is the fact that you get a lot of things for free out of the box. One of these things at the top level is autoloading.
So in the case of Devise. When you install Devise and run the generate command, you get a devise.rb file inside of your config/initializers/ folder. This file is always autoloaded by rails on server startup and reload. That's how all these methods are able to be use these devise methods without importing anything.
Read more at rails docs
I have to make a rails API only i.e. input is POST request and output will be an JSON response. I have to interact with mysql database with my own table names i.e. mysql tables are already created.
Below is the folder structure with "helpers" even though we are not using any "views". We are accessing the helper methods from our controllers. Please confirm if I am correct or not. Thanks in advance.
1) app/controllers/application_controller.rb
class ApplicationController < ActionController::API
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
2) app/controllers/feature_management_controller.rb
class FeatureManagementController < ApplicationController
def populate_bean
#json = OrionCountryList.new.sample_function
end
def send_response(bean)
helper = FeatureManagementHelper.new
if (bean.method.eql?"get_feature_list") && (!bean.app_key.blank?) && (bean.app_key!=nil) && (bean.app_key.casecmp("NULL")!=0)
logger.info bean.print_bean "Request for fetching featureList by app_key : " + bean.app_key.to_s + " And userID: " + bean.user_id.to_s
##json_response = helper.get_feature_list bean
else
logger.error "METHOD NOT FOUND. method during feature management :"+bean.method+" app_key :"+bean.app_key
##json_response = {:message => "API not avaliable"}
end
logger.info("Final json_response sent to app : "+##json_response.to_json)
render :json => ##json_response
end
end
3) app/helpers/application_helper.rb
class ApplicationHelper
APP_CONFIG = YAML.load(File.read(File.expand_path('../../../config/app_config.yml', __FILE__)))
end
4) app/helpers/feature/feature_management_helper.rb
class FeatureManagementHelper
def get_feature_list(bean)
response = Hash.new
response = {:success_code => "1"}
return response
end
end
Here we are using "class" key word inside the helpers. But on searching, it seems "module" key word is needed. But we couldn't find the way to access module methods of helpers inside controllers.
Any help is appreciated.Thanks!!!
UPDATE
#Ekkerhard, Thanks for the suggestion,
I have refrained from using helpers in the above way mentioned and instead used PORO for implementing my business logic as suggested by #spikermann using
this_link
Upon implementing the changes, my code structure looks something like this:
1) app/controllers/feature_management_controller/feature_management.rb
class FeatureManagementController
class FeatureManagement
def get_feature_list(bean)
response = Hash.new
response = {:success_code => "1"}
return response
end
end
end
Similarly for any controller "test_controller" I have a folder named "test_controller" at the location /app/controllers/
and I am keeping the business logic inside a test.rb file inside this "test_controller" folder.
2) We have all the controllers inside the /app/controllers
3) We have all the models inside the /app/models
4) We are reading the configuration file inside /config/application.rb
class Application < Rails::Application
config.autoload_paths += Dir["#{config.root}/lib/**/"]
APP_CONFIG = YAML.load(File.read(File.expand_path('app_config.yml', __FILE__)))
config.time_zone = "New Delhi"
config.active_record.default_timezone = :local
config.autoload_paths += Dir["#{config.root}/app/**/"]
end
Though if I read the config file from the feature_management.rb file things are working just fine i.e. adding this line to the feature_management.rb file :
/app/controllers/feature_management_controller/feature_management.rb
APP_CONFIG = YAML.load(File.read(File.expand_path('../../../../config/app_config.yml',
__FILE__)))
but upon trying to read the configuration from the application.rb file I am getting an error :
NameError (uninitialized constant FeatureManagementController::FeatureManagement::APP_CONFIG):
I was wondering whether this is the correct way to proceed and is there a better way to do it.
Appreciate your inputs..!!!
If you need, you can include the module inside your controller and access the methods. Like:
include HelperModuleName
Frankly, to me it seems that you are trying to just "get by" with Rails here and are using other paradigms in a Rails environment. I don't think you're going to be happy with that in the long (or even short) term; if you use Rails that way it will just get in your way.
First of all, I would not use helpers in this way, at all, ever. In my opinion, helpers are there solely for cutting out "stupid" code from view templates, to cut down on "programming" clutter inside otherwise HTML'ish/JSON'ish templates. And they are definitely never domain methods. They do domain-agnostic stuff like render form elements, complex tables or things like that.
Just because you are not outputting HTML but JSON does not mean you have to ditch the MVC paradigm completely, like you are doing. There are JSON templates, see In Rails, how do you render JSON using a view? .
You are using a helper to load configuration. Configuration lives in config/application.rb, config/environments/*.rb, config/initializers/*.rb etc. - see http://guides.rubyonrails.org/configuring.html . You should never need to load the YAML in a helper.
Your controller code suggests that you do not use routes.rb to structure your requests. Branching like you have in your controller is a big smell for me. See http://guides.rubyonrails.org/routing.html .
Maybe not the answers you are looking for, but that's my 2€. :)
I tried:
class MyMailer
def routes
Rails.application.routes.url_helpers
end
def my_mail
#my_route = routes.my_helper
... code omitted
end
Also inside mailer:
include Rails.application.routes.url_helpers
def my_mail
#my_route = my_helper
Also, the simple way, in mailer template:
= link_to 'asd', my_helper
But then when I try to start console I get:
undefined method `my_helper' for #<Module:0x007f9252e39b80> (NoMethodError)
Update
I am using the _url form of the helper, i.e. my_helper_url
For Rails 5, I included the url helpers into the my mailer file:
# mailers/invoice_mailer.rb
include Rails.application.routes.url_helpers
class InvoiceMailer < ApplicationMailer
def send_mail(invoice)
#invoice = invoice
mail(to: #invoice.client.email, subject: "Invoice Test")
end
end
Doing this broke my other routes.
# mailers/invoice_mailer.rb
include Rails.application.routes.url_helpers
Doing this is not the right way, this will break application as routes are reloading and routes will not be available is those are reloading
module SimpleBackend
extend ActiveSupport::Concern
Rails.application.reload_routes!
Right answer is to use *_url and not *_path methods in email templates as explained below in Rails docs.
https://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views
I ran into the same issue but with a Concern, i was unable to use any of the url helpers in my code even using directly Rails.application.routes.url_helpers.administrator_beverages_url i was getting this error:
undefined method `administrator_beverages_url' for #<Module:0x00000002167158> (NoMethodError)
even unable to use the rails console because of this error the only way i found to solve this was to use this code in my Concern
module SimpleBackend
extend ActiveSupport::Concern
Rails.application.reload_routes! #this did the trick
.....
The problem was Rails.application.routes.url_helpers was empty at the moment of the initialization. I don't know the performance implication of using this but for my case this is a small application and i can take the bullet.
In the mailer add
helper :my
or the helper you need
and it will load app/helpers/my_helper.rb & includes MyHelper
Enjoy
The rails route helpers are in Rails.application.routes.url_helpers. You should just be able to put
include Rails.application.routes.url_helpers at the top of your class, though I haven't tested this
I came across this issue while working with a newly added route that seemed to be unavailable in my Mailer. My problem was I needed to restart all the workers, so they would pick up the newly added route. Just leaving this footnote in here in case someone runs into the same issue, it can be tricky to solve if you don't know this is happening.
Please take a look at this blog which explains how you can make use of Rails.application.routes.url_helpers in the right manner.
http://hawkins.io/2012/03/generating_urls_whenever_and_wherever_you_want/
You need to use the my_helper_url
I am using a gem in my rails app, and there is a method that I would like to override. The gam is authlogic, and the specific method I was to override is find_by_smart_case_login_field(login).
I made a file in lib/modules with the following code:
# lib/modules/login.rb
module Authlogic
module ActsAsAuthentic
module Login
module Config
def find_by_smart_case_login_field(login)
login = login.downcase unless validates_uniqueness_of_login_field_options[:case_sensitive]
if login_field
where({ login_field.to_sym => login })
else
where({ email_field.to_sym => login })
end
end
end
end
end
end
But this didn't do anything. Does anyone know how to overwrite the above method?
Well, you are monkey patching a gem. Not bad, just don't abuse it:)
Two things you need to do before making your monkey patching works.
Add /lib to auto load path otherwise Rails don't know it.
In config/application.rb, find the autoload_path line, change it to
config.autoload_paths += %W(#{config.root}/extras #{config.root}/lib)
Require your custom module at app loading.
In config/initializers, add a custom file say application.rb, then add the following line
require 'modules/login.rb'
# Pay attention: No "lib/" before the file path
Now, profit!
As to module path, it doesn't matter as long as your module nesting is correct in the file.
I'm going out on a limb here, but my guess would be that you'd have to name the file something like
lib/authlogic/acts_as_authentic/login/config.rb
In other words, I believe the path has to map to the module structure.
I'm developing a web application in Rails 2.3.5.
I defined the module in lib/ folder as follows.
module TestModule
class Basic < ApplicationController
def show
p "module method"
end
end
end
and the load_paths are described in the environment.rb for this library as follows
Rails::Initializer.run do |config|
config.load_paths += %W[ #{RAILS_ROOT}/lib/test_module ]
end
but temporally, I want to override the above method without editing the lib method.
So, I put the override method in the "config/initializers/override_show.rb" as follows.
require_dependency "lib/test_module/basic.rb"
module TestModule
class Basic
def show
p "new method"
end
end
end
without "require_dependency", I get an error, because the original method located in lib/ folder wasn't loaded, so I put the "require_dependency" before overriding the TestModule.
In the above code, the new method works fine only once just after activating the server.
However, the new method is never called again, and the old method is called.
When I restart the rails server, the new method will be called just once.
Please give me some advice on how to override the method in the lib folder.
Thank you very much in advance.
Is it possible that you simply append the code in config/initializers/override_show.rb to lib/test_module/basic.rb ?