406 Not Acceptable on such a basic controller - ruby-on-rails

Not sure why I'm getting this. I did a bunch of reading and I can't make heads or tails of this.
My controller:
def create
#emails = Email.new(params[:email])
respond_to do |format|
if #emails.save
flash[:notice] = 'Email was successfully created.'
format.html { redirect_to admin_emails_path(:mail_type => #emails.mail_type) }
format.xml { render :xml => #emails, :status => :created, :location => #emails }
else
format.html { render :action => "new" }
format.xml { render :xml => #emails.errors, :status => :unprocessable_entity }
end
end
end
Nothing crazy there. Its a multipart(images) form submission..maybe that has something to do with?
Update
Some irb stuff:
>> admin_emails_path(:mail_type => #emails.mail_type)
"/admin/emails?mail_type=magic_email"
>> admin_emails_path(#emails)
"/admin/emails.%23%3Cemail:0x109eb6360%3E"
The second example seems to be what it actually is returning, ignoring my additional params in the URL.
I should also note that my edit redirect is identical, and it works perfectly.
Update 2
Just to show how completely helpless this situation is, I've changed my controller to this :
if #emails.save
flash[:notice] = 'Email was successfully created.'
debugger
format.html { render :action => "new" } # <=== WTF ?
format.xml { render :xml => #emails, :status => :created, :location => #emails }
else
And I still get this:
Completed in 7401ms (View: 3, DB: 7) | 406 Not Acceptable [http://localhost/admin/emails.%23%3Cemail:0x109fd2a28%3E]
Routes
admin.resources :emails, :collection => {:test_email => :get}, :member => {:update_current => :get, :send_email => :get, :duplicate => :get} do |email|
email.resources :distributions, :collection => {:delete_dist => :get}
end
Form
- form_for #emails, :url => admin_email_path(#emails), :id => "email_form", :html => {:multipart => true} do |f|
... lots of stuff ..
.clear
%p
= f.submit 'Save Email', :class => "button"

The MIME type for the request is determined by the file extension incoming.
The error here is the following line:
>> admin_emails_path(#emails)
"/admin/emails.%23%3Cemail:0x109eb6360%3E"
The helper admin_emails_path should not be passed the list of e-mails. This collection path should work on it's own. When you pass in the #emails object, it's trying to encode it into the URL and injecting a period, which rails is parsing like a file extension (the url decoded version of %23%3Cemail:0x109eb6360%3E).
Change the reference from:
admin_emails_path(#emails)
to:
admin_emails_path
...and you will not see these format errors.

Related

RSS link in Rails

I need to add a link to a rss page but i don't know how
def index
#boxes = Box.paginate :page => params[:page], :order => "boxes.id desc", :per_page => 5,
:include => [:suppliers, :manufacturer]
#page_title = 'Catálogo'
respond_to do |format|
format.html
format.xml { render :xml => #boxes }
format.rss { render :layout => false }
end
end
the url to access is http://localhost:3000/catalog.rss but i don't know how to make it like this <%= link_to 'Canal RSS', :action => 'index' %>
In your routes.rb, you add the route first:
get 'catelog' => '<YOUR_CONTROLLER_NAME>#index', :constraints => {:format => :rss}
Then you can use it like this:
<%= link_to 'Canal RSS', catelog_url %>
catelog is the route prefix. You can run rake routes to see it.

Trying to have admin user create other users, but it keeps taking me to Edit User after submitting

I was following Tony Amoyal's setup for authentication using Devise/cancan and only allowing an admin to create/register new users. I didn't follow him exactly because there is no need for users to have multiple roles in this application, but for the most part I used exactly what he suggested.
It mostly works, but the biggest issue I am having right now is when I try to create a new user and submit it on the register form, it immediately complains, takes me to Devise's edit registration form and complains about the :current_password field not being filled in. If I fill anything in at that point, it will update MY user, not the one I was trying to register.
Any help to get it to actually create the user instead of requesting more changes would be appreciated.
#controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :check_permissions, :only => [:new, :create, :cancel]
skip_before_filter :require_no_authentication
def check_permissions
authorize! :create, resource
end
end
#controllers/users_controller.rb
class UsersController < ApplicationController
load_and_authorize_resource :except =>[:create]
...
def new
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
end
...
def create
#user = User.new(params[:user])
if #user.save
respond_to do |format|
format.json { render :json => #user.to_json, :status => 200 }
format.xml { head :ok }
format.html { redirect_to :action => :index }
end
else
respond_to do |format|
format.json { render :text => "Could not create user", :status => :unprocessable_entity } # placeholder
format.xml { head :ok }
format.html { render :action => :new, :status => :unprocessable_entity }
end
end
end
end
#views/users/new.html.haml
= simple_form_for(#user, :method => :put, :html => { :class=>'form-horizontal' }) do |f|
%fieldset
%legend
= f.input :first_name
= f.input :last_name
= f.input :email
= f.input :password
= f.input :password_confirmation
.form-actions
= f.submit 'Register', :class => 'btn btn-primary'
= link_to 'Back', :back, :class => 'btn'
I was able to get around this problem by giving devise a path_prefix which would ensure this process is using my UsersController.

Filter json render in Rails

What is the best way if i would like to only return :id and :name fields in JSON
So far i have:
format.json { render :json => #contacts.map(&:attributes) , :only => ["id"]}
But the "name" attribute does not work in the :only section, since it is not a column in the database (it is defined in the model as firstname + lastname)
Thanks!
Rails 3 supports following filter options. as simple as is
respond_to do |format|
format.json { render json: #contacts, :only => [:id, :name] }
end
You can pass :methods to to_json / as_json
format.json do
render :json => #contacts.map { |contact| contact.as_json(:only => :id, :methods => :name) }
end
Alternatively you can just build up a hash manually
format.json do
render :json => #contacts.map { |contact| {:id => contact.id, :name => contact.name} }
end
See: http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json

rails - Devise - Creating a Registration Form

I've been banging my head against the wall try to understand how to get Devise to work with customer registration....
So On my landing page I want to show a registration form, so I added this to my view:
<%= render 'devise/registrations/new' %>
In that partial I have in the view a form tag like follows:
<%= form_for(user_registration_path, :url => user_registration_path) do |f| %>
.
.
In my application layout I have:
<% flash.each do |key, value| %>
<div class="flash <%= key %>"><%= value %></div>
<% end %>
The issue I'm having is when I submit a new registration form with invalid params, I don't see the error message?
But if I submit valid info the form does say it worked and that I need to check my email for the confirmation link, which is good.
Can you help me understand how to get this working end-2-end so I can display the errors:
Here's my full controller:
# GET /users/new
# GET /users/new.xml
# GET /users/new.json HTML AND AJAX
#-------------------------------------------------------------------
def new
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
end
# GET /users/1/edit
# GET /users/1/edit.xml
# GET /users/1/edit.json HTML AND AJAX
#-------------------------------------------------------------------
def edit
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
# POST /users
# POST /users.xml
# POST /users.json HTML AND AJAX
#-----------------------------------------------------------------
def create
#user = User.new(params[:user])
if #user.save
respond_to do |format|
format.json { render :json => #user.to_json, :status => 200 }
format.xml { head :ok }
format.html { redirect_to :action => :index }
end
else
respond_to do |format|
format.json { render :text => "Could not create user", :status => :unprocessable_entity } # placeholder
format.xml { head :ok }
format.html { render :action => :new, :status => :unprocessable_entity }
end
end
end
The model:
validates :fname, :presence => true, :length => { :minimum => 2 }
validates :lname, :presence => true, :length => { :minimum => 2 }
validates :password, :presence => true, :length => { :minimum => 6 }
validates :email, :presence => true, :length => { :minimum => 6 }
From the github readme:
"Remember that Devise uses flash messages to let users know if sign in was successful or failed. Devise expects your application to call "flash[:notice]" and "flash[:alert]" as appropriate."
Where is your <%= error_messages_for %>? That is how errors will be displayed.
Also, devise needs virtual attributes in the model for additional attributes so don't forget to add :lname, :fname etc... to the devise user model or whatever you are doing.
Update
<%= f.error_messages_for :model %>
Before Rails 3 this is how errors were formatted, but in R3 it's depircated and you need to install a plugin to access errors this way. See comments for the link to the plugin
Just insert this at the beginning of your form, end before the end of it:
<%= devise_error_messages! %>
Devise is kinda tricky, I just finally managed to figure it out myself, and it's awesome. Btw, don't render the view as a partial, use templates, and then set your root to users#registrations_controller, given that you created custom controllers and views.
If you haven't, I wrote a blog post about it here

link_to :action => 'create' going to index rather than 'create'

I am building a fairly simple recipe app to learn RoR, and I am attempting to allow a user to save a recipe by clicking a link rather than through a form, so I am connecting the user_recipe controllers 'create' function through a link_to.
Unfortunately, for some reason the link_to is calling the index function rather than the create.
I've written the link_to as
<%= "save this recipe", :action => 'create', :recipe_id => #recipe %>
this link is on the user_recipes/index.html.erb and is calling the 'create' function of the same controller. It doesn't seem to make a difference if I include the :controller or not.
The controllers look like this
def index
#recipe = params[:recipe_id]
#user_recipes = UserRecipes.all # change to find when more than one user in db
respond_to do |format|
format.html #index.html.erb
format.xml { render :xml => #recipes }
end
end
def create
#user_recipe = UserRecipe.new
#user_recipe.recipe_id = params[:recipe_id]
#user_recipe.user_id = current_user
respond_to do |format|
if #menu_recipe.save
format.html { redirect_to(r, :notice => 'Menu was successfully created.') }
format.xml { render :xml => #menu, :status => :created, :location => #menu }
else
format.html { render :action => "new" }
format.xml { render :xml => #menu.errors, :status => :unprocessable_entity }
end
end
In the standard REST scheme the index action and the create action both have the same url (/recipes) and only differ in that index is accessed using GET and create is accessed using POST. So link_to :action => :create will simply generate a link to /recipes which will cause the browser to perform a GET request for /recipes when clicked and thus invoke the index action.
To invoke the create action use link_to {:action => :create}, :method => :post, telling link_to explicitly that you want a post request, or use a form with a submit button rather than a link.
Assuming you have default resources set up in your routes file, i.e. something like this
resources :recipes
The following will generate a link that will create a recipe; i.e. will be routed to the create action.
<%= link_to "Create Recipe", recipes_path, :method => :post %>
For this to work, JS needs to be enabled in your browser.
The following will generate a link that will show all recipes; i.e. will be routed to the index action.
<%= link_to "All Recipes", recipes_path %>
This assumes the default which is a Get HTTP request.

Resources