Call helper from RABL template - ruby-on-rails

I have a helper, controller and template like:
Helper:
# app/helpers/application_helper.rb
module ApplicationHelper
def current_user
#current_user ||= User.find_by(access_token: access_token)
end
private
def access_token
pattern = /^Bearer /
header = request.headers["Authorization"]
header.gsub(pattern, "") if header && header.match(pattern)
end
end
Controller:
# app/controllers/api/v1/companies_controller.rb
class Api::V1::CompaniesController < Api::V1::BaseController
before_action :set_company, only: [:show]
def show
render #company
end
private
def set_company
#company ||= Company.find(params[:id])
end
end
# app/controllers/api/v1/base_controller.rb
class Api::V1::BaseController < ApplicationController
respond_to :json
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include ApplicationHelper
protect_from_forgery with: :null_session
end
RABL-Rails template:
object :#company
attributes :id, :name, :description, :website
# --- How can I call a helper method here?
# if (#company.owner?(current_user) or current_user.kind_of?(Admin))
# attributes :contact
# end
attributes :created_at, :updated_at
When I call a helper method from RABL template, it will raise an error:
undefined local variable or method `current_user' for #<RablRails::Compiler:0x00000002494c68>
How can I call a helper method from RABL template?
Note: I used gem rabl-rails '~> 0.4.1'.

It seems your calling it the right way but the real problem is that your controller doesn't have inheritance from ApplicationController (unless there is more in Api::V1::BaseController that we can't see). So this means that your probably not getting ApplicationHelper included.
I would suggest you just add it to your controller
class Api::V1::CompaniesController < Api::V1::BaseController
include ApplicationHelper
...
end

Related

Refactoring the class component of submitted parameters

The following pattern is encountered:
params[:vehicle][:user_id]
params[:location][:user_id]
params[...etc...][:user_id]
what syntax allows the creation of a method that inputs the current class as the symbol within the param ? for example
class VehiclesController
def edit
v = Vehicle.where('user_id = ? AND user_id = ?', params[:vehicle][:user_id], current_user.id).first
end
class LocationsController
def edit
l = Location.where('user_id = ? AND user_id = ?', params[:location][:user_id], current_user.id).first
end
You can add a method to ApplicationController:
class ApplicationController < ActionController::Base
private
def form_params
params[controller_name.singularize]
end
end
and use it in other controllers:
class VehiclesController < ApplicationController
def create
form_params # => #<ActionController::Parameters {"user_id"=>"1"} permitted: false>
end
end
For permitted params, could be this:
class ApplicationController < ActionController::Base
private
def form_params
params.require(controller_name.singularize).permit(permitted_params)
end
def permitted_params
[] # nothing is permitted by default
end
end
class VehiclesController < ApplicationController
def create
form_params # => #<ActionController::Parameters {"user_id"=>"1"} permitted: true>
end
private
# Override `permitted_params`
def permitted_params
# FIXME: Seems `user_id` is not needed when you have `current_user.id`.
# Besides, it is bad to expose current `user_id` in the form,
# because I can start messing with it and start submitting
# different ids in your forms; like a payment form, make someone
# else pay for my charges.
[:user_id]
end
end

Rails api controller doesn't inherit method from the parent class

Doing API for my first Rails project.
I have base class ApiController for all the APIs:
module Api
class ApiController < ::ApplicationController
respond_to :json
skip_before_action :verify_authenticity_token
def index
#collection = resource_class.all
render json: #collection.as_json(as_json_collection)
end
private
def resource_class
raise NotImplementedError
end
def as_json_collection
{}
end
end
end
And I have child class UsersController:
module Api
class UsersController < ApiController
private
def resource_class
User
end
def resource_params
params.require(:user).permit(:name, :email)
end
end
end
My routes:
namespace :api do
resources :users
end
Then I'm going to my_app/api/users I have error:
The action 'index' could not be found for Api::UsersController
But then I changing UsersController writing it's own index class, everything works fine and I'm having all my Users in JSON format.
I've alrady tried to comment all private marks in both classes, but that doesn't help.
I don't want to write an API for every entity in my project and I'd like to avoid this problem in future.
I got it to work with this:
module Api
class ApiController < ::ApplicationController
def index
respond_to do |format|
format.json { render json: '"abc"' }
end
end
end
end
module Api
class UsersController < ApiController
end
end
The URL was http://localhost:3000/api/users.json
So for you I suggest:
module Api
class ApiController < ::ApplicationController
def index
respond_to do |format|
format.json do
#collection = resource_class.all
render json: #collection.as_json(as_json_collection)
end
end
end
end
end
module Api
class UsersController < ApiController
def resource_class
User
end
def resource_params
params.require(:user).permit(:name, :email)
end
end
end
Its supposed to be like this:
class Api::ApiController < ApplicationController
and do not forget to remove extra end, end of the file!
#sample
- api(folder)
-- api_controller.rb (Api::ApiController < ApplicationController)
-- users_controller.rb (Api::UsersController < Api::ApiController)
application_controller.rb
You need to read this my friend:
rails routes
When you do this:
namespace :api do
resources :users
end
rails creates CRUD routes automatically which means that my_app/api/users will translate to: .../users#index.
Do this to see your routes created by rails:
rails routes and for specific word (e.g. user): rails routes | grep user
Seeing is believing ;)

How to avoid :authenticity_token unpermitted params on create in Rails with Devise?

I'm using Devise in a Rails 6 app and running into an issue with :authenticity_token being an Unpermitted parameter. How do I create a new instance of Audit, allow the authenticity_token but not pass into create?
my AuditsController class:
class AuditsController < ApplicationController
before_action :audits_params
def show
#audit = Audit.last
end
def create
#audit = Audit.create(audits_params)
byebug
if #audit.save
redirect_to audits_show_path(#audit)
else
flash.now[:notice] = "Unable to create audit"
end
end
private
def audits_params
params.permit(:request_state, :time_modified, :request_license, :account, :customers_reason, :format)
end
end
and on my applicationController class:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
end
Also using rails_admin but not sure if that matters.

Circular dependency detected while autoloading constant SpushHelper

In my Rails app I've several controllers and each of them should send push notifications to mobile devices. To achieve this I use gem 'RPush' and everything was ok when I've had init RPush, send notifications, etc methods inside each controller. But now I decided to refactor the whole code and create module where all these methods will be stored. Suggested I must include my module in ApplicaitonController to make it's methods visible inside all cotrollers and I did it. Now I faced a problem Circular dependency detected while autoloading constant SpushHelper
My ApplicationController code:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :null_session
include SPushHelper
create_push_apps
end
UsersController code:
class UsersController < ApplicationController
before_action :authenticate_root!, only: [:index,:destroy]
before_action :set_user, only: [:destroy]
def index
#users = User.all
end
def destroy
#user.destroy
redirect_to users_url
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:push_token, :uuid, :device_type)
end
end
and my SPushHelper code:
module SPushHelper
ANDROID_KEY = "my_android_key_here"
def create_push_apps
#create android push app instance
create_android_push_app
...
end
def create_android_push_app
if not(defined? #android_app)
#android_app = Rpush::Gcm::App.find_by_name("android_app")
if #android_app.nil?
#android_app = Rpush::Gcm::App.new
#android_app.name = "android_app"
#android_app.auth_key = ANDROID_KEY
#android_app.connections = 1
#android_app.save!
end
end
end
def send_push_to_android(notification)
get_users_tokens
n_android = Rpush::Gcm::Notification.new
n_android.app = Rpush::Gcm::App.find_by_name("android_app")
n_android.registration_ids = #users_tokens
n_android.data = notification
n_android.save!
end
def get_users_tokens
if not(defined?(#users))
#users = User.all
else
if #users.nil?
#users = User.all
end
end
if not(defined?(#users_tokens))
#users_tokens = []
end
#users.each do |u|
#users_tokens << u.push_token
end
end
end
The error looks weird because I'm not using SPushHelper at all.
What am I doing wrong?

Rails: Do something once per page reload

How to invoke method once per page reload? defining before_filter in ApplicationController is failed because of multiple controllers used to perform action
When you say multiple controllers are used in one action, could you be more specific? Normally a before_filter in the controller responsible for the action would suffice.
If you want your before filter to affect specific methods in multiple controllers then place the method itself in the ApplicationController but the before_filter in each of the controllers that contain the action.
class ApplicationController
def foo
#bar = 'bar'
end
end
class UserController
before_filter :foo, :only => [:method1]
def method1
...
end
def method2
...
end
end
class StuffController
before_filter :foo, :only => [:method2]
def method1
...
end
def method2
...
end
end
class UnimportantController
# No before filter, neither of these methods will call :foo
def method1
...
end
def method2
...
end
end

Resources