How to allow custom flash keys in a redirect_to call in Rails 3 - redirect

In Rails 3, you can pass has attributes directly to redirect_to to set the flash. For example:
redirect_to root_path, :notice => "Something was successful!"
However, this only works with the :alert and :notice keys; if you want to use custom keys, you have to use a more verbose version:
redirect_to root_path, :flash => { :error => "Something was successful!" }
Is there any way to make it so that custom keys (such as :error, above) can be passed to redirect_to without specifying it in :flash => {}?

In Rails 4 you can do this
class ApplicationController < ActionController::Base
add_flash_types :error, ...
and then somewhere
redirect_to root_path, error: 'Some error'
http://blog.remarkablelabs.com/2012/12/register-your-own-flash-types-rails-4-countdown-to-2013

I used the following code, placed in lib/core_ext/rails/action_controller/flash.rb and loaded via an initializer (it's a rewrite of the built-in Rails code):
module ActionController
module Flash
extend ActiveSupport::Concern
included do
delegate :alert, :notice, :error, :to => "request.flash"
helper_method :alert, :notice, :error
end
protected
def redirect_to(options = {}, response_status_and_flash = {}) #:doc:
if alert = response_status_and_flash.delete(:alert)
flash[:alert] = alert
end
if notice = response_status_and_flash.delete(:notice)
flash[:notice] = notice
end
if error = response_status_and_flash.delete(:error)
flash[:error] = error
end
if other_flashes = response_status_and_flash.delete(:flash)
flash.update(other_flashes)
end
super(options, response_status_and_flash)
end
end
end
You can, of course, add more keys besides just :error; check the code at http://github.com/rails/rails/blob/ead93c/actionpack/lib/action_controller/metal/flash.rb to see how the function looked originally.

Related

Rails 4 welcome wizard, how to correct this code to make it work for rails 4?

Try to build a welcome wizard and try to get existing rails code to be ported to be rails 4 compatible. Based mostly on previous great answer: https://stackoverflow.com/a/17255451/355281
I try to call http://books:3000/welcome/basics
This results in:
Circular dependency detected while autoloading constant WelcomeController
app/controllers/welcome_controller.rb
class Welcome::ApplicationController < ::ApplicationController
layout "welcome"
before_filter :authentice_user!
end
app/controllers/welcome_basics_controller.rb
class Welcome::BasicsControlller < Welcome::ApplicationController
before_action :authenticate_user!
before_filter :allowed?
def new
#step = Welcome::Basics.new(current_user)
end
def create
#step = Welcome::Basics.new(current_user)
if #step.save(params[:welcome_basics])
redirect_to welcome_some_other_step_path, :notice => "Yay"
else
render :new
end
end
private
def step
#step ||= Welcome::Basics.new(current_user)
end
helper_method :step
def allowed?
redirect_to previous_step_path unless step.allowed?
end
end
**app/models/welcome_basics.rb
class Welcome::Basics
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
def persisted?
false
end
def initialize(user)
#user = user
end
attr_reader :user
delegate :some_field, :some_other_field, :to => :user
validates_presence_of :some_field
def save(params)
user.some_field = params[:some_field]
user.some_other_field = params[:some_other_field]
if valid?
user.step = 2
user.save
end
end
def photo
#photo ||= Photo.new
end
def profile
#profile ||= user.profiles.first
end
end
/config/routes.rb
namespace :welcome do
resource :basics, :only => [:new, :create]
end
I see a few things that appear to be off. The one that appears to be the biggest issue with Rails 4 vs Rails 3.2 is in your pseudo-model definition.
class Welcome::Basics
include ActiveModel::Model # Necessary for Rails 4
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
...
end
In your welcome_controller.rb, you have authentice user which should read authenticate user.
In your welcome_basics_controller.rb you misspelled controller in your definition, currently: Welcome::BasicsControlller should be Welcome::BasicsController.
I'd also recommend that you change your naming and inheritance to be a bit simpler and more inline with Rails convention over configuration. This would be my approach:
Since welcome_basics.rb is a pseudo-model, I'd put it in its own directory to prevent any potential automatic sourcing of ActiveModel. I'd also change the name to the singular to be in line with Rails conventions for models.
app/pseudo_models/welcome_basic.rb
class WelcomeBasic
include ActiveModel::Model # Necessary for Rails 4
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
...
end
Now I'd put your welcome_controller in a sub-directory called "welcome" within the controller directory:
app/controllers/welcome/welcome_controller.rb
class Welcome::WelcomeController < ApplicationController
layout "welcome"
before_filter :authenticate_user!
end
Then your basics controller should be called basics within the "welcome" directory, and since your inheriting from your welcome controller, you don't need to repeat the authenticate_user! line. Also remember that you'll need to rename your calls to your pseudo-model from Welcome::Basics to WelcomeBasic. For Rails 4 you'll also need to implement strong params in your controller.
app/controllers/welcome/basics_controller.rb
class Welcome::BasicsController < Welcome::WelcomeController
before_filter :allowed?
def new
#step = WelcomeBasic.new(current_user)
end
def create
#step = WelcomeBasic.new(current_user)
if #step.save(basic_params) #updated to use strong_params
redirect_to welcome_some_other_step_path, :notice => "Yay"
else
render :new
end
end
private
#For strong_params
def basic_params
params.require(:welcome_basic).permit(:attribute1, :attribute2)
end
def step
#step ||= WelcomeBasic.new(current_user)
end
helper_method :step
def allowed?
redirect_to previous_step_path unless step.allowed?
end
end
/config/routes.rb
...
namespace :welcome do
resources :basics, :only => [:new, :create]
end
...
The other thing that you'll need to ensure is that your corresponding views are placed within the same directory structure as your controller, so you should have the following:
/app/views/welcome/basics/welcome.html.erb
One other note, when you say "I try to call http://books:3000/welcome/basics", I assume you mean that your attempting to post your form? Otherwise, you should be calling http://books:3000/welcome/basics/new in order to get your basics form. If you want that route to map to http://books:3000/welcome/basics you'll need to make the corresponding adjustments in your config/routes.rb file.

databasedotcom error on no record found

Just started using databasedotcom gem and now stuck.
When trying to find a record in Salesforce by Id, if the id/record doesn't exist, it produces the following error:
"Provided external ID field does not exist or is not accessible:"
If the Id does exist I am able to continue with my page fine.
Here's my code:
def search
#account = Account.find(params[:id])
if #account.Id
redirect_to new_user_registration_path(:id => #account.Id)
elsif params[:id].to_s.present? and #account.nil?
flash[:alert] = "Couldn't find that one. Please check and re-submit your number."
redirect_to search_path
end
end
How can I overcome this?
Thank you.
Changed the code to the following and it works fine now - thank you Danny Burkes. It captures the exception and routes accordingly.
def search
begin
#account = Account.find(params[:id])
if #account.Id
redirect_to new_user_registration_path(:id => #account.Id)
end
rescue Exception => e
flash[:alert] = "Couldn't find that one. Please check and re-submit your number."
redirect_to search_path
end
end

Facebook Authentication using Koala does not work -- Fails to retrieve access_token

This is a web app that uses FB connect. Koala - Rails
Controller code:
class UsersController < ApplicationController
before_filter :parse_facebook_cookies
def parse_facebook_cookies
#facebook_cookies ||= Koala::Facebook::OAuth.new('api_id','app_secret').get_user_info_from_cookie(cookies)
end
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
#title = "sign up"
require 'koala'
#graph = Koala::Facebook::API.new
#access_token = #facebook_cookies["access_token"]
#user1 = #graph.get_object("me")
#user.name = #user1["name"]
#user.uid = #user1["id"]
#user.save
end
end
It gives me the following error when executing:
#access_token = #facebook_cookies["access_token"]
"undefined method `[]' for nil:NilClass"
I appreciate any pointers to what may be going wrong! Thanks!

Non-expiring sessions in Padrino

I've made a Padrino app that has one single password for accessing the admin page. I'm using the following helpers for the authorization.
# Check if the user is authenticated.
def authenticated?(opts = {})
if session["cooly"] != options.session_secret
redirect url(opts[:send_to] || :login)
end
end
# Create a new session.
def authenticate!
session["cooly"] ||= 0
session["cooly"] = options.session_secret
end
Write now, when I exit my browser, the session goes away and I have to login again. How do I keep the session?
Make sure you have the in your app session_secret
set :session_secret, 'fc29ce0f33f0c8cde13f3'
The answer was to make non-expiring cookies.
# Check if the user is authenticated.
def authenticated?(opts = {})
if session["cooly"] == options.session_secret || request.cookies["cooly"] == options.session_secret
return true
else
redirect url(opts[:send_to] || :login)
end
end
# Create a new session.
def authenticate!
session["cooly"] ||= 0
session["cooly"] = options.session_secret
expiration_date = 10.year.from_now
response.set_cookie('cooly', :value => options.session_secret, :expires => expiration_date)
end
Check out: https://gist.github.com/977690 and that should resolve the issue.

Write Web call for iphone in ruby on rail. I want to get json formate and send response but formate of json is incorrect

I have a bug in the following Rails code which I cannot find. Any help would be appreciated.
class Api::ItemsController < ApplicationController
respond_to :json
def create
begin
#puts "params: #{params}"
if params[:item_post][:user][:uid] && params[:item_post][:user][:provider]
#user = User.find_by_provider_and_uid(params[:item_post][:user][:provider], params[:item_post][:user][:uid])
elsif params[:item_post][:user][:token]
#user = User.create_with_token(params[:item_post][:user][:token])
elsif params[:item_post][:user][:email]
#user = User.find_by_email(params[:item_post][:user][:email])
end
if #user
#item = #user.items.new(params[:item_post][:item])
else
#item = Item.new(params[:item_post][:item])
#item.reply_email = params[:item_post][:user][:email]
end
if #item.save
if params[:item_post][:item_images]
params[:item_post][:item_images].each_value do |item_image|
#item.images.create(item_image)
end
end
respond_with(#item)
else
#puts "Errors 1: #{#item.errors}"
respond_with(#item.errors)
end
rescue => e
#puts "Errors 2: #{e.message}"
respond_with(e.message.to_json, :status => :unprocessable_entity)
end
end
end
Problem:
I have been looking into the parameters received by the server. And I've tried to find the code where the parameters are built. Where can I find it?
In the server logs I can see the post as:
{"item_post":"{\"item\":{\"title\":\"Apple TV\",\"price\":\"45.50\",\"description\":\"Dual-Shielded High Speed HDMI Cable with Ethernet 2M are sold yesterday\",\"zipcode\":\"94102\"},\"user\":{\"email\":\"user#email.com\"}}}
I was expecting the post to look like this:
{\"item_post\":{\"item\":{\"title\":\"Apple TV\",\"price\":\"45.50\",\"description\":\"Dual-Shielded High Speed HDMI Cable with Ethernet 2M are sold yesterday\",\"zipcode\":\"94102\"},\"user\":{\"email\":\"user#email.com\"}}}
It seems to me that the 'item_post' block is being wrapped in unnecessary quotes, making it a string instead of a JSON hash:
I think this:
{"item_post":"{
should look like (no quote) this:
{"item_post":{
I am only guessing to what the problem could be.
I think you need avoid the to_json in your rescue
respond_with(e.message.to_json, :status => :unprocessable_entity)
put
respond_with(e.message, :status => :unprocessable_entity)
In your case the to_json before the to_json in the respond_with return a String it's why you have a String convert in JSON and not your Hash convert in JSON