Ruby / ActionMailer / Saving mail - ruby-on-rails

I am creating a customer support app where clients can create, view, edit and comment support tickets.
I have this portion of the app working fine, but I want to have the data they submit into the ticket form emailed to me.
I have a separate "contact us" form that emails the data to me perfectly, but I want to combine the two forms into one.
It should work like this: client creates ticket, ticket is saved into the database, a copy of the ticket is emailed to me.
I can't figure out how to make all of these actions happen from one form.
Here is my tickets controller:
class TicketsController < ApplicationController
def new
#ticket = Ticket.new
end
def create
#ticket = Ticket.new(ticket_params)
#ticket.save
redirect_to #ticket
end
def show
#ticket = Ticket.find(params[:id])
end
def index
#tickets = Ticket.all
end
def edit
#ticket = Ticket.find(params[:id])
end
def update
#ticket = Ticket.find(params[:id])
if #ticket.update(ticket_params)
redirect_to #ticket
else
render 'edit'
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
redirect_to tickets_path
end
private
def ticket_params
params.require(:ticket).permit(:name, :email, :phone, :help)
end
end
Here is my new ticket view:
<%= link_to "View an Existing Ticket", tickets_path, :class =>'btn btn-danger btn-sm'%>
<h1>New Ticket</h1>
<%= form_for :ticket, url: tickets_path do |f| %>
<p>
<%= f.label "Name:" %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label "Email:" %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :"Phone #:" %>
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :"How can we help?" %>
<p><%= f.text_area :help, :cols=> 38, :rows => 8 %></p>
</p>
<p>
<button type="submit" class="btn btn-danger btn-sm">Submit Ticket</button>
</p>
<% end %>
<p><%= button_to "Back", root_path, :class => "btn btn-danger btn-sm", :method => :get %></p>
Here is my email controller:
class ContactController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
Here is my email view:
<%= form_for #message, :url => contactcreate_path do |form| %>
<fieldset class="fields">
<div class="field">
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :email %>
<%= form.text_field :email %>
</div>
<div class="field">
<%= form.label :subject %>
<%= form.text_field :subject %>
</div>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
</fieldset>
<fieldset class="actions">
<%= form.submit "Send" %>
</fieldset>
<% end %>
Ticket Model:
class Ticket < ActiveRecord::Base
after_create :send_new_ticket_to_email
private
def send_new_ticket_to_email
NotificationsMailer.send_new_ticket(self).deliver
end
end
Notifications Mailer:
class NotificationsMailer < ActionMailer::Base
def send_new_ticket(ticket)
#ticket = ticket
mail(:subject => "HelpDesk: #{message.subject}")
default :from => "HelpDeskApp#ascendstudioslive.com"
default :to => "Support#ascendstudioslive.com"
end
Let me know if there is anything else you would like to see. Basically, I want to have one form that saves a ticket to the database and then emails a copy of it out.
Thank you!

