Rails, change URL for a POST action within a controller - ruby-on-rails

I want the URL to be changed when a call to an action within the controller is made. My current scenario:
Controller:
class EventController < ApplicationController
def index
if city.blank?
failure
end
...
end
def failure
...
render 'failure'
end
end
Routes:
get '/event', to: 'event#index'
post '/event/failure' => 'event#failure'
But this code keeps the url as /events. The desired result is /events/failure
I've views for payment 'index' and 'failure'. I'm using rails ~ 5.0.0.

For the URL to change you will want to do a redirect, something like this :
class EventController < ApplicationController
def index
if city.blank?
redirect_to action: 'failure'
end
...
end
def failure
...
render 'failure'
end
end
But, redirection is not possible for POST requests as given in HTTP/1.1
You might want to consider changing your strategy.

Related

Rescue clause launched multiple times the same action

The following action
def send(server=1)
#messagelog = Messagelog.new(server_id: params[:server], struttura_id: params[:struttura], user_id: params[:user], chat_id: params[:chat], methodtype_id: params[:methodtype], payload: params[:payload])
#messagelog.save
bot = Telegram.bot
case params[:methodtype]
when 1
result = bot.send_message(chat_id: params[:chat], text: params[:payload])
when 2
result = bot.send_photo(chat_id: params[:chat], photo: params[:payload])
when 3
result = bot.send_document(chat_id: params[:chat], document: params[:payload])
else
end
#messagelog.update_attributes(result: result.to_json)
rescue StandardError => msg
end
is invoked via an API and runs 5 times, rescued or not. Its route is:
namespace :api do
namespace :v1 do
post 'send', to: 'messages#send', defaults: { format: :json }
The class class Api::V1::MessagesController < Api::V1::ApibaseController does not invoke before_actions, however it inherits
class Api::V1::ApibaseController < ApplicationController
before_action :access_control
def access_control
authenticate_or_request_with_http_token do |token, options|
#server = Server.where('apikey = ?', token).first
end
end
Where is this multiplication of actions originating from? The only hiccup from the logs is a statment that:
No template found for Api::V1::MessagesController#send, rendering head :no_content
If the param are hard-wired to the action, this is also generated, but only one action occurs. Rails 5.2.4
How can this be resolved?

Rails - AbstractController::DoubleRenderError in my controller

