Trying to Create Basic API with before_action method - ruby-on-rails

First time trying to create an API and am having some issues. I want to use the Host header in the post request to find the property that the lead is supposed to be routed to. However I get undefined local variable or method for my method that is supposed to pull the header out and find the correct property. Here is the controller:
class LeadsController < ApplicationController
before_action capture_header, only: :create
skip_before_action :verify_authenticity_token
def create
#property.leads.create!(lead_params)
end
private
def lead_params
params.permit(:firstname, :lastname, :email, :phone, :moveindate, :source)
end
def capture_header
referrer = request.headers["HTTP_REFERER"]
domain = URI.parse(referrer).host.match(/\w*.com$/)[0]
#property = Property.where(url: domain)
end
end
The error:
undefined local variable or method `capture_header' for
LeadsController:Class
Any insight would be greatly appreciated.

missing symbol for method "capture_header".
Please try: before_action :capture_header, only: :create

Related

Method not required for GET? If so, is it common not to write it?

I'm new to Rails, and I was thinking that a method should be defined for every single route.
However, /hello_world works as long as I write as below:
Rails.application.routes.draw do
get "/hello_world", to: "hello#world"
end
class HelloController < ApplicationController
# no world
end
# app/views/hello/world.html.erb
hello world!
Is it an expected behavior? If so, is it common not to write it?
You only need a controller action if you have any processing / data retrieval that you need to do before you display the view.
So, yes, the method itself isn't necessarily needed.
You might need to retrieve a record in a show action like this...
class CustomersController < ApplicationController
def show
#customer = Customer.find(params[:id])
end
end
but inn some cases, you might have a before_action that does whatever's neeeded for several methods, so you (again) don't need to specify the action method.
class CustomersController < ApplicationController
before_action :set_customer only: [:show, :edit, :update]
private
def set_customer
#customer = Customer.find(params[:id])
end
end
So this is a case where you might have needed to define a method for the action, but you've now made it unneccessary.

NoMethodError in Admin::DashboardController#index

am new to rails, and am using active admin for a work, and i get this error whenever i open active admin dashboard
NoMethodError in Admin::DashboardController#index
undefined method `asideSection' for #<Admin::DashboardController:0x00007fc544017d70>
here is my application_conrtoller.rb
class ApplicationController < ActionController::Base
before_action :asideSection
def hhome
end
def getAsideSection
#asideSections = Page.all
end
end
how can i fix it please.
before_action :asideSection tries to call a method named asideSection.
This method does not exist.
However, you have defined a method named: getAsideSection. I presume that this is what you want to be called.
So, you could either change that to: before_action :getAsideSection, or rename the method to asideSection.
Here is how I would write it, also following the ruby style guide convention of using snake_case for variables and method names:
class ApplicationController < ActionController::Base
before_action :get_aside_sections
def home
# ...
end
private
def get_aside_sections
#aside_sections = Page.all
end
end

ActionDispatch::Http::UploadedFile to array for Active Storage Rails 5.2

I am building Rails API. And using Postman to test the API. While uploading file through Postman I am not getting array of files in backend. In spite I am getting the type ActionDispatch::Http::UploadedFile. Because of that I am not getting my avatar in post_params. How to fix it.
Here is my controller class:
class Api::V1::PostsController < Api::V1::BaseController
skip_before_action :authenticate, only: [:create]
before_action :current_timeline, only: [:create]
def create
post = current_timeline.posts.build(post_params)
binding.pry
if post.save
render_success(:created, post, meta: {message: 'Post sucessfully added'})
else
render_error(421, post.errors)
end
end
private
def post_params
params.require(:post).permit(:message, :user_id, :occasion_id, :timeline_id, avatars: [])
end
def current_timeline
Timeline.find(post_params[:timeline_id])
end
end
In spite I am getting the type ActionDispatch::Http::UploadedFile
In postman, you need to change the field name to avatars[], then you can get avatars as array:
{"avatars"=>[#ActionDispatch::Http::UploadedFile....]}
You can send avatars[] param with/without index in brackets as per this answer

How to stop devise users from deleting other users posts?

I have a devise user ( that I call a Provider in my app) and I am trying to write a custom authentication method to prevent the Providers from deleting each other's posts (called Procedures in my app). Right now I have the correct_user method in my procedures controller.
def correct_user
#provider = #procedure.provider.find(params[:id])
redirect_to(provider_path(current_provider)) unless current_provider?(#provider)
end
I call it with the following before filter, also in my procedures controller:
before_filter :correct_user, :except => [:index, :show]
And I get the following error when trying to edit a procedure, even the provider's own procedure:
NoMethodError (undefined method `provider' for nil:NilClass)
app/controllers/procedures_controller.rb:8:in `correct_user'
Parameters: {"id"=>"523"}
From the looks of this error, the correct_user method is finding the procedure id instead of the provider id. How can I fix this? Thanks
Authentication is about making sure that the user is who he says is. Devise is an authorization library. The only access control it provides is that you can make actions off limits for unknown users.
Authorization is making rules about who gets to do what. Popular libraries include Pundit & CanCanCan.
Even without a lib you could write a simple authorization rule like this:
class Provider < ActiveRecord::Base
class NotAuthorized < StandardError; end
end
class ApplicationController < ActionController::Base
rescue_from Provider::NotAuthorized, with: :deny_access
private
def deny_access
render 'some_view', status: 403
end
end
class ProceduresController < ApplicationController
before_action :find_procedure, only: [:show, :edit, :update, :destroy]
before_action :authorize_resource!, except: [:new, :index, :show]
# DELETE /procedures/:id
def destroy
# This line never gets run if the user is not authorized.
#procedure.destroy
end
private
def find_procedure
#procedure = Procedure.find(params[:id])
end
def authorize_resource!
unless current_provider == #procedure.provider
raise Provider::NotAuthorized and return false
end
end
end
Notice that in the authorize_resource! method you compare the user id of the record that you are authorizing against the user id from the session.
If you used the id from the params you're leaving yourself wide open to a spoofing attack where a user pretends to be someone else by passing another user's id in the params.
However, I would not recommend that you write an authorization solution from scratch unless you really know what you are doing.
The error message tell you this:
Your variable #procedure is nil at the time that the method correct_user is called.

How to get the name of the action in an after_action filter for ActionMailer

In the class below, how do I get the current action name (i.e. email_confirmation, password_reset) in side the after_action callback add_mandril_headers?
class UserMailer < ActionMailer::Base
after_action :add_mandril_headers
def email_confirmation(user)
mail(..)
end
def password_reset(user)
mail(..)
end
private
# how to get the action name?
def add_mandrill_headers
headers['X-MC-Tags'] = [mailer_name, action_name].join('_');
end
end
Turns out action_name returns the current mailer action name. I tried it based on the fact that ActionController has a similar method.
Thanks #HarishShetty!
As you mentioned, the action_name is good for all Controllers, as it is inherited from ApplicationController.
For example, I was using public_activity and wanted some simplification in my controllers:
class SiteDetailsController < ApplicationController
after_action :track_activity, only: [:create, :update, :destroy]
# ...
private
def track_activity
#site_detail.create_activity action_name, owner: current_user
end
end

Resources