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
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.
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.
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
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
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.