Access file selected through a form in Ruby on Rails? - html

I have the following Ruby code which includes a form to select a file:
<%= form_for :import, :url=>{:controller=>"user", :action=>"upload"}, :html => { :multipart => true } do |f| %>
<div class= "field">
<%= f.file_field :import %>
<%= submit_tag 'Import' %>
</div>
Inside my controller I am trying to call the file that the user selected from their local disk.
The below code works when I give it the file:
book = Spreadsheet.open 'c:/myexcel.xls'
But I am not sure how to inside a controller call up the file that was selected from the form.
Please help

Could do this with CarrierWave, see railscast here .
Heres the code to import data from an Excel spreadsheet:
def upload
require 'spreadsheet'
Spreadsheet.client_encoding = 'UTF-8'
file_to_import = params[ :import ][ :import ]
file = FileUploader.new
file.store!(file_to_import)
book = Spreadsheet.open "#{file.store_path}"
sheet = book.worksheet 0
sheet.each 1 do |row|
#user = User.new(:code => row[0], :name => row[1], :status => row[2], :account => current_user.account).save
end
Alternatively for uploading files and retrieving them you could use the 'paperclip' gem (railscast here ).
It is quite old but its a respected gem which is well supported and hasn't changed much.
Hope that helps

Related

Ruby on Rails - No data in Params to save in database

