Syntax error in content type case statement - ruby

This is my code in my Padrino application and I can't figure out what line or bug it is. The error message is "syntax error, unexpected keyword_end expecting $end"
get :index, :provides => [:html, :json] do
#title = "Restaurants"
#restaurants = Restaurant.all
case content_type
when :json
render #restaurants
else
render 'restaurants/index'
end
end
end
Could you please point out my mistake and also suggest how I might debug it in future? Thanks

You have one spare end keyword.
You should remove one.
There is a little mess with indentation in your code. Keeping right indentation helps a lot in avoiding such errors. I would suggest to indent your code like this:
get :index, :provides => [:html, :json] do
#title = "Restaurants"
#restaurants = Restaurant.all
case content_type
when :json
render #restaurants
else
render 'restaurants/index'
end
end

There's an end too much.
Be more careful with your code indentation and this will never be a problem. Example on how it would look in Vim under. I just used =G and it aligned it for me. Additionaly, it'll only highlight the correct use of end. Your favorite editor of choice should have this functionality too. If not, switch.

try this:
get :index, :provides => [:html, :json] do
#title = "Restaurants"
#restaurants = Restaurant.all
case content_type
when :json
render #restaurants
else
render 'restaurants/index'
end
end

Related

How to display payment gateway response messages in view - Rails 4, Active Merchant

I'm using Active Merchant with Stripe as the payment gateway. Everything works fine except that i don't know how to go about getting the gateway response error messages from Stripe (when a card is declined, invalid etc) to display on the checkout page to the user. I can get a StandardError to be raised that redirects to an error page with the response message but that's it.
ORDER MODEL
class Order < ActiveRecord::Base
has_many :order_products
has_many :products, through: :order_products
attr_accessor :card_number, :security_code, :card_expires_on
validate :validate_card, :on => :create
def validate_card
unless credit_card.valid?
credit_card.errors.full_messages.each do |message|
errors[:base] << message
end
end
end
def purchase(basket)
response = GATEWAY.purchase(Product.total_basket_price(basket)*100, credit_card, purchase_options)
unless response.success?
raise StandardError, response.message
end
end
def credit_card
#credit_card ||= ActiveMerchant::Billing::CreditCard.new(
:number => card_number,
:first_name => first_name,
:last_name => last_name,
:verification_value => security_code,
:month => card_expires_on.month,
:year => card_expires_on.year
)
end
def purchase_options
{
:billing_address => {
:address1 => address_1,
:address2 => address_2,
:city => city,
:country => country_code,
:zip => postal_code
}
}
end
end
ORDERS CONTROLLER
class OrdersController < ApplicationController
def create
#order = Order.new(order_params)
# #product = basket.find(params[:product_id])
basket.each do |item_id|
#order.order_products.build(product: Product.find(item_id))
end
if #order.save
if #order.purchase(basket)
render "show"
else
render "failure"
end
else
render "new"
end
end
Can anyone lend a hand, please??
Many Thanks
Easy peasy!
This is a simple matter of control flow. In Ruby, as in most languages, exceptions interrupt the normal program flow. As your code is written now, #purchase is raising an exception when it fails.
That's fine and a perfectly valid design decision. But the code interacting with #purchase is this:
if #order.purchase(basket)
render "show"
else
render "failure"
end
That code has no exception handling, so any exception will be caught by Rails, program flow will halt, and you'll get either a detailed error page (in development mode) or a generic 500 error page (in production mode).
Since you profess to be new to Ruby and Rails, a little code substitution might make this clearer:
# If #purchase is successful, it evaluates to true.
if true
render "show" # 'show' view is rendered as expected. Flow stops.
else
render "failure"
end
# If #purchase fails, it raises an exception.
if raise StandardError, response.message
# ^^^ Exception is raised, flow stops here.
render "show" # This code is never reached.
else # This code is never reached.
render "failure" # This code is never reached.
end
As I implied in the beginning, though, it's an easy fix once you know what the issue is. You can simply handle the exception with rescue. Where you currently have an if/else block, you can swap in an if block and a rescue block:
if #order.purchase(basket)
render 'show'
end
rescue => e
render 'failure'
There's room for improvement here depending on your needs—since you're raising and rescuing StandardError, for example, your can't easily distinguish between a network failure and a declined card—but it'll get you moving again.
After a lot of fiddling and help, the working solution was to search for an error key within the response params hash and if an error was present add the message to the object errors. Not particularly elegant but it now does what i want.
ORDER MODEL
def purchase(basket)
response = GATEWAY.purchase(Product.total_basket_price(basket)*100, credit_card, purchase_options)
if response.params.key?('error')
self.errors.add :base, response.message
false
else
true
end
end
ORDERS CONTROLLER
Also switched the order of the if statements in the controller so that def purchase(basket) runs first before the order is saved, allowing the error message(s) from the response to be caught and displayed.
if #order.purchase(basket)
if #order.save
render "show"
else
render "new"
end
else
render "new"
end
VIEW
<%= if #order.errors.any?
#order.errors[:base].to_sentence
end%>

