Ruby on Rails: Routing error - ruby-on-rails

I am having trouble deleting and showing user records.
Here is my routes.rb
FinalApp::Application.routes.draw do
resources :users
devise_for :users, :controllers => { :registrations => 'admin' }
resources :projects
match "search" => "projects#search", :as => :search
root :to => 'projects#index'
end
Here is my admin controller:
class AdminController < ApplicationController
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #users }
end
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# GET /users/1
# GET /users/1.json
def show
#user = User.find(params[:id])
#user_user_id = params[:id]
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
# GET /users/new
# GET /users/new.json
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
end
# POST /users
# POST /users.json
# PUT /users/1
# PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
end
Here is my view:
<%= stylesheet_link_tag "admin" %>
<body>
<div id ="title1">Admin</div>
<div class ="menu"></div>
<div id ="section3">
<table id = "mytable">
<table border = "1">
<tr>
<th>Username </th>
<th>Email</th>
<th>First Name</th>
<th>Last Name</th>
<th>Admin?</th>
<th></th>
<th></th>
<th></th>
</tr>
<%= link_to "New User", admin_new_path %><br />
<% #users.each do |t| %>
<tr>
<td><%= t.username %></td>
<td><%= t.email %></td>
<td><%= t.firstname %></td>
<td><%= t.lastname %></td>
<td><%= t.admin %></td>
<td><%= link_to 'Show', t %></td>
<td> <%= button_to "Delete", t, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table></br>
</body>
</html>
I can display the User database, but when I go to delete a record. I get this error No route matches [DELETE] "/users/11". I am new to rails so please remember this when trying to help. Thanks in advance.
Edit: here are my routes =>
admin_index GET /admin(.:format) admin#index
POST /admin(.:format) admin#create
new_admin GET /admin/new(.:format) admin#new
edit_admin GET /admin/:id/edit(.:format) admin#edit
admin GET /admin/:id(.:format) admin#show
PUT /admin/:id(.:format) admin#update
DELETE /admin/:id(.:format) admin#destroy
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) admin#cancel
user_registration POST /users(.:format) admin#create
new_user_registration GET /users/sign_up(.:format) admin#new
edit_user_registration GET /users/edit(.:format) admin#edit
PUT /users(.:format) admin#update
DELETE /users(.:format) admin#destroy
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
search /search(.:format) projects#search
root / projects#index
EDIT2: This is how my routes.rb file should have looked. Using rake routes I was able to change the paths to fix my problem.
FinalApp::Application.routes.draw do
# website home
root :to => 'projects#index'
# devise sessions (NB does not use admin/users controller)
devise_for :users, :controllers => { :registrations => 'users' }
# normal controllers
resources :users
resources :projects
# custom routes
match "search" => "projects#search", :as => :search
end

You should add resources :users to your routes.rb. In any case, you can always check rake routes in your console to see the available routes.
On a side note, the way you define you admin routes are not completely correct. Not everything is a get. For example, creating an admin would be a post. The easiest way is just to use something like resources :admins.

You have ended up with two routes leading to admin#destroy:
DELETE /users(.:format) admin#destroy
DELETE /admin/:id(.:format) admin#destroy
and yet you have no route which matches /users/xx, just a route which matches DELETE /users with an optional format bit. You have a route which matches /admin/11 so if you tried that it would work, however I would try to simplify things a bit.
Do you actually need to specify a controller on the devise resources? What exactly do you want to override there, as you have ended up with a load of routes (like cancel) which lead nowhere and some which clash...
Try a simpler routes definition (NB this requires renaming your AdminController UsersController instead, I would follow this convention as it will make your life easier, and match your other urls, so you end up with users/1 etc, not admin/1)
FinalApp::Application.routes.draw do
# website home
root :to => 'projects#index'
# devise sessions (NB does not use admin/users controller)
devise_for :users
# normal controllers
resources :users
resources :projects
# custom routes
match "search" => "projects#search", :as => :search
end
Then do rake routes to make sure you understand where the routes are pointing. You need a route which says (NB the :id bit):
DELETE /users/:id(.:format) users#destroy
or if you prefer an admin controller (and are willing to sort out the custom routes)
DELETE /admin/:id(.:format) admin#destroy
Perhaps before diving into this though you could read through the rails routing guide as it might clear a few things up for you:
http://guides.rubyonrails.org/routing.html