This is my controller
class Api::V1::WebhooksController < ApplicationController
include Api::V1::WebhookHelper
include Api::V1::LogHelper
skip_before_action :verify_authenticity_token
after_action :handle_wehbook
# Schedule plan
def schedule_plan
add_log(status: "webhook", message: "New Plan is scheduled.")
end
def handle_wehbook
if webhook_verified?
webhook_verified!
render status: 200, json: { error: 'webhook is verified.' }
else
webhook_verified!(verified: false)
render status: 500, json: { error: 'webhook is not verified.' }
end
end
end
This is Webhook Helper.
I am sure in WebhookHelper, it never redirects or renders anything.
require 'openssl'
require 'base64'
module Api::V1::WebhookHelper
include Api::V1::LogHelper
def webhook_verified?
digest = OpenSSL::Digest.new('sha256')
hmac = OpenSSL::HMAC.digest(digest, secret, request.body.read)
hash = Base64.encode64(hmac).strip
hash == signature
end
def secret
ENV["API_KEY"]
end
def signature
request.headers["HTTP_X_SIGNATURE"]
end
def webhook_verified!(verified: true)
if verified
add_log(status: "webhook", message: "Webhook is verified.") # only puts log
else
add_log(status: "webhook", type: "warning", message: "Webhook is not verified.") # only puts log
end
end
end
I am getting this issue.
AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".):
app/controllers/api/v1/webhooks_controller.rb:31:in `handle_wehbook'
I am not sure I am calling render or redirect multiple times in my action.
Anyone can help me?
Your handle_wehbook function is an after_action, it runs after some other action.
The latter has already rendered something (it may be an rails error or a redirect) thus the double render

how to post to form from within an action

I have a link that goes to an action, so if someone clicks:
localhost/cart/checkout?pid=123
It goes to the CartController checkout action which then displays a form.
But in some circumstances (depending on when I load the Product with id 123) I may not need to display the form, I can just load the data and then post to the form's action.
How can I programatically post to where my form was going to post with data.
class CartController < ApplicationController
def checkout
pid = params[:pid]
product = Product.find(pid)
if product....
# no need to display view, just post to handleCheckout
end
end
# checkout form posts to this action
def handleCheckout
end
end
I have not done something like this before but I have some idea so please note that none of the is tested.
If your handleCheckout action is meant to be used as a Get request then you can redirect to this action with the params. like:
class CartController < ApplicationController
def checkout
pid = params[:pid]
product = Product.find(pid)
if product....
redirect_to action: "handleCheckout", params: params
# Not sure whether you will get it as 'params' or params[:params] in handleCheckout action
end
end
# checkout form posts to this action
def handleCheckout
end
end
And if handleCheckout is meant to be used as post Then above method might not work since redirect_to will create a new http Get request to that action. so you may try something like this:
def checkout
pid = params[:pid]
product = Product.find(pid)
if product....
handleCheckout
# params since is a global hash and above method has access to it
end
end
# checkout form posts to this action
def handleCheckout
# your other code
redirect_to 'some_action' and return
# in above line you have to return with a render or redirect
# Otherwise it will render 'checkout' template with render and redirect or
# it will throw double render error if you have a simple render or redirect without explicit return
end
As I mentioned, I have not tried any of above code. There might be errors. I hope it helps.

RAILS API Endpoint

I am a .NET developer and need to work on a API built in Ruby. Following is the API Code. Can anybody help me in getting the endpoint to it.
class Api::SessionsController < ApplicationController
respond_to :json
skip_before_filter :verify_authenticity_token
before_filter :protect_with_api_key
def update
status = true
participant_ids = []
unless params[:participants].blank?
params[:participants].each do |participant_data|
participant = Participant.where(participant_id: participant_data['participant_id']).first
unless participant.present?
status = false
participant_ids << participant_data['participant_id']
else
activity_records = participant_data['cumulative_time']['activity_records']
participant_data['cumulative_time']['activity_records'] = [] if activity_records.nil?
participant.participant_sessions.new(participant_data['cumulative_time'])
participant.save!
end
end
end
if status
render :json => {status: "OK"}
else
render :json => {error: "No participant with id # {participant_ids.join(',')}"}, :status => 422
end
end
end
I have tried to work with following way /api/sessions/
Pass the required key
passing the
participant parameter with PUT Request like below
{"participants":[{"first_name":"Demo", "last_name":"User", "email":"demouser#demouser.com", "password":"RubyNewBie","postal_code":"160055", "coordinator_name":"RubyNewBie", "coordinator_email":"info#RubyNewBie", "coordinator_phone":""}]}
Please guide me.
Thanks and Regards
By default, update action routes to /api/sessions/:id, so you should make query to that url. Also make sure that you have your route for session set up in routes.rb
Edit:
namespace :api do
resources :participants do
resources :sessions
end
end
If it looks like that, then you're using nested routing. Check:
http://guides.rubyonrails.org/routing.html#nested-resources
You'll have to use the url /api/participants/:participant_id/sessions/:session_id under that setting.

Ruby on rails, render 404 when type post id

Post model change to URL parameters to title
class Post < ActiveRecord::Base
def to_param
"#{id}-#{title}"
end
end
When any one type http://0.0.0.0:3000/posts/4 it redirect to belong particular post
When any one type post id, How redirect to 404 page?
I think you could just check if id is number or no. And do somehing like that:
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
like:
in application.rb:
def check_id(arg)
if params[arg] && params[arg].match(/\A[0-9]+\z/)
render_404
false
end
end
def render_404
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
end
in controller.rb:
before_filter -> { check_id(:id) }
In case you don't want to display a 404 error page from your controller, you can just redirect to your root path like this:
rescue ActiveRecord::RecordNotFound
redirect_to root_path
Method to_param needs to build path to resource: apidock.com/rails/ActiveRecord/Base/to_param
class User < ActiveRecord::Base
def to_param # overridden
name
end
end
user = User.find_by_name('Phusion')
user_path(user) # => "/users/Phusion"
How to make friendly URLs you can find out there
If you want to have user-friendly links, simple way is gem friendly-id

Resources