I am sending an email whenever a new record is created in my Rails 3 application.
def new_resource_notification(resource)
#resource = resource
mail(:to => "admin#domain.com", :bcc => User.all.map(&:email), :subject => "New item added")
end
Resource Controller
# POST /resources
# POST /resources.json
def create
#resource = Resource.create( params[:resource] )
#resource.uploadedip_string = request.env['REMOTE_ADDR']
respond_to do |format|
if #resource.save
UserMailer.new_resource_notification(#resource).deliver
format.html { redirect_to #resource, notice: 'Resource was successfully created.' }
format.json { render json: #resource, status: :created, location: #resource }
else
format.html { render action: "new" }
format.json { render json: #resource.errors, status: :unprocessable_entity }
end
end
end
I am using Devise for the user authentication an have added a field called email_subscribe. I've also added a simple checkbox in the user profile view to enable and disable the subscription.
Everything is working correctly at the moment. All users receive an email when a new record is created and users can set and unset their subscription. What I am trying to do now is make the two work together.
How do I only send an email to the users who's email_subscribe is true?
mails = User.where(:email_subscriber => true)
mail(:to => "admin#domain.com", :bcc => mails, subject => "New item added")
Related
I have a Rails 3.2.18 app where I want to ship details of a call (includes name, age, and other information) to a recipient's phone that is already a field in the database.
So for instance a call has a unit assigned, and each unit has a medic (employee) assigned. In the medic model there's a phone field 281-444-555 (example number). What I want to be able to do in the calls controller is to send a SMS on create and update with the details of that call so it arrives on their phone as SMS.
I'm currently doing notifications to phones by using Email to SMS gateway 2813334444#vtext.com (example) using ActionMailer and it works "ok". But I really want to leverage Twilio.
Here's how I'm doing the mailer action to notify the medics of calls on create/update
calls_controller
def create
parse_times!
#call = Call.new(params[:call])
#call.dispatched_by = current_user.username
if #call.save
#call.send_mail(:new_call)
redirect_to calls_path, notice: "Call #{#call.incident_number} was successfully created.".html_safe
else
render :new
end
end
def update
parse_times!
#call = Call.find(params[:id])
respond_to do |format|
if #call.update_attributes(params[:call])
unless #call.call_status == "close"
#call.send_mail(:update_call)
end
format.html { redirect_to #call, notice: "Call #{#call.incident_number} was successfully updated.".html_safe }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #call.errors, status: :unprocessable_entity }
end
end
end
call_mailer
def new_call(medic, call)
#call = call
#medic = medic
mail to: [#medic.medic_sms, #medic.medic_email], :cc => "noreply#company.com", subject: "New Call: #{#call.incident_number}"
end
def update_call(medic, call)
#call = call
#medic = medic
mail to: [#medic.medic_sms, #medic.medic_email], subject: "Updated Call: #{#call.incident_number}"
end
call model (mailer method)
def send_mail(mail_type)
units.each do |unit|
CallMailer.send(mail_type, unit.incharge, self).deliver
CallMailer.send(mail_type, unit.attendant, self).deliver
end
end
end
This is working just fine for mailing the phones and emails of the medics, but I would like to add something similar using Twilio where I can ship the call details to them via SMS in the create and update action.
If anyone can point me in the right direction, I'd appreciate it. I have a Twilio account already and would like to put it to good use.
Update 08/03/14
I think I figured this out and got it working in a basic fashion. But I'd like to see if there's someway to cleanly pass #call object data into the :body => section. Right now I'm having to iterate over the specific fields I want to send (which are about 10 different fields). It would be nice if I could create a partial or template and pass it to :body => similar to how ActionMailer works. Any thoughts?
calls_controller.rb (working)
def update
parse_times!
#call = Call.find(params[:id])
respond_to do |format|
if #call.update_attributes(params[:call])
unless #call.call_status == "close"
unless #call.unit_ids.empty?
send_sms
end
#call.send_mail(:update_call)
end
format.html { redirect_to #call, notice: "Call #{#call.incident_number} was successfully updated.".html_safe }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #call.errors, status: :unprocessable_entity }
end
end
end
private
def send_sms
account_sid = 'AC5CCCCC'
auth_token = 'ATTTTT'
#client = Twilio::REST::Client.new account_sid, auth_token
#client.account.messages.create(
:from => '2814084444',
:to => #call.units.first.incharge.medic_phone,
:body => "incident_number #{#call.incident_number} patient name #{#call.patient_name}"
)
#client.account.messages.create(
:from => '2814084444',
:to => #call.units.first.attendant.medic_phone,
:body => "incident_number #{#call.incident_number} patient name #{#call.patient_name}"
)
end
end
Ok, I have this figured out now. I needed to do string interpolation in the :body element for Twilio to send the information out. Here is my final code and it's working and updated with a conditional to only fire Twilio if certain conditions are met.
calls_controller.rb
def update
parse_times!
#call = Call.find(params[:id])
respond_to do |format|
if #call.update_attributes(params[:call])
if !(#call.call_status == "close") && !(#call.unit_ids.empty?)
send_update_sms
#call.send_mail(:update_call)
end
format.html { redirect_to #call, notice: "Call #{#call.incident_number} was successfully updated.".html_safe }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #call.errors, status: :unprocessable_entity }
end
end
end
def send_update_sms
account_sid = 'AC5CCCC'
auth_token = 'ATTTT'
#client = Twilio::REST::Client.new account_sid, auth_token
#client.account.messages.create(
:from => '28140844444',
:to => #call.units.first.incharge.medic_phone,
:body => "Updated: #{#call.incident_number}/#{#call.units.map(&:unit_name).join(", ")}/#{#call.patient_name}/#{#call.patient_age}/#{#call.patient_sex.try(:sex)}/#{#call.nature.try(:determinant)}/#{#call.special_equipments.map(&:name).join(", ")}/#{#call.traffic_type}/#{transfer_from_address}/#{transfer_to_address} CHECK EMAIL FOR FULL CALL INFO"
)
#client.account.messages.create(
:from => '2814084444',
:to => #call.units.first.attendant.medic_phone,
:body => "Updated: #{#call.incident_number}/#{#call.units.map(&:unit_name).join(", ")}/#{#call.patient_name}/#{#call.patient_age}/#{#call.patient_sex.try(:sex)}/#{#call.nature.try(:determinant)}/#{#call.special_equipments.map(&:name).join(", ")}/#{#call.traffic_type}/#{transfer_from_address}/#{transfer_to_address} CHECK EMAIL FOR FULL CALL INFO"
)
end
def transfer_from_address
if #call.transferred_from.nil?
#call.transfer_from_other
else
#call.transferred_from.try(:facility_name) + ' ' + #call.transferred_from.try(:facility_address)
end
end
def transfer_to_address
if #call.transferred_to.nil?
#call.transfer_to_other
else
#call.transferred_to.try(:facility_name) + ' ' + #call.transferred_to.try(:facility_address)
end
end
When you create a User in rails through the create action, the url is changed to
http://myapplication.com/users with POST
before being redirected elsewhere. If validation fails, it appears that the above URL is retained. If you then refresh, you end up on the index page (as it's now a GET).
I would expect if validation was failed the url would remain as
http://myapplication.com/users/new
As i don't have an index page, this is causing me problems. Is there a way to resolve this please?
This depends on the logic in the respond_to block in your controller.
This is a typical example of the create action in users_controller.rb:
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
So if the save fails, the new action is rendered again.
In your UsersController, do like this:
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url # save success will return to root page
else
render 'new'
end
end
I'm trying to test a controller with a name space, following is my controller (/admin/sites_controller.rb):
class Admin::SitesController < AdminController
def create
#site = Site.new(params[:site])
respond_to do |format|
if #site.save
format.html { redirect_to(#site, :notice => 'Site was successfully created.') }
format.xml { render :xml => #site, :status => :created, :location => #site }
else
format.html { render :action => "new" }
format.xml { render :xml => #site.errors, :status => :unprocessable_entity }
end
end
end
end
and following is my routes.rb file
namespace :admin do
resources :sites
end
I'm using rspec2 to test my controller and following is my controller spec
describe Admin::SitesController do
describe "POST create" do
describe "with valid params" do
it "creates a new Site" do
expect {
post :create, :site => valid_attributes
}.to change(Site, :count).by(1)
end
end
end
end
But when I run the spec it gives me the following routing error
Admin::SitesController POST create with valid params creates a new Site
Failure/Error: post :create, :site => valid_attributes
NoMethodError:
undefined method `site_url' for #<Admin::SitesController:0xb5fbe6d0>
# ./app/controllers/admin/sites_controller.rb:47:in `create'
# ./app/controllers/admin/sites_controller.rb:45:in `create'
# ./spec/controllers/admin/sites_controller_spec.rb:78
# ./spec/controllers/admin/sites_controller_spec.rb:77
I guess its because of the 'admin' name space I'm using, but how can I fix that?
I'm using
Rails3
Rspec2
Linux
When you namespace the route, you're creating URL and path helpers that look like this:
HTTP Verb Path action helper
GET /admin/sites index admin_sites_path
GET /admin/sites/new new new_admin_site_path
POST /admin/sites create admin_sites_path
GET /admin/sites/:id show admin_site_path(:id)
GET /admin/sites/:id/edit edit edit_admin_site_path(:id)
PUT /admin/sites/:id update admin_site_path(:id)
DELETE /admin/sites/:id destroy admin_site_path(:id)
So you can either use those directly in your code (i.e. redirect_to admin_site_path(#site) ), or you can do something like:
redirect_to([:admin, #site])
I'm following along with railscast 196. I've got two levels of associations. App -> Form -> Question. This is the new action in the form controller.
def new
#app = App.find(params[:app_id])
#form = Form.new
3.times {#form.questions.build }
end
the view is displaying all 3 questions fine and I can submit the form... but nothing is inserted into the database for the questions. Here is my create action
def create
#app = App.find(params[:app_id])
#form = #app.forms.create(params[:form])
respond_to do |format|
if #form.save
format.html { redirect_to(:show => session[:current_app], :notice => 'Form was successfully created.') }
format.xml { render :xml => #form, :status => :created, :location => #form }
else
format.html { render :action => "new" }
format.xml { render :xml => #form.errors, :status => :unprocessable_entity }
end
end
end
Here are the params that are sent to my create method:
{"commit"=>"Create Form",
"authenticity_token"=>"Zue27vqDL8KuNutzdEKfza3pBz6VyyKqvso19dgi3Iw=",
"utf8"=>"✓",
"app_id"=>"3",
"form"=>{"questions_attributes"=>{"0"=>{"content"=>"question 1 text"},
"1"=>{"content"=>"question 2 text"},
"2"=>{"content"=>"question 3 text"}},
"title"=>"title of form"}}`
This shows that the params are being sent correctly... I think. The question model just has a "content" text column.
Any help appreciated :)
Assuming:
You have your form set up properly,
Your server shows your data is being sent to the new action, and
Your model doesn't contain callbacks that are blocking the save,
try changing:
#form = #app.forms.create(params[:form])
to
#form = #app.forms.build(params[:form])
Ok figured it out. Turns out I should have been looking at my console a little more. The error it was hanging up on when trying to insert questions into the db was "Warning: can't mass assign protected attributes :questions_attributes". Adding this into the accessible attributes did the trick.
class Form < ActiveRecord::Base
belongs_to :app
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions
attr_accessible :title, :questions_attributes
end
I am trying to upload an image from iPhone to my working rails application that uses Carrierwave for processing. Do I need to account for the CSRF authenticity token that rails requires?
I have the following in my Titanium app.js file, taken pretty much from their Snapost example code:
xhr.open('POST','http://myapp.com/foos/1/bars');
xhr.send({media:originalImage});
My rails action is very simple:
def create
#bar = #foo.bars.build(params[:bar])
#bar.image = params[:file]
respond_to do |format|
if #bar.save
format.html { redirect_to(#foo, :notice => 'Bar was successfully created.') }
format.json { render :json => #bar, :status => :created }
fotmat.xml { render :xml => #bar, :status => :created }
else
format.html { render :action => "new" }
format.json { render :json => #bar.errors, :status => :unprocessable_entity }
format.xml { render :xml => #bar.errors, :status => :unprocessable_entity }
end
end
end
From my device, I get the 'xhr.onerror' alert describing a timeout when I attempt an upload. My server log is as follows:
Started POST "/foos/1/bars" for ###.###.#.### at 2011-05-01 17:01:33 -0500
Processing by BarsController#create as MULTIPART_FORM
Parameters: {"media"=#<ActionDispatch::Http::UploadedFile:0xabdd968 #original_filename="285050.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"media\"; filename=\"2
85050.jpg\"\r\nContent-Type: image/jpeg\r\n", #tempfile=#<File:/tmp/RackMultipart20110501-32635-olgooh>>, "foo_id"=>"1"}
^[[1m^[[36mSQL (1.9ms)^[[0m ^[[1mSHOW TABLES^[[0m
^[[1m^[[35mFoo Load (0.1ms)^[[0m SELECT foos.* FROM foos WHERE foos.id = 1 LIMIT 1
^[[1m^[[36mSQL (2.6ms)^[[0m ^[[1mBEGIN^[[0m
^[[1m^[[35mSQL (5.9ms)^[[0m ROLLBACK
Completed 406 Not Acceptable in 468ms
You are correct, it is the authenticity token (or lack there of) that is causing the problem. How do I ignore the authenticity token for specific actions in Rails? has more details on how to have it ignored. More details at http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html