Before filter on condition

I have a Sinatra app where all routes require a user login by default. Something like this:
before do
env['warden'].authenticate!
end
get :index do
render :index
end
Now I would like to use a custom Sinatra condition to make exceptions, but I cannot find a way to read if the condition is true/false/nil
def self.public(enable)
condition {
if enable
puts 'yes'
else
puts 'no'
end
}
end
before do
# unless public?
env['warden'].authenticate!
end
get :index do
render :index
end
get :foo, :public => true do
render :index
end
Since the authentication check must be done even if the condition is not defined, I guess I still must use a before filter, but I am not sure how to access my custom condition.
I was able to solve this using Sinatra's helpers and some digging into Sinatra's internals. I think this should work for you:
helpers do
def skip_authentication?
possible_routes = self.class.routes[request.request_method]
possible_routes.any? do |pattern, _, conditions, _|
pattern.match(request.path_info) &&
conditions.any? {|c| c.name == :authentication }
end
end
end
before do
skip_authentication? || env['warden'].authenticate!
end
set(:authentication) do |enabled|
condition(:authentication) { true } unless enabled
end
get :index do
render :index
end
get :foo, authentication: false do
render :index
end

Is there any issues to have `end` as a method name?

I am working on a RoR project, and I want to know if I can use end as a method name. It seems to work fine, but I would like to know if this method will bring any issues in the future. I tried and it works:
class Dany
def end
puts 'Hola'
end
end
and this is the output:
Dany.new.end # => Hola
Ruby let's you do this, but you're going to run into all sorts of issues.
# end.rb
class Dany
def end
puts "Hola"
end
def other
end # should puts Hola
end
end
Instead, you will get
end.rb:10: syntax error, unexpected keyword_end, expecting end-of-input
Bottom line: don't do this. Don't use any keywords as a method name.
It is not a good idea to use a keyword as a method name, but as long as you disambiguate the token as a method call, you can use it. It is not practical though.
Dany.new.instance_eval{self.end} # => Hola
Dany.new.send(:end) # => Hola
Dany.new.method(:end).call # => Hola
Dany.new.instance_eval{end} # => syntax error, unexpected keyword_end
The usual disambiguation using () does not seem to work for this case, making it complicated.
Dany.new.instance_eval{end()} # => syntax error, unexpected keyword_end

syntax error, unexpected $end, expecting keyword_end

I am getting this error when trying to click a button with umlaut:
syntax error, unexpected $end, expecting keyword_end
click_on 'Neue Firma hinzufц╪gen'
I am testing with Ruby & Capabara.
##Create_User_spec.rb
require 'acceptance/acceptance_helper'
## Feature 'Create User'
feature 'Create User' do ##
Scenario 'Create a User'
scenario 'Create a User' do
## Login into the service
visit 'url'
fill_in 'User-username', :with => 'test'
fill_in 'User-password', :with => 'test'
click_on 'login'
click_link 'Test'
click_on 'Neue Firma hinzufügen'
end
end
This also can happen if you have a stray . trailing a method, so check for those as well.
It happened to me because of special characters, in my case portuguese signs. I believe the problem is the "ü" in hinzufügen. Looking for a solution yet.
Edit: found a solution!
I added the following to the very top of the rb file:
# encoding: utf-8
(don't miss the # sign, it is needed)
This error due to an extra end.Mean you have written an extra end with no matching do.
This happened to me as well but because I was missing an end. I am following this tutorial
http://tutorials.jumpstartlab.com/projects/blogger.html
My model was:
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
It needed to be:
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
end
Hope that helps someone.

Erb template not rendering when used with ensure exception handling

I have come across a issue when writing some sinatra code I have the follow block of code
begin
# do stuff here
rescue SomeException::Class => ex
flash.now[:err] = "some error " + ex.message
ensure
erb :content, :layout => :mainlayout
end
The problem I have is the erb output is only partially rendered, mainlayout.erb is rendered, however, content.erb doesn't get included. I have used the same erb line in other parts of the application and they work fine.
The following actually works and is a work around that I am currently using
begin
# do stuff here
erb :content, :layout => :mainlayout
rescue SomeException::Class => ex
flash.now[:err] = "some error " + ex.message
erb :content, :layout => :mainlayout
end
Any ideas to why this isn't completing when under ensure? I would like to use it as its more elegant.
try to use return erb :content, :layout => :mainlayout read more about ensure here - http://blog.leshill.org/blog/2009/11/17/ensure-with-explicit-return.html

Resources