This appears to be a pretty standard use of Devise with your only notable difference being the name of your Controller. Therefore, the only thing you should need for devise routing is:
devise_for :users, :controllers => { :registrations => 'admin' }
Also, delete all of your "get 'admin/*'" entries. Not every HTTP method is a GET when you're working in a REST environment. Here is one article that discusses REST methods.

Related

Unable to find working route - No route matches {:action=>"show", :controller=>"users"}

No route matches {:action=>"show", :controller=>"users"}
Working with a condition current_page in rails with this format. Trying to not render a navbar within users/show path, but it should be visible in the rest of site. One thing to note is that the users/show URL has been configured in routes.rb to not show '/users/' folder in the URL, so it looks like 'mysite.com/username'
<% if current_page?(controller: 'users', action: 'show') %>
no navbar
<% else %>
<%= render partial: "shared/navbar" %>
<% end %>
The first condition works fine, however when I reach a page that should match the 'else' condition, for instance my root_path, I get this error:
ActionController::UrlGenerationError in Dashboard#show
Showing /Users/javier/Desktop/rails-apps/testtradus3/app/views/shared/_navbar.html.erb where line #1 raised:
No route matches {:action=>"show", :controller=>"users"}
My route.rb looks like this
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
Rails.application.routes.draw do
...
# This removes '/users/' from user/show URI
resources :users, path: '', :only => [:show]
# User account
devise_for :users,
controllers: {
omniauth_callbacks: "users/omniauth_callbacks",
registrations: "users/registrations",
sessions: "users/sessions"
}
devise_scope :user do
get "session/otp", to: "sessions#otp"
end
resources :users do
resources :builduser, controller: 'users/builduser'
end
...
end
This returns this rails routes:
users GET /users(.:format) users#index
POST /users(.:format) users#create
I have tried removing the custom path in routes.rb, so something like resources :users and that returns these routes
users GET /users(.:format) users#index
POST /users(.:format) users#create
GET /users(.:format) users#index
POST /users(.:format) users#create
GET /users/new(.:format) users#new
GET /users/:id/edit(.:format) users#edit
GET /users/:id(.:format) users#show
My UsersController.rb
class UsersController < ApplicationController
def index
#users = User.all
end
def show
#user = User.friendly.find(params[:id])
#order = Order.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
# format.html { redirect_to #order, notice: "Order was successfully created." }
# Added this one below:
format.html { redirect_to user_builduser_index_path(#user)}
format.json { render :show, status: :created, location: #user }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
..
end
Going off some of the examples listed in the link below, you could try:
current_page?(users_path(current_user))
# or
current_page?(users_path(#user))
# or even
current_page?("/#{#user&.id}")
An alternative could be to set a before_action in your ApplicationController to set an instance variable:
before_action :display_nav_bar # this would apply to all routes unless overridden like below in the UsersController
def display_nav_bar
#display_nav_bar = true
end
# and in your UsersController:
def show
#display_nav_bar = false
# other stuff
#user = User.find(params[:id)
end
then
<% if #display_nav_bar %>
<%= render partial: "shared/navbar" %>
<% else %>
no navbar
<% end %>
You could also look into using layouts for different controllers and control rendering the nav bar that way.
current_page? source

Rails Route adding dot with Devise

My rails app is adding a dot/period "." into the route when trying to browse to a devise gem user's profile.
routes.rb:
devise_for :users, :controllers => { :registrations => "registrations" }
(Basically using routes to allow for some custom functions - it should be still using the default devise routing paths.
Rake routes output:
user_registration POST /users(.:format) registrations#create
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
Link in view:
<%= link_to 'Edit', edit_user_registration_path(user) %>
Where user is defined in a .each loop.
Outputted Link in URL looks like:
http://localhost:3000/users/edit.2
My goal is to have a link to edit any user's profile (permissions controlled outside these items of course).
I "think" my problem is the routes.rb and not specifying the path correctly there. I think it should be something that would have a rake routes that includes an :id parameter.
Thanks for the help!
That's normal routes's devise, registrations#edit is for edit current signed-in user, If you want to CRUD interface for users (I think you want to editing a user), you can add another controller (e.g users_controller.rb) and make some action , example for controller :
def edit
#user = User.find(params[:id])
end
def update
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to some_path, notice: 'Updated.' }
format.json { head :no_content }
else
format.html {
flash[:alert] = "Something wrong"
render :action => :edituser
}
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
On your routes.rb you can following like this
scope '/user' do
match '/edit/:id' => 'users#edit', :as => :edit_user
put '/update/:id' => 'users#update', :as => :update_user
end
And links on each section looks like :
<%= link_to 'Edit', edit_user_path(user) %>
references :
How To: Manage users through a CRUD interface
CRUD Devise Example
I think Devise's edit_user_registration_path uses current_user internally, so you shouldn't need the (user) in your link_to

Ruby On Rails Routing Error (was previously working)

So I'm working on a project and I want to create new subcategory. The link was working but I'm not getting the following error:
No route matches {:action=>"show", :controller=>"subcategories"}
The project is fairly new so my routes file is very simple:
Mrprice::Application.routes.draw do
get "admin/index" => 'admin#index'
resources :products
resources :subcategories
resources :categories
root to: 'store#index', as: 'root'
end
In my view:
<%= link_to 'New Subcategory', new_subcategory_path %>
I'm sure there's a typo somewhere or else the solution is very simple but I can't for the life of me figure it out.
I hope I've given enough information and that someone here knows what the problem is!
edit: subcategories_controller.rb (relevant methods)
def show
#subcategory = Subcategory.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #subcategory }
end
end
def new
#subcategory = Subcategory.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #subcategory }
end
end
def create
#subcategory = Subcategory.new(params[:subcategory])
respond_to do |format|
if #subcategory.save
format.html { redirect_to #subcategory, notice: 'Subcategory was successfully created.' }
format.json { render json: #subcategory, status: :created, location: #subcategory }
else
format.html { render action: "new" }
format.json { render json: #subcategory.errors, status: :unprocessable_entity }
end
end
end
rake routes gives:
admin_index GET /admin/index(.:format) admin#index
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
subcategories GET /subcategories(.:format) subcategories#index
POST /subcategories(.:format) subcategories#creat
new_subcategory GET /subcategories/new(.:format) subcategories#new
edit_subcategory GET /subcategories/:id/edit(.:format) subcategories#edit
subcategory GET /subcategories/:id(.:format) subcategories#show
PUT /subcategories/:id(.:format) subcategories#updat
DELETE /subcategories/:id(.:format) subcategories#destr
categories GET /categories(.:format) categories#index
POST /categories(.:format) categories#create
new_category GET /categories/new(.:format) categories#new
edit_category GET /categories/:id/edit(.:format) categories#edit
category GET /categories/:id(.:format) categories#show
PUT /categories/:id(.:format) categories#update
DELETE /categories/:id(.:format) categories#destroy
root / store#index
note: not sure how to fix the formatting - I already tried a code block
Okay so I finally figured it out!
The problem was a routing error on the new subcategory form.
I had:
<%= link_to "Subcategories Home", subcategories_index_path %>
I know this was incorrect so I changed it to:
<%= link_to "Subcategories Home", subcategories_url %>
Mostly I just went through Rails Routing from the Outside In with a fine toothed comb until I figured out the correct way to route back to subcategories#index.

Add Edit and Delete feature in comment polymorphic-association-revised posts

I read this http://railscasts.com/episodes/154-polymorphic-association-revised posts and implement it as it have. But i want to add edit and delete features also in this tuotorial.
I have comments_controller.rb is like this
class CommentsController < ApplicationController
before_filter :load_commentable
def index
#comments = #commentable.comments
end
def new
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(params[:comment])
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
render :new
end
end
private
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
# def load_commentable
# klass = [Article, Photo, Event].detect { |c| params["#{c.name.underscore}_id"] }
# #commentable = klass.find(params["#{klass.name.underscore}_id"])
# end
end
my _comments.html.erb as given is like this
<div id="comments">
<% #comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
</div>
my routes is like this
Blog::Application.routes.draw do
resources :articles do
resources :comments
end
resources :photos do
resources :comments
end
resources :events do
resources :comments
end
resources :comments
root to: 'articles#index'
end
My rake routes is like this
article_comment GET /articles/:article_id/comments/:id(.:format) comments#show
PUT /articles/:article_id/comments/:id(.:format) comments#update
DELETE /articles/:article_id/comments/:id(.:format) comments#destroy
articles GET /articles(.:format) articles#index
POST /articles(.:format) articles#create
new_article GET /articles/new(.:format) articles#new
edit_article GET /articles/:id/edit(.:format) articles#edit
article GET /articles/:id(.:format) articles#show
PUT /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
photo_comments GET /photos/:photo_id/comments(.:format) comments#index
POST /photos/:photo_id/comments(.:format) comments#create
new_photo_comment GET /photos/:photo_id/comments/new(.:format) comments#new
edit_photo_comment GET /photos/:photo_id/comments/:id/edit(.:format) comments#edit
photo_comment GET /photos/:photo_id/comments/:id(.:format) comments#show
PUT /photos/:photo_id/comments/:id(.:format) comments#update
DELETE /photos/:photo_id/comments/:id(.:format) comments#destroy
photos GET /photos(.:format) photos#index
POST /photos(.:format) photos#create
new_photo GET /photos/new(.:format) photos#new
edit_photo GET /photos/:id/edit(.:format) photos#edit
photo GET /photos/:id(.:format) photos#show
PUT /photos/:id(.:format) photos#update
DELETE /photos/:id(.:format) photos#destroy
event_comments GET /events/:event_id/comments(.:format) comments#index
POST /events/:event_id/comments(.:format) comments#create
new_event_comment GET /events/:event_id/comments/new(.:format) comments#new
edit_event_comment GET /events/:event_id/comments/:id/edit(.:format) comments#edit
event_comment GET /events/:event_id/comments/:id(.:format) comments#show
PUT /events/:event_id/comments/:id(.:format) comments#update
DELETE /events/:event_id/comments/:id(.:format) comments#destroy
events GET /events(.:format) events#index
POST /events(.:format) events#create
new_event GET /events/new(.:format) events#new
edit_event GET /events/:id/edit(.:format) events#edit
event GET /events/:id(.:format) events#show
PUT /events/:id(.:format) events#update
DELETE /events/:id(.:format) events#destroy
comments GET /comments(.:format) comments#index
POST /comments(.:format) comments#create
new_comment GET /comments/new(.:format) comments#new
edit_comment GET /comments/:id/edit(.:format) comments#edit
comment GET /comments/:id(.:format) comments#show
PUT /comments/:id(.:format) comments#update
DELETE /comments/:id(.:format) comments#destroy
root / articles#index
Like so....? This assumes your routes are nested for :Edit, and :update actions under the "commentable" routes.
def edit
#comment = #commentable.comments.find(params[:id])
end
def create
#comment = #commentable.comments.find(params[:id])
if #comment.update_attributes(params[:comment])
redirect_to #commentable, notice: "Comment updated."
else
render :edit
end
end
Your edit should look like this:
<%= link_to 'Edit', [:edit, #comment.commentable, #comment] %>
However... you will want to have some kind of authentication and/or authorization.
I don't have a lot of time to look this over right now, but in response to your tweet I'm posting the code I was using in my test app that I got to work. I'm using HAML here.
When calling for an edit, or delete link in my view I used this partial:
- #category.photos.each do |photo|
= image_tag photo.image_url(:thumb)
%figcaption
= link_to "Change", [:edit, #category, photo]
= link_to "Delete", [#category, photo], :method => :delete
= link_to "New photo", [:new, #category, :photo]
My photos controller:
class PhotosController < ApplicationController
def create
#category = Category.find(params[:category_id])
#photo = #category.photos.create!(params[:photo])
redirect_to #category, :notice => "Photo created."
end
def edit
#category = Category.find(params[:category_id])
#photos = #category.photos
#photo = #photos.find(params[:id])
end
def update
#category = Category.find(params[:category_id])
#photo = #category.photos.find(params[:id])
respond_to do |format|
if #photo.update_attributes(params[:photo])
format.html { redirect_to #category, notice: "<i class=icon-ok /> #{#category.name} was successfully updated."}
format.js
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
def new
#category = Category.find(params[:category_id])
#photo = #category.photos.new
end
def destroy
#category = Category.find(params[:category_id])
#photos = #category.photos
#photo = #photos.find(params[:id])
#photo.destroy
redirect_to #category, :notice => "Photo deleted."
end
end
In my photo model I have:
class Photo
include Mongoid::Document
embedded_in :category, :inverse_of => :photos
field :image
attr_accessible :image
# Set uploader
mount_uploader :image, ImageUploader
end
In the category model:
class Category
# Includes to set up the model
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Ancestry
include Mongoid::Versioning
include Mongoid::Paranoia
include Mongoid::Slug
include Mongoid::History::Trackable
# tell it that it can go nest itself
has_ancestry
embeds_many :photos
# Accept nested attributes
accepts_nested_attributes_for :photos, :autosave => true
# tell history how it can track things
track_history :on => [:name, :description], # track these fields
#:modifier_field => :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier
:version_field => :version, # adds "field :version, :type => Integer" to track current version, default is :version
:track_create => false, # track document creation, default is false
:track_update => true, # track document updates, default is true
:track_destroy => false # track document destruction, default is false
# Keep at most 5 versions of a record
max_versions 5
# Add the models fields here
field :name, type: String
field :ancestry, type: String
field :description, type: String
# Set which field the url slug should use
slug :name
# Make sure these attributes can be accessed
attr_accessible :ancestry, :name, :parent_id, :description
# Make name fields capitalized on save
def name=(t)
write_attribute(:name, t.to_s.split(' ').map {|w| w.capitalize}.join(' '))
end
# Create some scopes
scope :except, lambda{ |category| where("id <> ?", category.id)}
end
Notes:
I just pasted a bunch of my code, cause I didn't have too much time to parse it down to answer specifically.
Hopefully the way I've written some of my code can help you.
Keep in mind that I'm using:
Mongoid
Rails 3
Cheers,
-Brandon
This is the destroy action for polymorphic association, I am sure you can figure out the Edit :)
VIEW
<%= link_to content_tag(:i, "", class: "icon-trash icons"), [#commentable, comment], method: :delete,
data: { confirm: "Are you sure?" },
title: "Delete" %>
CONTROLLER
def destroy
#comment = Comment.find(params[:id])
#commentable = #comment.commentable
if #comment.destroy
flash[:success] = "Comment Destroyed!"
redirect_to :back
end
end

Rails Import CSV - No Route Matches

I'm very new to Rails. I'm currently trying to import data from an csv file into my rails application. However, when I followed examples and guides online, I got the error: No route matches {:action=>"import_csv", :controller=>"lists"} I've already added it in my routes.rb though. Can anyone help me check what is wrong if my codes to cause to 'no route matches' error? Below are my files:
lists_controller.rb
def import_csv
require 'fastercsv'
respond_to do |format|
#csv=params[:file].read
#n=0
#parsed_file = CSV.parse(csv)
#parsed_file.each do |row|
#user_new = User.new
#user_new.first_name = row[0]
#user_new.last_name = row[1]
#user_new.email = row[2]
#user_new.address = row[3]
#user_new.city = row[4]
#user_new.state = row[5]
#user_new.zip = row[6]
#user_new.country = row[7]
#user_new.notes = row[8]
#user_new.birthday = row[9]
#user_new.home_number = row[10]
#user_new.mobile_number = row[11]
#user_new.list_id = list_id
#user_new.save
#n=#n+1
GC.start if n%50==0
flash[:notice] = "CSV Imported Successfully, with #{n} records"
end
format.html { redirect_to lists_url }
format.json { head :no_content }
end
end
app/views/lists/show.html.erb
<%= form_for(:list, :url => list_import_csv_path, :html => {:multipart => true}) do |f| %>
<table>
<tr>
<td><label for="dump_file">Select a CSV File :</label></td>
<td ><%= file_field_tag :file %></td>
</tr>
<tr>
<td colspan='2'><%= submit_tag 'Submit' %></td>
</tr>
</table>
<% end %>
routes.rb
resources :lists do
get 'import_csv'
#match '/import_csv/:id' => 'lists#import_csv', :as => :import_csv
end
rake routes
identities GET /identities(.:format) identities#index
POST /identities(.:format) identities#create
new_identity GET /identities/new(.:format) identities#new
edit_identity GET /identities/:id/edit(.:format) identities#edit
identity GET /identities/:id(.:format) identities#show
PUT /identities/:id(.:format) identities#update
DELETE /identities/:id(.:format) identities#destroy
newsletter_cancel GET /newsletters/:newsletter_id/cancel(.:format) newsletters#cancel
newsletters GET /newsletters(.:format) newsletters#index
POST /newsletters(.:format) newsletters#create
new_newsletter GET /newsletters/new(.:format) newsletters#new
edit_newsletter GET /newsletters/:id/edit(.:format) newsletters#edit
newsletter GET /newsletters/:id(.:format) newsletters#show
PUT /newsletters/:id(.:format) newsletters#update
DELETE /newsletters/:id(.:format) newsletters#destroy
list_import_csv GET /lists/:list_id/import_csv(.:format) lists#import_csv
lists GET /lists(.:format) lists#index
POST /lists(.:format) lists#create
new_list GET /lists/new(.:format) lists#new
edit_list GET /lists/:id/edit(.:format) lists#edit
list GET /lists/:id(.:format) lists#show
PUT /lists/:id(.:format) lists#update
DELETE /lists/:id(.:format) lists#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
Your form is submitted with a POST, while the route is for a GET. Either pass :method => :get to the form_for helper, or change your route to post (I would prefer the former though, since you're requesting data, not changing anything on the server).
To specify GET method for a form, you would do
<%= form_for (:list, :url => list_import_csv_path, :method => :get, :html => {:multipart => true}) do |f| %>
I'm also not sure if it's a good idea to force start garbage collection - it'd kill your performance if it kicks in while processing requests. Leftover objects should get garbage collected automatically.
I'd also extract the User export part (probably into a static method on the User model):
require 'faster_csv'
class User < ActiveRecord::Base
...
def self.import_from_csv(file)
CSV.parse(file).each do |row|
u = User.new(:first_name => row[0], :last_name => row[1] ...etc)
return false if !u.save
end
end
end
Then, in the controller:
def import_csv
respond_to do |format|
if !User.import_from_csv(params[:file])
format.html { render :show, :error => "Some error here" }
format.json { render :json => "Some error here", :status => :unprocessable_entity }
else
format.html { redirect_to lists_url, :notice => "Import successful!" }
format.json { :head => :ok }
end
end
end
Use post instead of get in your config/routes.rb.

Resources