When the user clicks on 'send invoice', the invoice show link is sent to the client's email. However, I get this error each time I click on send
"undefined method `id' for nil:NilClass"
Email message view
<h3>Hi <%= #client.try(:first_name) %></h3>
<p>Click the link below to view invoice</p>
<%= link_to 'INVOICE', edit_invoice_url(#invoice.id) %>
User mailer controller
def show
#user=current_user
#client=Client.find_by(params[:client_id])
#invoice = #client.invoices.find_by(id: params[:id])
end
def update
#user=User.find_by(params[:user_id])
#client = Client.find_by(params[:client_id])
#invoice = Invoice.find_by(params[:qty])
if #invoice
UserMailer.invoice_mail(#client).deliver
flash[:change_pass] = "Invoice sent successfully!"
redirect_to client_path(#user.company_name)
end
end
Send invoice link
<%= link_to 'send', invoice_path(#invoice), method: :patch %>
Maybe it's because find_by finder require an attribute for right SQL query.
And if you want to find instance by id - you have to use find method.
For example:
> Box.find_by(3)
=> Box Load (3.1ms) SELECT "boxes".* FROM "boxes" WHERE (3) LIMIT 1
PG::DatatypeMismatch: ERROR: argument of WHERE must be type boolean, not type integer
and Box.find_by(id: 3) will return an object (if exist) like Box.find(3)
Related
I am trying to create a destination, but it keeps telling me in my browser that 'name' is nil when it redirects redirects to my 'show' view.
Error I receive
undefined method `name' for nil:NilClass
Here are my controller actions for new, create, and show:
def show
#destination = Destination.find_by(id: params[:id])
end
def new
#destination = Destination.new
end
def create
#destination = Destination.create(dest_params)
redirect_to user_destination_path(current_user, #destination.id )
end
private
def dest_params
params.require(:destination).permit(:name,:user_id)
end
My new form where I enter the name of the destination:
<h2>Add a destination</h2>
<div>
<%= form_for #destination do |f|%>
<%= f.label :name %>
<%= f.text_field :name %><br>
<%= f.submit %>
<% end %>
</div>
here is my read/show view:
<h3>Added destination</h3>
<div>
<p><%= #destination.name %></p>
</div>
Before all this I was getting missing required keys [:id] errors, but I seemed to fix that but for some reason I suspect that might have something to do with the issue I am having now. Let me know if you are able to spot the issue
Updated Error
No route matches {:action=>"show", :controller=>"destinations", :id=>nil, :user_id=>"1"}, missing required keys: [:id]
The main problem here is a total lack of error handling. You're not checking at all if the user provided valid input or if the record was even saved in your create method.
def create
#destination = Destination.create(dest_params)
redirect_to user_destination_path(current_user, #destination.id )
end
If the record is not saved for example due to a failed validation #destination.id is nil.
In your show method you're using find_by instead of find which just lets the error slide instead of raising a ActiveRecord::RecordNotFound error.
Your controller should actually look like:
class DestinationsController
def show
# will raise if the record is not found and return a 404 not found response
# instead of just exploding
#destination = Destination.find(params[:id])
end
def new
#destination = Destination.new
end
def create
# never just assume that the record is created unless you want
# to get kicked in the pants.
#destination = Destination.new(dest_params)
if #destination.save
# this route really does not need to be nested.
# see https://guides.rubyonrails.org/routing.html#shallow-nesting
redirect_to user_destination_path(current_user, #destination)
else
# re-render the form with errors
render :new
end
end
private
def dest_params
params.require(:destination).permit(:name,:user_id)
end
end
I am trying to create a custom form_for where I check if the record exists in the table or not. I've done tons of research but haven't come up with anything useful.
My current approach is to create a simple search form and display all similar records. However, that's not what I am looking for. Ideal scenario would be:
Get record's name from form_for
Check if this record present
If present - redirect to one page. If not - redirect to another page
My controller:
def validate_name
#room = Room.new
name = params[:name]
if name != nil
puts "Redirect to page A"
else
puts "Redirect to page B"
end
end
The problem here is that whenever the user comes to the page it automatically triggers the code above. My goal is to create a form validation that tries to find the exact record and then redirect based on if else condition.
Current form_for:
= form_for(Room.new, url: name_room_path, method: :get, action: :validate_name) do |f|
= f.text_field :name
= f.submit
I am sure that my form is incorrect too because I got lost. I found ways to create custom forms but can't figure out how to trigger database check based on the user's input.
PS: these are not new or update actions.
Thank you for your help and time.
Try this:
class RoomsController < ActionController::Base
def validate_name
if params[:name] && Room.where(name: params[:name]).last.present?
puts "Redirect to page A"
elsif params[:name] && Room.where(name: params[:name]).last.nil?
puts "Redirect to page B"
end
end
end
in routes.rb:
get '/rooms/validate_name', to: 'rooms#validate_name'
in view:
<%= form_tag(rooms_validate_name_path, :method => :get )do %>
<%= text_field_tag :name %>
<%= submit_tag %>
<% end %>
I have a page where users can enter email if they can't remember their login page to their subdomain url, but I am not able to set it up correctly.
I have an Account table in the public tenant with email table. And I receive this error: undefined local variable or method `account' for #
Here's what I have on the search page
find_login.html.erb:
<div class="form-inputs">
<%= form_tag(find_login_path, :method => "get") do %>
<%= text_field_tag :search, params[:search], placeholder: "Email Address", class: "form-control" %>
<%= submit_tag "Continue", :name => nil, class: "btn btn-default" %>
<% end %>
</div>
accounts_controller.rb:
def find_login
#accounts = Account.find_by_email(params[:search].to_s.downcase)
unless #accounts.nil?
flash[:success] = "Email found! An email has been sent."
UserMailer.login_recovery(account).deliver
else
flash[:error] = "Email NOT found!" if params[:search] && !params[:search].empty?
end
end
user_mailer.rb:
def login_recovery(account)
#account = account
mail to: #account.email, subject: 'Your login recocery'
end
You store the found Account in the instance variable #accounts, but you pass a local variable account to the Mailer.
Just change
UserMailer.login_recovery(account).deliver
to
UserMailer.login_recovery(#accounts).deliver
Or as a rewrite of the method:
def find_login
query = params[:search].presence
if query
account = Account.find_by_email(query.downcase)
if account
UserMailer.login_recovery(account).deliver
flash[:success] = "Email found! An email has been sent."
else
flash[:error] = "Email NOT found!"
end
end
end
First let's anlayze this error message :
error: undefined local variable or method `account' for #
It's saying that a variable account is undefined, so let's look at your method :
def find_login
#accounts = Account.find_by_email(params[:search].to_s.downcase)
unless #accounts.nil?
flash[:success] = "Email found! An email has been sent."
UserMailer.login_recovery(account).deliver
else
flash[:error] = "Email NOT found!" if params[:search] && !params[:search].empty?
end
end
In ruby, # denote instance variables and a normal variable does not have any special symbol.
So your checking if an account exist with #accounts = Account.find_by_email(params[:search].to_s.downcase). Note that you're using #accounts to store the result of your query!
Next thing you do, you check if #accounts is nil. Everything is good so far. Your account, if found, will be store in that variable.
Now, you call login_recovery with account as parameter. account is different from #accounts since it's a normal variable and does not have the same name. That's where the error is thrown.
As #spickermann said in his answer, use #accounts.
I wanted to add a step-by-step explanation.
I've been trying to implement the code from this question: Send an email manually of a specific page in rails app
The only difference is that I need to fetch the email address from my model. This is usually no problem when sending emails from models.
UserMailer.report(self).deliver
But I want to click on a button in the show view of my record.
I need to manually send out emails using the details of the record in the email.
Maybe there is a better approach than using an extra controller for this?
# app/mailers/user_mailer.rb
class UserMailer < ActionMailer
def report(thing)
#thing = thing
mail :to => thing.email, :from => 'you#example.com',
:subject => 'that report you want'
end
end
# app/views/user_mailer/report.html.erb
<h1>Report</h1>
<p>Here is your <% #thing.customer_id %></p>
# app/controllers/reports_controller.rb
def create
UserMailer.report(#thing).deliver
flash[:notice] = 'report sent!'
redirect_to root_path # or wherever
end
# in a view
<% form_tag(reports_path(#thing), :method => :post) do %>
<% submit_tag 'send report email' %>
<% end %>
I'm returning null with the code above:
ArgumentError (wrong number of arguments (0 for 1)):
app/controllers/reports_controller.rb:3:in `create'
Create is a post request in rails, you cannot pass parameter like this you need to fetch from params. I'm seeing you are giving it a parameter which is wrong.
Secondly you are doing #thing = thing and then you are sending thing (without #) to report method of UserMailer which is also wrong, it would be be nil in report method. you should do UserMailer.report(#thing).deliver after #thing is an object which has email
I'm trying to pass the id of the user currently signed in into a form rendered by the partial below
<%= render :partial=>'new_reservation', :locals=> {:reservation => Reservation.new(:table_id=>#table.id, :user_id=>#user.id)} %>
I'm using Devise and also tried to call current_user but it doesn't seem to be working. Whenever I look at the reservation that was created I don't see a user id.
Any idea what I am missing
Why are you sending a new ActiveRecord object to your partial?
You'd be better setting an instance variable & sending that as a local:
#controller
#reservation = Reservation.build(table_id: #table.id, user_id: current_user.id)
#view
<%= render partial: "new_reservation", locals: {reservation: #reservation} %>