The application has: Clients, which has and belongs to many ActionItems, which has and belongs to many Clients. A user, chooses a client (a client they have as a customer), and adds action items (to do's) to that client. -- Like: User creates => "Email client about X topic," for client: Crayola LLC.
I've been instructed to nest resources like so, in routes:
resources :clients do
resources :action_items
end
So that I can get a URL like:
-http://localhost:3000/clients/42/action_items/11
To display the action items for a specific client.
However - deleting action items for that client, doesn't work. It's been trying to redirect me to the destroy action, on which I get:
undefined local variable or method `clients_action_items' for # <ActionItemsController:0x007febd0edf800>
Prior to this, the delete link, which uses the destroy action, was attempting to redirect me to the show page, on which I was getting:
No route matches [POST] "/clients/42/action_items/1"
Then I added: post '/clients/:client_id/action_items/:id' => 'action_items#destroy' to the routes file. (and now I get the undefined local variable or method clients_action_items' error.
Routes:
Rails.application.routes.draw do
get 'users/index'
get 'users/new'
get 'users/edit'
get 'users/delete'
get 'users/create'
patch 'users/create'
patch 'users/update'
get 'clients/index'
get 'clients/new'
get 'clients/edit'
get 'clients/delete' => 'clients#delete'
get 'clients/create'
patch 'clients/create'
patch 'clients/update'
post '/clients/:client_id/action_items/:id' => 'action_items#destroy'
get 'login', :to => "access#index"
resources :action_items
#/clients/13/action_items
resources :clients do
resources :action_items
end
#get 'home/index'
#get 'home/edit'
#
#get 'home/delete'
#get 'home/show'
root 'home#index'
#define, below **, is the URL we named categories/index. It is now localhost:3000/define
#get 'index' => 'questions#index'
#get 'questions/edit'
#get 'new' => 'questions#new'
#get 'questions/delete'
#post 'questions/destroy'
#get 'questions/show'
#post 'create' => 'questions#create'
match ':controller(/:action(/:id))', :via => [:get, :post]
# end
end
Action Items Controller:
class ActionItemsController < ApplicationController
# before_action :get_owner
def index
#action_items = ActionItem.all
#client = Client.find(params[:client_id])
end
def new
#action_items = ActionItem.new
# #action_items_client = #client.action_items.new
#client = Client.find(params[:client_id])
end
def create
# #action_item = ActionItem.new(action_items_params)
# if #action_item.save
# redirect_to(:action => 'show', :id => #action_item.id)
# #renders client individual page
# else
# redirect_to(:action => 'new')
# end
#client = Client.find(params[:client_id])
#action_item_client = #client.action_items.new(action_items_params)
if #action_item_client.save
redirect_to(:action => 'show', :id => #action_item_client.id, :client_id => #client.id)
else
redirect_to(:action => 'new')
end
end
def edit
#action_item = ActionItem.find(params[:id])
end
def update
#action_item = ActionItem.find(params[:id])
if #action_item.update_attributes(action_items_params)
redirect_to(:controller => 'action_items', :action => 'show', :id => #action_item.id)
flash[:notice] = "Updated"
else
render 'new'
end
end
def show
#client = Client.find(params[:id])
#action_item = ActionItem.find(params[:action_item_id])
end
def action_clients
#action_clients = ActionItem.Client.new
end
def delete
#action_item = #client.action_items.find(params[:client_id])
end
def destroy
# #action_items = #client.action_items.find(params[:id]).destroy
# redirect_to(:controller => 'action_items', :action => 'index')
item = clients_action_items.find(params[:client_id])
item.destroy
if params[:client_id]
redirect_to clients_action_items_path(params[:client_id])
else
redirect_to clients_action_items_path
end
end
private
def action_items_params
params.require(:action_item).permit(:purpose, :correspondence_method, :know_person, :contact_name_answer, :additional_notes)
end
# private
# def get_owner
# if params[:client_id].present?
# #owner = user.clients.find(params[:client_id])
# else
# #owner = user
# end
# end
end
Index view from which I am deleting an action item:
<%= link_to('New Action Item', :controller => 'action_items', :action => 'new') %></br>
<ol><% #action_items.each do |list| %>
<li>
Action Item for <%= #client.name %> is: <strong><%= list.correspondence_method %></strong> Client, about:
<strong><%= list.purpose %> </strong></li>
And you created some additional notes: <strong><%= list.additional_notes %></strong></br></br>
-- Crud Actions -- </br>
<%= link_to('New Action Item', :controller => 'action_items', :action => 'new') %></br>
<%= link_to('Edit Action Item', :controller => 'action_items', :action => 'edit', :id => list.id) %></br>
<%= link_to('Show Individual', :controller => 'action_items', :action => 'show', :id => list.id) %></br>
<%= button_to('Delete Action Item', :controller => 'action_items', :action => 'destroy', :id => list.id) %></br>
<h2> new delete </h2>
</br></br>
<% end %></ol>
I have created the foreign key columns in a migration file with a join table called: action_items_clients:
class CreateActionItemsClients < ActiveRecord::Migration
def change
create_table :action_items_clients, :id => false do |t|
t.integer :action_item_id
t.integer :client_id
end
end
end
-New to rails. Please excuse dirty code. What is wrong here? Why the destroy link issues? Why was the destroy link redirecting to show before, and giving me both routing and ID errors?
Thanks for your time.
*** EDIT ****
Rake routes output:
Prefix Verb URI Pattern Controller#Action
users_index GET /users/index(.:format) users#index
users_new GET /users/new(.:format) users#new
users_edit GET /users/edit(.:format) users#edit
users_delete GET /users/delete(.:format) users#delete
users_create GET /users/create(.:format) users#create
PATCH /users/create(.:format) users#create
users_update PATCH /users/update(.:format) users#update
clients_index GET /clients/index(.:format) clients#index
clients_new GET /clients/new(.:format) clients#new
clients_edit GET /clients/edit(.:format) clients#edit
clients_delete GET /clients/delete(.:format) clients#delete
clients_create GET /clients/create(.:format) clients#create
PATCH /clients/create(.:format) clients#create
clients_update PATCH /clients/update(.:format) clients#update
DELETE /clients/:client_id/action_items/:id(.:format) action_items#destroy
login GET /login(.:format) access#index
action_items GET /action_items(.:format) action_items#index
POST /action_items(.:format) action_items#create
new_action_item GET /action_items/new(.:format) action_items#new
edit_action_item GET /action_items/:id/edit(.:format) action_items#edit
action_item GET /action_items/:id(.:format) action_items#show
PATCH /action_items/:id(.:format) action_items#update
PUT /action_items/:id(.:format) action_items#update
DELETE /action_items/:id(.:format) action_items#destroy
client_action_items GET /clients/:client_id/action_items(.:format) action_items#index
POST /clients/:client_id/action_items(.:format) action_items#create
new_client_action_item GET /clients/:client_id/action_items/new(.:format) action_items#new
edit_client_action_item GET /clients/:client_id/action_items/:id/edit(.:format) action_items#edit
client_action_item GET /clients/:client_id/action_items/:id(.:format) action_items#show
PATCH /clients/:client_id/action_items/:id(.:format) action_items#update
PUT /clients/:client_id/action_items/:id(.:format) action_items#update
DELETE /clients/:client_id/action_items/:id(.:format) action_items#destroy
clients GET /clients(.:format) clients#index
POST /clients(.:format) clients#create
new_client GET /clients/new(.:format) clients#new
edit_client GET /clients/:id/edit(.:format) clients#edit
client GET /clients/:id(.:format) clients#show
PATCH /clients/:id(.:format) clients#update
PUT /clients/:id(.:format) clients#update
DELETE /clients/:id(.:format) clients#destroy
root GET / home#index
GET|POST /:controller(/:action(/:id))(.:format) :controller#:action
It seems you are trying to destroy an object using a POST request.
No route matches [POST] "/clients/42/action_items/1"
Did you try a DELETE request?
delete '/clients/:client_id/action_items/:id' => 'action_items#destroy'
You can read further about CRUD (Create, Read, Update, Delete) operations here
Also, can you run rake:routes and post the output here? That will help figure out what routes are actually being generated.
EDIT
So, as you can see from the output of rake:routes there is a LOT of duplication. You basically have three models, User, Client and ActionItems with basic CRUD and one login.
Rake file:
Rails.application.routes.draw do
get 'login', :to => "access#index"
resources :users
resources :action_items
resources :clients do
member do
get :action_items
end
end
root 'home#index'
end
Client and ActionItems have a many-to-many relation. If it was a one-to-many ie many ActionItems belong to only one Client then it would have been better to nest the resources.
To show all action items of a client you only need one extra method in client controller.
Clients Controller:
def show
#client = Client.find(params[:id])
end
def action_items
#list_action_items = #client.action_items
end
Action Items Controller:
#Will list all action_items irrespective of which clients they belong to
def index
#action_items = ActionItem.all
end
#For creating a new action item,
def new
#action_item = ActionItem.new
#You can render a form with dropdown here with Client.all to assign the new action_item to a client
end
def create
#action_item = ActionItem.new(action_items_params)
if #action_item.save
redirect_to(:action => 'show', :id => #action_item.id)
#renders client individual page
else
redirect_to(:action => 'new')
end
end
def edit
#action_item = ActionItem.find(params[:id])
end
def update
if #action_item.update_attributes(action_items_params)
flash[:notice] = "Updated"
redirect_to(:controller => 'action_items', :action => 'show', :id => #action_item.id)
else
render 'new'
end
end
def show
#action_item = ActionItem.find(params[:id])
end
def destroy
#action_item.destroy
flash[:notice] = "Action Item has been deleted."
redirect_to action_items_path
end
I have tried to simplify the structure here. If you want to perform tasks like deleting all action items of a client from the index/list page of all clients, you can define a method destroy_many in the ActionItems controller which takes client_id as argument, queries all action items and deletes them.
You don't need separate ClientActionItem controller/routes.
Also, if you want to continue with nested routes,
try
<%= button_to('Delete Action Item', client_action_item_path(#client.id, list.id), method: :delete) %></br>
The nested route requires two arguments. The first is client.id and second the action_item id.
This should work, but un-tested. I am not sure of your intentions, but I would use a link_to with a class of button personally.
<%= button_to('Delete Action Item', client_action_item_path(#client, list), method: :delete) %></br>
Related
I recently watched the railscast episode #250 Authentication from Scratch (revised) and I have the signup / login / logout actions working. However I am working on creating an action to delete a user from the database, but I am currently experiencing some errors when I try to delete a user.
The users_controller.rb delete / destroy actions look like the following,
def delete
# the below line calls the destroy method / action
self.destroy
end
def destroy
session[:user_id] = nil
# #user = User.find(params[:id])
#user.destroy
# User.find(parmas[:id]).destroy
# the below line didn't delete the current user :(
# #user = User.destroy
redirect_to :controller=>'users', :action => 'new'
end
The error message I'm getting in the browser when I try to delete a user looks like the following.
The page that contains the delete link looks like the following, index.html.erb
<h1>Welcome
<% if current_user %>
<%= current_user.email %>
<% end %>
</h1>
<p>You have <%= current_user.credit %> credits.</p>
<!-- http://stackoverflow.com/questions/5607155/ -->
<%= link_to('Delete your account', :controller => 'users', :action => 'destroy') %>
routes.rb
Rails.application.routes.draw do
# the below generated route is not necessary
# get 'sessions/new'
# delete user route
#get 'delete' => 'users#delete'
# shortened routes, per railscast comment
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
get 'logout' => 'sessions#destroy'
# get 'signup', to: 'users#new', :as 'signup'
# get 'login', to: 'sessions#new', :as 'login'
# get 'logout', to: 'sessions#destroy', :as 'logout'
resources :users
resources :sessions
root to: 'users#new'
# get 'users/new'
# the below line specifies JSON as the default API format
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :users
end
end
It stands to reason you're getting a NoMethodError, since you've never set the #user variable, that line is commented out:
def destroy
session[:user_id] = nil
# #user = User.find(params[:id]) <-- Commenting out this line was your problem
#user.destroy
Changing to
def destroy
session[:user_id] = nil
#user = User.find(params[:id])
#user.destroy
You should be good to go.
EDIT: one thing you'd probably want to do is change from using the old style of link_to, specifying the controller and action, and change to the new style, using route helpers. In this case, you'd use, i believe, link_to 'Delete your account', current_user, :method => :delete, but you can check by running rake routes, where it will list the helpers available based on your routes.rb file.
Well, I think you should make things a bit simpler and start from the dummiest thing, that works. First of all, if you use your controller as a resource, there would not be a delete action there, only destroy.
def destroy
User.find(params[:id]).destroy
session[:user_id] = nil
redirect_to new_user_path
end
P.S. once again, I assume that you have set resources :users in your routes.rb.
If you have a bunch of get|post|put|delete routes instead, just make sure you point the redirect correctly.
I'm getting a strange reaction to my 'destroy' method. I get this error when trying to destroy a project:
Unknown action
The action '5' could not be found for ProjectsController
I figured out when when I change my routes.rb file from resources :projects (plural) to resources :project (singular), the destroy action works as it should (and returns to the index) but then my show method works but update and new methods throw undefined methodprojects_path'` errors. Why is this happening??
class ProjectsController < ApplicationController
def index
#projects = Project.sorted
end
def show
#project = Project.find(params[:id])
end
def new
#project = Project.new
#project_count = Project.count + 1
end
def create
# Instantiate a new object using form parameters
#project = Project.new(project_params)
# Save the object
if #project.save
# If save succeeds, redirect to the index action
flash[:notice] = "Project created successfully."
redirect_to(:action => 'index')
else
# If save fails, redisplay the form so user can fix problems
#project_count = Project.count + 1
render('new')
end
end
def edit
#project = Project.find(params[:id])
#project_count = Project.count
end
def update
#project = Project.find(params[:id])
if #project.update_attributes(project_params)
flash[:notice] = "Project updated successfully."
redirect_to(:action => 'show', :id => #project.id)
else
#project_count = Project.count
render('edit')
end
end
def delete
#project = Project.find(params[:id])
end
def destroy
project = Project.find(params[:id])
project.destroy
flash[:notice] = "Project '#{project.name}' destroyed successfully."
redirect_to(:action => 'index')
end
private
def project_params
params.require(:project).permit(:name, :financing, :visible, :position)
end
end
routes.rb file:
Rails.application.routes.draw do
root :to => 'projects#index'
resources :projects
match ':controller(/:action(/:id))', :via => [:get, :post]
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# Exampl
e resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end
# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable
# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end
Delete.html.erb page:
<% #page_title = "Delete Project" %>
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="project destroy">
<h2>Delete Projects</h2>
<%= form_for(:project, :url => {:action => 'destroy', :id => #project.id}) do |f| %>
<p>Are you sure you want to permanently delete this project?</p>
<p class="reference-name"><%= #project.name %></p>
<div class="form-buttons">
<%= submit_tag("Delete Project") %>
</div>
<% end %>
</div>
[UPDATE]
Another interesting update. I messed around with destroy and changed the controller to:
def delete
#project = Project.find(params[:id])
#project.destroy
end
def destroy
project = Project.find(params[:id])
project.destroy
flash[:notice] = "Project '#{project.name}' destroyed successfully."
redirect_to(:action => 'index')
end
I did this to see if it was an issue with the destroy method. It does destroy the project, and still returns the delete page which causes the same error, but it does destroy it.
Though you are doing a couple of unconventional stuff like having delete.html.erb (objects are deleted from the show view page), I'm going to address your direct question.
you said:
"when I change my routes.rb file from resources :projects (plural) to resources :project (singular), the destroy action works as it should (and returns to the index) but then my show method works but update and new methods throw undefined method projects_path'` errors. Why is this happening??"
you have understand every time you change your routes, you have to modify the helper paths in your views.
example: when you had resources :projects, you helper methods were (run rake db:migrate)
projects_path GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project_path GET /projects/new(.:format) projects#new
edit_project_path GET /projects/:id/edit(.:format) projects#edit
project_path GET /projects/:id(.:format) projects#show
PATCH /projects/:id(.:format) projects#update
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
So at this point, projects_path was working because as you can see above, projects_path is there.
when you changed your routes to resources :project(singular), your helper paths change as well. run rake db:migrate to see them:
project_index_path GET /project(.:format) project#index
POST /project(.:format) project#create
GET /project/new(.:format) project#new
GET /project/:id/edit(.:format) project#edit
GET /project/:id(.:format) project#show
PATCH /project/:id(.:format) project#update
PUT /project/:id(.:format) project#update
DELETE /project/:id(.:format) project#destroy
As you can see the helper path that maps to project#index is project_index_path.
So I'm guessing in your edit.html.erb (or somewhere else) you have the old code: projects_path and so you are getting undefined method projects_path because the helper no longer exist. The correct helper method in this case, is project_index_path.
I'm getting the following error on a page that contains a link to credit/edit an object:
Routing Error
No route matches {:controller=>"connections", :action=>"edit", :id=>nil}
My app has user profile pages (#show action in users_controller.rb) with a link to create or edit an existing "connection" (a relationship between users like Facebook or LinkedIn). If the connection does not exist, the link will send the user to create a new connection. If the connection already exists, the link will send the user to edit the existing connection. My create functionality works fine. However, once the connection has been created, visiting the user page throws the routing error. It clearly does not like my link_to for the edit action.
Here is the link_to on the user page:
<% unless current_user == #user %>
<% if #contact.present? %>
<%= #user.first_name %> is your <%= #connection.description %> (<%= link_to "edit contact", { :controller => 'connections', :action => 'edit', :id => #connection.id} %> )
<% else %>
How do you know <%= #user.first_name %>? (<%= link_to "edit contact", { :controller => 'connections', :action => 'create', :user_id => #user.id }, :method => 'post' %> )
<% end %>
The error also specifically states that :id is set to nil (null). The problem must be here. How can I my app to refer to the correct connection? My instance variable should have done the trick.
Here's the connection controller:
class ConnectionsController < ApplicationController
def index
end
def update
#connection = current_user.connections.find(params[:id])
if #connection.update_attributes(params[:connection])
flash[:notice] = "Contact relationship updated"
render 'activities'
end
end
def edit
#connection = current_user.connections.find(params[:id])
end
def create
##user = User.find(params[:user_id])
#connection = current_user.connections.build(params[:connection])
#user = User.find(params[:user_id])
if #connection.save
flash[:success] = "Contact relationship saved!"
else
render #user
end
end
end
And here's the User controller show action (where the link_to exists):
def show
#user = User.find(params[:id])
#connection = current_user.connections.build(:otheruser_id => #user)
#contact = current_user.connections.where(user_id: current_user, otheruser_id: #user)
end
routes.rb:
authenticated :user do
root :to => 'activities#index'
end
root :to => "home#index"
devise_for :users, :controllers => { :registrations => "registrations" }
resources :users do
member do
get :following, :followers, :posts, :comments, :activities, :works, :contributions, :connections
end
end
resources :works do
resources :comments
end
resources :relationships, only: [:create, :destroy]
resources :posts
resources :activities
resources :reposts
resources :comments do
member do
put :toggle_is_contribution
end
end
resources :explore
resources :connections
Any ideas on how to fix the link_to? Thanks!
EDIT 1: relevant rake routes:
connections GET /connections(.:format) connections#index
POST /connections(.:format) connections#create
new_connection GET /connections/new(.:format) connections#new
edit_connection GET /connections/:id/edit(.:format) connections#edit
connection GET /connections/:id(.:format) connections#show
PUT /connections/:id(.:format) connections#update
DELETE /connections/:id(.:format) connections#destroy
Your problem is in:
#connection = current_user.connections.build(:otheruser_id => #user)
That instantiates a connection object and assigns it to #connection. This object hasn't been saved, therefore it doesn't have an id. Conceptually it's wrong too, how can you edit something that doesn't exist yet? If you want to send the user to create a new connection, Connections#new is what you're after.
My question has to do with mapping to controllers/actions using named routes. I am trying to map '/profile' to 'customers#show'. My routes file looks like this:
root :to => 'pages#home'
## named routes
match "profile" => "customers#show", :as => 'profile'
match 'signin' => 'sessions#new', :as => 'signin'
match 'signout' => 'sessions#destroy', :as => 'signout'
resources :customers do
member do
get 'add_card'
post 'submit_card'
end
end
resources :payments, :only => [:show, :new]
delete 'payments/delete_recurring_payment'
post 'payments/submit_non_recurring'
post 'payments/submit_recurring'
resources :sessions, :only => [:create, :destroy, :new]
Running 'rake routes' gives me this:
root / pages#home
profile /profile(.:format) customers#show
signin /signin(.:format) sessions#new
signout /signout(.:format) sessions#destroy
add_card_customer GET /customers/:id/add_card(.:format) customers#add_card
submit_card_customer POST /customers/:id/submit_card(.:format) customers#submit_card
customers GET /customers(.:format) customers#index
POST /customers(.:format) customers#create
new_customer GET /customers/new(.:format) customers#new
edit_customer GET /customers/:id/edit(.:format) customers#edit
customer GET /customers/:id(.:format) customers#show
PUT /customers/:id(.:format) customers#update
DELETE /customers/:id(.:format) customers#destroy
new_payment GET /payments/new(.:format) payments#new
payment GET /payments/:id(.:format) payments#show
Here is where I'm stumped. When I go to localhost:3000/profile I get a routing error saying this:
No route matches {:action=>"edit", :controller=>"customers"}
This seems odd because there is indeed a route to 'customers#edit' due to my declaring customers as a resource.
However, when I go to 'localhost:3000/signin' I get routed to 'customers#show' which is where I want '/profile' to route to.
It seems like my routes are 'one off' in my routes file but I have no idea why. Any help would be much appreciated.
Thanks
UPDATE 1: Adding my Customers Controller
class CustomersController < ApplicationController
layout "payments_layout"
def show
#customer = current_user
get_account_info(#customer)
get_payment_history(#customer, 10)
end
def new
#title = 'Create an account'
#customer = Customer.new
end
def edit
#customer = current_user
get_account_info(#customer)
end
def update
#customer = current_user
if #customer.update(params[:customer])
redirect_to #customer
else
#card_message = "Use this form to add a credit card to your account. You must have a credit card associated with your account in
in order to make payments on our system."
get_account_info(#customer)
render 'edit'
end
end
def create
#customer = Customer.new(params[:customer])
if #customer.save_and_get_stripe_id
sign_in(#customer)
redirect_to #customer
else
#title = 'Create an account'
render 'new'
end
end
def add_card
#customer = current_user
get_account_info(#customer)
#card_message = "Use this form to add a credit card to your account. You must have a credit card associated with your account in
in order to make payments on our system."
end
def submit_card
#customer = current_user
res = #customer.add_or_update_card(params)
if res
redirect_to #customer
else
#error = res
customer.get_account_info(#customer)
render 'add_card'
end
end
end
Check your views.
Do you have a link to edit your user profile?
It seems like you actually route to the right controller and action but have some links that rake can't route, e.g. you don't pass the ID to your edit_customer_path link.
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.