My problem is similar to this question: Ruby on Rails - Data not saved. Index showing blank values
However the strong params match the answers and no data seems to come through.
If I use params.require(:banktransaction).permit(...) I get an error: param is missing or the value is empty
If i remove the require part, a row is added but with no values.
I went through the view and controller and checked my spelling, for the life of me I can't see what I have missed, can anyone point me in the right direction?
controller:
class BankAccountsController < ApplicationController
def delete
end
def destroy
end
def edit
end
def update
end
def index
#bankaccount = BankAccount.all
end
def show
end
def new
#banktransaction = BankAccount.new(:transactionDate => Time.now, :description => params[:description], :credit => params[:credit], :debit => params[:debit])
end
def create
#banktransaction = BankAccount.new(bank_account_params)
if #banktransaction.save
flash[:notice] = "transaction added successfully."
redirect_to(bank_accounts_path)
else
render('new')
end
end
private
def bank_account_params
params.require(:banktransaction).permit(:transactionDate,:description,:credit,:debit)
end
end
View:
<h1>BankAccounts#new</h1>
<p>Find me in app/views/bank_accounts/new.html.erb</p>
<div class="new transaction">
<h2>Create Transaction</h2>
<%= form_for(#banktransaction, :html => {:multipart =>true }) do |f| %>
<%= render(:partial =>'form', :locals=> {:f => f}) %>
<div class="form-buttons">
<%= f.submit("Create Transaction") %>
</div>
<% end %>
</div>
Form partial:
<%= f.label(:transactionDate) %>: <%= f.date_field(:transactionDate) %><br>
<%= f.label(:description) %>: <%= f.text_field(:description) %><br>
<%= f.label(:credit) %>: <%= f.number_field(:credit) %><br>
<%= f.label(:debit) %>: <%= f.number_field(:debit) %><br>
routes:
Rails.application.routes.draw do
resources :bank_accounts do
member do
get :delete
end
end
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
In short, you just permit wrong params key. It's bank_account and your bank_account_params should be
def bank_account_params
params.require(:bank_account).permit(:transactionDate,:description,:credit,:debit)
end
The Rails's form builder will build your params base on model name, not variable name.
Your new action assign a BankAccount instance
def new
#banktransaction = BankAccount.new(:transactionDate => Time.now, :description => params[:description], :credit => params[:credit], :debit => params[:debit])
end
so the form builder will use bank_account as the param key instead of variable name banktransaction

Error: "Template is missing"

I am getting the error:
Template is missing
Missing template customers/search, application/search with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}.
This is happening when I'm trying to make a search bar to search through my existing customers in the database. I think it's happening because I am using a partial '_search.html.erb' but it needs to be a partial and I don't know how to fix this problem.
Here is my customers\ _search.html.erb:
<%= form_tag search_customers_path do %>
<input class = "searchbar" id ="custsearch" name=query" placeholder = "find colleague" type="text">
<% end %>
the html it's being rendered with (in events\new.html.erb):
<div class = "searchbar">
<%= render partial: 'customers/search', :object => #customers, locals:{} %>
</div>
here is my customers controller 'search' method:
def search
#q = "%#{params[:query]}%"
#customers = Customer.where("first_name LIKE ? or last_name LIKE ? ",#q,#q)
render :layout => false
end
and here is my routes file:
root 'pages#home'
get '/main' => 'pages#main'
get '/signup' => 'customers#new'
resources :customers do
collection do
get 'search'
end
end
get '/compose' => 'events#new'
resources :events
I'm not even sure if this search will work, but this is the first hurdle to achieving it. Please help!
Thanks
Your search action looking for customers/search.html.erb but you don't have any. Try create a new file in customers folder with name search.html.erb and paste your below code there:
<div class = "searchbar">
<%= render partial: 'customers/search', :object => #customers, locals:{} %>
</div>
also remove render :layout => false from your search action. If you are sending request in html format.
#punitcse's answer was right:
def create
# this will be looking for customers/search.html.erb
# you have to explicitly define it:
render partial: "search", layout: false
end
This should resolve the error.
Calling the partial in the view is pretty normal:
<%= render partial: "customers/search", object: #object %>
The issue looks like it's caused by your create action, which can be corrected to resolve it.
You just need to modify you controller to something like
def search
#q = "%#{params[:query]}%"
#customers = Customer.where("first_name LIKE ? or last_name LIKE ? ",#q,#q)
render partial: "customers/search", locals: { customers: #customers }, :layout => false
end
In cutomers/_search change to
#customers/_search.html.erb
<%= form_tag search_customers_path, method: :get do %>
<input class = "searchbar" id ="custsearch" name=query" placeholder = "find colleague" type="text">

Rails POST params not accessed in controller

I'm trying to write an application that will have to interact with POST but I'm having issues accessing the parameters. This is not meant to be useful right now but I'm just trying to flash the result of the form. According to google dev tools, the POST parameter is set to 1.
Here's my routes.rb file
devise_scope :user do
put 'users/toggle_activation' => 'users/sessions#toggle_activation'
get 'users/sign_out' => 'users/sessions#destroy'
post 'pages/home' => 'users/sessions#activities'
end
This is the controller in question
def activities
params.permit(:tennis)
current_user.save
flash[:notice] = params[:tennis]
redirect_to root_path
end
This is the form code
<%= form_for :user do |f| %>
<%= f.check_box :tennis %>
<%= f.submit %>
<% end %>
Any help is appreciated.
If you're using "form_for", then the check_box name will result as "user[tennis]", not just "tennis". View source in your browser and you should see this.
Do something like the following in your controller method (although I'm not sure how it will be called with "form_for :user" because your "activities" route isn't in your routes.rb in the code above):
user_params = params.require(:user).permit(:tennis)
flash[:notice] = user_params[:tennis]

"No route matches" : Nightmare with routing rails namespace

I'm geting crazy with a namespace URL that leads to incorrect action 'show' instead of 'new'.
When I'm using this URL : admin/admin_utilisateurs/new
I get this error :
Routing Error
No route matches {:action=>"show", :controller=>"admin/admin_utilisateurs"}
Try running rake routes for more information on available routes.
This is the link_to I'm using in my index page :
link_to 'Nouveau', new_admin_admin_utilisateur_path, :class => 'btn-text btn-dimensions btn-encrusted metal'
These are my rake routes :
root / welcome#index
pub_responsables GET /catalogs/managers(.:format) pub_responsables#index
POST /catalogs/managers(.:format) pub_responsables#create
new_pub_responsable GET /catalogs/managers/new(.:format) pub_responsables#new
edit_pub_responsable GET /catalogs/managers/:id/edit(.:format) pub_responsables#edit
pub_responsable GET /catalogs/managers/:id(.:format) pub_responsables#show
PUT /catalogs/managers/:id(.:format) pub_responsables#update
DELETE /catalogs/managers/:id(.:format) pub_responsables#destroy
new_admin_utilisateur_session GET /admin_utilisateurs/sign_in(.:format) devise/sessions#new
admin_utilisateur_session POST /admin_utilisateurs/sign_in(.:format) devise/sessions#create
destroy_admin_utilisateur_session DELETE /admin_utilisateurs/sign_out(.:format) devise/sessions#destroy
admin_utilisateur_password POST /admin_utilisateurs/password(.:format) devise/passwords#create
new_admin_utilisateur_password GET /admin_utilisateurs/password/new(.:format) devise/passwords#new
edit_admin_utilisateur_password GET /admin_utilisateurs/password/edit(.:format) devise/passwords#edit
PUT /admin_utilisateurs/password(.:format) devise/passwords#update
cancel_admin_utilisateur_registration GET /admin_utilisateurs/cancel(.:format) admin_utilisateurs/registrations#cancel
admin_utilisateur_registration POST /admin_utilisateurs(.:format) admin_utilisateurs/registrations#create
new_admin_utilisateur_registration GET /admin_utilisateurs/sign_up(.:format) admin_utilisateurs/registrations#new
edit_admin_utilisateur_registration GET /admin_utilisateurs/edit(.:format) admin_utilisateurs/registrations#edit
PUT /admin_utilisateurs(.:format) admin_utilisateurs/registrations#update
DELETE /admin_utilisateurs(.:format) admin_utilisateurs/registrations#destroy
admin_utilisateur_confirmation POST /admin_utilisateurs/confirmation(.:format) devise/confirmations#create
new_admin_utilisateur_confirmation GET /admin_utilisateurs/confirmation/new(.:format) devise/confirmations#new
GET /admin_utilisateurs/confirmation(.:format) devise/confirmations#show
admin_utilisateur_unlock POST /admin_utilisateurs/unlock(.:format) devise/unlocks#create
new_admin_utilisateur_unlock GET /admin_utilisateurs/unlock/new(.:format) devise/unlocks#new
GET /admin_utilisateurs/unlock(.:format) devise/unlocks#show
admin_admin_utilisateurs GET /admin/admin_utilisateurs(.:format) admin/admin_utilisateurs#index
POST /admin/admin_utilisateurs(.:format) admin/admin_utilisateurs#create
new_admin_admin_utilisateur GET /admin/admin_utilisateurs/new(.:format) admin/admin_utilisateurs#new
edit_admin_admin_utilisateur GET /admin/admin_utilisateurs/:id/edit(.:format) admin/admin_utilisateurs#edit
admin_admin_utilisateur GET /admin/admin_utilisateurs/:id(.:format) admin/admin_utilisateurs#show
PUT /admin/admin_utilisateurs/:id(.:format) admin/admin_utilisateurs#update
DELETE /admin/admin_utilisateurs/:id(.:format) admin/admin_utilisateurs#destroy
For info, I'm using Devise on a users table which I called "admin_utilisateurs".
Devise is working great with options : :database_authenticatable, :confirmable, :recoverable, :registerable, :trackable, :timeoutable, :validatable, :lockable
The point is that I setup another controller for admin purpose on the admin_utilisateurs table.
So here it is my config/routes.rb
root :to => 'welcome#index'
resources :pub_responsables, :path =>'/catalogs/managers'
devise_for :admin_utilisateurs, :controllers => {:registrations => 'admin_utilisateurs/registrations'}
namespace :admin do
resources :admin_utilisateurs
end
So my admin controller is located in app/controllers/admin/admin_utilisateurs_controller.rb
Here is the action of my 'new' controller's action :
class Admin::AdminUtilisateursController < ApplicationController
before_filter :authenticate_admin_utilisateur!
...
def new
#admin_utilisateur = AdminUtilisateur.new
respond_with(#admin_utilisateur)
end
...
end
The view for that controller are located in app/view/admin/admin_utilisateurs/
But the issue is really connected to the route because the other path for 'show', 'edit' and 'update' are working properly.
And if I delete my controller app/controllers/admin/admin_utilisateurs_controller.rb, Rails is not complaining about missing controller, she's still complaining about the "no route for show action".
I'm really lost. Could anyone advise please ?
Thanks in advance
===== UPDATE 1 =====
Here it is the log related to my URL request :
Started GET "/admin/admin_utilisateurs/new" for 127.0.0.1 at 2012-10-25 12:55:05 +0200
Processing by Admin::AdminUtilisateursController#new as HTML
Rendered shared/_main_title.html.haml (0.4ms)
Rendered admin/admin_utilisateurs/_form.html.haml (17.2ms)
Rendered admin/admin_utilisateurs/new.html.haml within layouts/application (31.7ms)
Completed 500 Internal Server Error in 45ms
ActionController::RoutingError (No route matches {:action=>"show", :controller=>"admin/admin_utilisateurs"}):
app/views/admin/admin_utilisateurs/_form.html.haml:1:in `_app_views_admin_admin_utilisateurs__form_html_haml___780348754_85631840'
app/views/admin/admin_utilisateurs/new.html.haml:9:in `_app_views_admin_admin_utilisateurs_new_html_haml__296364877_85537950'
app/controllers/admin/admin_utilisateurs_controller.rb:51:in `new'
It seems that it is properly routed but then there is a problem in the view.
I retried to remove the controller file admin_utilisateurs_controller.rb but this time restart my web server (sudo service apache2 restart) and the error was different.
I got this time a "Routing error uninitialized constant Admin::AdminUtilisateursController".
So this confrim there is an issue in my view...
digging deeper...
OK, I found the issue.
The issue was coming from my partial form view which I use for my 'edit' action and for my 'new' action : /app/views/admin/admin_utilisateurs/_form.html.haml
= form_for #admin_utilisateur, :url => admin_admin_utilisateur_path, :html => {:class => "formulaire-standard"} do |f|
= render :partial => 'shared/error_message', :locals => { :element => #admin_utilisateur, :debut_erreur => 'Cet utilisateur ne peut ĂȘtre enregistrĂ©'}
.groupe-champs
.champ
= f.label :nom
= f.text_field :nom, :class => 'input-width-8-col', :required => 'required'
.champ
= f.label :prenom
= f.text_field :prenom, :class => 'input-width-5-col', :required => 'required'
.champ
= f.label :telephone
= f.telephone_field :telephone, :class => 'input-width-5-col', :required => 'required'
.champ
= f.label :mobile
= f.telephone_field :mobile, :class => 'input-width-5-col'
.champ
= f.label :email
= f.email_field :email, :class => 'input-width-8-col', :required => 'required'
.groupe-champs
= render :partial => 'shared/checkboxes_admin_utilisateur', :locals => { :resource => #admin_utilisateur }
.groupe-champs
.champ-1
= f.check_box :approved
.champ-5
= f.label :approved
.checkbox-explication
= t('activerecord.attributes.admin_utilisateur.explanations.active')
.separator
.groupe-actions
= f.submit 'Enregistrer', :class => 'btn-text btn-dimensions btn-encrusted metal'
= link_to 'Annuler', admin_admin_utilisateur_path, :class => 'btn-text btn-dimensions btn-encrusted metal'
I was using the form_for tag incorrectly. Because my form is used within a namespace, I must add the namespace into its arguments, and remove the :url option because otherwise this form will only work with the 'edit' action :
= form_for [:admin, #admin_utilisateur], :html => {:class => "formulaire-standard"} do |f|
This code lets Rails guess what path to use wether it's for a new record or to edit an existing record. So I don't need to specify the :url and the :method.
The second mistake was (a classical one) the link_to at the bottom of the form.
I forgot the 's' at the end of the route helper (admin_admin_utilisateurSSSS_path):
= link_to 'Annuler', admin_admin_utilisateurs_path, :class => 'btn-text btn-dimensions btn-encrusted metal'
The moral of the story :
ALLWAYS CHECK YOUR /log/development.log FILE ! ;-)

Trying to create an email signup form but get undefined method `model_name' for NilClass:Class

I've been staring at this for a while and Google hasn't helped much so I'm turning to you guys for help. This should be a pretty simple fix.
The goal of the code is to take an email address from a sign up field and place it in the database.
I think most of what I need is there but I'm getting this error:
undefined method model_name for NilClass:Class
My home.html.erb file contains the following:
<%= form_for(#signup) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit "Enter" %>
</div>
<% end %>
The model contains this:
class Signup < ActiveRecord::Base
attr_accessible :email
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates(:email, :presence => true,
:length => {:maxiumum => 40},
:format => {:with => email_regex})
end
The controller contains:
class SignupController < ApplicationController
def show
end
def new
#signup = Signup.new
end
def create
#signup = Signup.new(params[:id])
if #signup.save
else
render 'new'
end
end
end
The problem is most likely because of an instance variable that you're using in your form_for not being set to an ActiveRecord object. It appears that you are setting it correctly in your "new" action, but it's not clear that you're rendering the correct template since you mention the form being in "home.html.erb"?
Either way, ensure that whatever you're using in the form_for is set to a valid ActiveRecord object and your problem may be solved.
In addition, you may want to change your create action to use all the params from the form:
#signup = Signup.new(params[:signup])
Add this to the home action in the pages controller:
#signup = Signup.new
The reason for the error is that you are using #signup in your form, but you didn't define it in your show controller action.