You can create an after_create callback in your Ticket model to e-mail the saved ticket to yourself.
class Ticket < ActiveRecord::Base
after_create :send_new_ticket_to_email
private
def send_new_ticket_to_email
UserMailer.send_new_ticket(self).deliver
end
end
and in your ActionMailer class:
class UserMailer < ActionMailer::Base
def send_new_ticket(ticket)
#ticket = ticket
/* here you configure the variables for your email */
mail(to: your#email.com, subject: 'New ticket...')
end
end
then you will be able to use the #ticket object in your mailer views whatever way you please.

Have you tried this? I don't know if it is going to work, but all the same:
#new_message = NotificationsMailer.new_message(#message)
save_to_db(#new_message) # custom method to write it into your db somehow
#new_message.deliver

Not really sure what a contact is versus a ticket, but, broadly, the way to do what you want is, in your create action:
def create
#message = Message.create(params[:message])) # create will save and validate the message
if #message.valid?
NotificationsMailer.new_message(#message).deliver # #message gets set to
# else...
end

Related

Ruby on Rails: Populate dropdown with two fields of database record

In my database I have a Users table that looks something like:
User_ID Firstname Surname Company
1 Steve Jobs Apple
2 Bill Gates Microsoft
What I am trying to do is make a drop down menu in a form that would allow a user to choose from selecting their name or their company, e.g. when Steve Jobs is logged in he can either select "Steve" or "Apple" in the drop down menu.
What I have tried so far is the following:
<%= f.select :from_name, [session[:user_id],session[:user_id]] %>
Which obviously didn't work because it only returns the user id of the logged in user.
<%= f.select :from_name, [#user.firstname,#user.company] %>
Which gave me the error undefined methodfirstname for nil:NilClass`
My Users controller is as follows:
class UsersController < ApplicationController
before_filter :check_authorization, :except => [:show, :new, :create, :search ]
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
#user.role = "customer"
if #user.save
session[:user_id] = #user.id
# Save a copy of the email address entered by the user into the Accounts table
#account = Account.create(email: params[:user][:primaryemailaddress], user_id: session[:user_id])
redirect_to root_path
else
render 'new'
end
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user
else
render 'edit'
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to users_path
end
private
def user_params
params.require(:user).permit(:title, :firstname, :surname, :housenumber, :street, :city, :postcode, :company, :primaryemailaddress, :password)
end
end
And my _form.html.erb is:
<%= form_for(#email) do |f| %>
<% if #email.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#email.errors.count, "error") %> prohibited this email from being saved:</h2>
<ul>
<% #email.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] %>
</p>
<p>
<%= f.label :From_Email_Address %><br>
<%= f.collection_select :account_id, Account.where(user_id: session[:user_id]),
:id,:email %>
</p>
<p>
<%= f.label :to %><br>
<%= f.text_field :to %>
</p>
<p>
<%= f.label :cc %><br>
<%= f.text_field :cc %>
</p>
<p>
<%= f.label :bcc %><br>
<%= f.text_field :bcc %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :message %><br>
<%= f.text_field :message %>
</p>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm not too sure how to solve this issue, can someone please help.
#BenSmith I guess you are accessing EmailsController. And on that controller's new or edit method there is no #user variable.
In your edit and new method add
#user = User.find(session[:user_id])
undefined method firstname for nil:NilClass
Seems like some how #user is nil
create a helper and check for presence of #user
<%= f.select :from_name, dropdown_values %>
application_helper.rb
def dropdown_values
if #user.present?
[#user.firstname, #user.company]
else
['default', 'values']
end
end
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] if #user.present?%>
</p>
because User.new time create blank object doesn't find username.i hope its will be help you.

Variables not displaying in rails blog post

I'm building a simple blog tool using rails and having trouble with variables displaying from a form. What is most confusing is that the post times are showing correctly, but the title and text aren't coming through.
My new form page looks like:
<h1>New post</h1>
<%= form_for :blog, url: blogs_path do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
The controller is currently:
class BlogsController < ApplicationController
def index
end
def new
end
def create
#blog = Blog.new(post_params[:id])
#blog.save
redirect_to #blog
end
def show
#blog = Blog.find(params[:id])
end
private
def post_params
params.require(:blog).permit(:title, :body)
end
end
And the show page is:
<div id="blog">
<h1>
<%= #blog.title %>
</h1>
<p class="date">
Submitted <%= time_ago_in_words(#blog.created_at) %> ago
</p>
<p>
<%= #blog.body %>
</p>
</div>
Any ideas?
Change:
def create
#blog = Blog.new(post_params[:id])
#blog.save
redirect_to #blog
end
to:
def create
#blog = Blog.new(post_params)
#blog.save
redirect_to #blog
end
The reason why it wasn't working is that you were only trying to savepost_params[:id]. You need to pass the whole param as an argument when creating a new blog post Blog.new(post_params)

Displaying specific info to a logged in user

I am creating a customer service web app for our clients that allows them to submit new customer service tickets, once logged in. I have a login system that I created using the sorcery gem, and I have modified it to accept an additional field: client code.
We are assigning client codes to help prevent unauthorized users from creating accounts.
Upon login, it asks for the information like so:
Name:
Email:
Client Code: (we assign this)
Password:
My question is this, is there a way to only display customer service tickets to clients with the same client code? For example, The "Coca-Cola" clients would only see other "Coca-Cola" tickets and the "Pepsi" clients would only see other "Pepsi" tickets, etc.
Here is my Tickets Controller:
class TicketsController < ApplicationController
before_filter :require_login
def new
#ticket = Ticket.new
end
def create
#ticket = Ticket.new(ticket_params)
if
#ticket.save
redirect_to #ticket
flash[:notice] = "Your Ticket has been submitted. We will contact you very soon!"
else
flash[:notice] = "Something went wrong :("
render 'new'
end
end
def show
#ticket = Ticket.find(params[:id])
end
def index
#tickets = Ticket.all
end
def edit
#ticket = Ticket.find(params[:id])
end
def update
#ticket = Ticket.find(params[:id])
if #ticket.update(ticket_params)
redirect_to #ticket
else
render 'edit'
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
redirect_to tickets_path
end
private
def ticket_params
params.require(:ticket).permit(:name, :email, :phone, :help)
end
end
Here is the Ticket Index View:
<div class="panel panel-default">
<div class="panel-heading">Ticket Queue</div>
<div class="panel-body">
<table class="table">
<tr>
<th>Name</th>
<th>Phone</th>
<th></th>
<th></th>
</tr>
<% #tickets.each do |ticket| %>
<tr>
<td><%= ticket.name %></td>
<td><%= ticket.phone %></td>
<td><%= button_to "View or Edit", ticket_path(ticket), :class => "btn btn-primary btn-sm", :method => :get %></td>
<td><%= button_to "Delete", ticket_path(ticket), :class => "btn btn-primary btn- sm", :method => :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
</div>
Here is the New Ticket View:
<div class="panel panel-info">
<div class="panel-heading">
<div id="wrapper">
<h1 class="panel-title">New Ticket
<div id="first"><%= button_to "Back", root_path, :class => "btn btn-primary btn-sm", :method => :get %></div>
</div>
</h1>
</div>
<div class="panel-body">
<%= form_for :ticket, url: tickets_path do |f| %>
<p>
<%= f.label "Name:" %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label "Email:" %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :"Phone #:" %>
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :"How can we help?" %>
<p><%= f.text_area :help, :cols=> 38, :rows => 8 %></p>
</p>
<p>
<button type="submit" class="btn btn-primary btn-sm"><span class="glyphicon glyphicon-envelope"></span> Submit Ticket</button>
</p>
<% end %>
</div>
</div>
Here is the User Model:
class User < ActiveRecord::Base
authenticates_with_sorcery!
validates :password, length: { minimum: 3 }
validates :password, confirmation: true
validates :password_confirmation, presence: true
validates :code, inclusion: { in: %w(Client1, Client2), message: "Please enter a valid Client Code", :allow_nil => false}
validates :email, uniqueness: true
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
Here is the New User View:
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label "Client Code" %><br />
<%= f.text_field :code %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here is the User Controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
skip_before_filter :require_login, only: [:index, :new, :create]
# GET /users
def index
#users = User.all
end
# GET /users/1
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
def create
#user = User.new(user_params)
if #user.save
redirect_to(:users, notice: 'User was successfully created')
else
render :new
end
end
# PATCH/PUT /users/1
def update
if #user.update(user_params)
redirect_to #user, notice: 'User was successfully updated.'
else
render :edit
end
end
# DELETE /users/1
def destroy
#user.destroy
redirect_to users_url, notice: 'User was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :code)
end
end
Let me know if you need to see anything else, thank you!
From your example, I would think Users would have an additional database layer:
class User < ActiveRecord::Base
belongs_to :company
has_many :tickets, through: :companies
end
class Company < ActiveRecord::Base
has_many :users
has_many :tickets
end
class Ticket < ActiveRecord::Base
belongs_to :company
end
Then you can easily display tickets associated with each company

sign up and create new object at the same time

i'm new in Ruby on Rails.
I was trying to register a new user with devise and at the same time, create a new Company object. The association between them : User belongs to Company. Company has many users. I tried to make it based on this link : http://railscasts.com/episodes/196-nested-model-form-part-1?view=asciicast, but it didnt work. it said : "undefined method for Company", which is Company doesnt have email attribute.
and in sign up form, i only put email attribute for user
<div class="title"><%= t('.signup') %></div>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="control-group"><%= f.label :email, t('.email') %>
<%= f.email_field :email %></div>
<div class="control-group"><%= f.label :password, t('.password') %>
<%= f.password_field :password %></div>
<div class="control-group"><%= f.label :password_confirmation, t('.password_confirmation') %>
<%= f.password_field :password_confirmation %></div>
<%= f.fields_for :company_attributes do |f_company| %>
<div class="control-group"><%= f_company.label :name, t('.company_name') %>
<%= f_company.text_field :name %></div>
<% end %>
<div class="buttons"><%= f.submit t('.signup'), class:"btn btn-primary" %><br>
<%= render "links" %></div>
<% end %>
updated
Company controller :
class CompaniesController < Devise::RegistrationsController
def new
#company = Company.new
#user = #company.users.build
end
def create
#company = Company.new(params[:company])
#user = User.create(params[:user].merge(company_id:company.id))
if #company.save
redirect_to "/"
else
render 'users/sign_up'
end
end
end
User Controller :
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to users_path
else
render 'users/new'
end
end
I would really appreciate any idea and any help. Thanks in advance
In your case, since you are only interested in receiving the company_name I'd simplify it and submit the company_name via a text_field_tag.
In other words, I would replace:
<%= f.fields_for :company_attributes do |f_company| %>
<div class="control-group"><%= f_company.label :name, t('.company_name') %>
<%= f_company.text_field :name %></div>
<% end %>
With this
<%= text_field_tag 'company_name', {placeholder:"Enter here the name of your company",class:"form-control"} %>
This would submit the name to the UsersController, and you could access it with params[:company_name] so the controller would look like this:
Users controller:
def new
#user = User.new
end
def create
#user = User.create(params[:user])
#Create a company via 'user<->company' association using 'company_name'
#company= #user.company.create(name: params[:company_name])
if #user.save
redirect_to users_path
else
render 'users/new'
end
end

Rails nested form, attributes not getting passed

So I have a Conversation model, which has_many messages. I'm trying to create a new message when I create a conversation. Here's my ConversationsController:
class ConversationsController < ApplicationController
before_filter :authenticate_user!
def new
recipient = User.find(params[:user])
#conversation = Conversation.new(from: current_user, to: recipient)
#conversation.messages.build(from: current_user, to: recipient)
end
def create
#conversation = Conversation.create(params[:conversation])
redirect_to #conversation
end
end
And here's my form (conversations/new.html.erb):
<%= form_for #conversation do |f| %>
<%= f.fields_for :messages do |g| %>
<%= g.label :subject %>
<%= g.text_field :subject %>
<%= g.label :content %>
<%= g.text_field :content %>
<% end %>
<%= f.submit "Send" %>
<% end %>
The problem: when I submit the form, the conversation's message gets saved, but the to and from fields that I specified as parameters in build are not saved (they are nil). However, the subject and content fields filled out in this form are saved just fine.
I've done a little bit of digging... if I do a puts on #conversation.messages in the new action, or in the new.html.erb, the message seems to have to and from. It's only when the message reaches the create action do those fields disappear.
UPDATED:
class ConversationsController < ApplicationController
before_filter :authenticate_user!
def new
recipient = User.find(params[:user])
#conversation = Conversation.new(to: recipient)
#conversation.messages.build
end
def create
#conversation = current_user.conversations.build(params[:conversation])
# Set all the attributes for conversation and messages which
# should not be left up to the user.
#conversation.to = current_user
#conversation.messages.each do |message|
message.to = #conversation.to
message.from = #conversation.from
end
redirect_to #conversation
end
end
<%= form_for #conversation do |f| %>
<%= f.hidden_field :recipient %>
<%= f.fields_for :messages do |g| %>
<%= g.label :subject %>
<%= g.text_field :subject %>
<%= g.label :content %>
<%= g.text_field :content %>
<% end %>
<%= f.submit "Send" %>
<% end %>
You may still want to validate the recipient in your Conversation model.

Resources