406 Not Acceptable - xhr image upload to rails - ruby-on-rails-3

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

Related

Sending Information Through Twilio Using Rails

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

Rails 3 send mailer if user attribute is true?

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")

Rails 3.2.2 - Possible to add custom node to as_json

As it's not currently possible for me to use a json templating engine (jbuilder or rabl) as per Rails3 ActionView Template Handlers doesn't work on Production Server I'm wondering how to best change this controller action to include a custom node with as_json (or something else)
class Mobile::AndroidUsersController < SecureMobileUserController
skip_before_filter :authorize, :only => :create
respond_to :json
# POST /mobile_users
# POST /mobile_users.xml
def create
#mobile_user = AndroidUser.find_by_auth(params[:mobile_user][:auth])
unless #mobile_user
#mobile_user = AndroidUser.new(params[:mobile_user])
else
#mobile_user.attributes = params[:mobile_user]
end
respond_to do |format|
if #mobile_user.save
format.json #Add a custom token node here
else
:unprocessable_entity }
format.json { render json: #mobile_user.errors, status: :unprocessable_entity }
:unprocessable_entity }
end
end
end
end
I just need to add a custom node called token that has a value that I get from calling a method on the MobileUser class
:token => MobileUser.next_token
You can change the call to as_json like this:
format.json {render :json => #mobile_user.as_json(:methods => [:next_token])}

Rails3 and Rspec2 controller testing with a namespace

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])

Rails 3.1 respond_to & render_403 problem

I'm not sure what it is. I've just upgraded to Rails 3.1 from 3.0.9 and here's what I get in my specs:
PeopleController edit action should require owner
Failure/Error: response.should render_template("/public/403.html")
expecting <"/public/403.html"> but rendering with <"search/_search_menu_item">
This is all over my specs in various controllers. I also have this code in my AppController:
def render_403
respond_to do |format|
format.html { render :file => "#{Rails.root}/public/403.html", :status => 403, :layout => false }
format.json { render :json => { :error => true, :message => "Error 403, you don't have permissions for this operation." } }
end
end
And this in PeopleController:
def edit
render_403 unless #person.account.id == current_account.id
end
I'm certain that format.html block gets executed (checked it). However the spec expectation fails. Wonder what is going on here.
(search/_search_menu_item is a partial that gets included onto every page, which basically means that the app layout gets rendered here instead.)
Update: I've replaced render_403 in #edit with render(:file => "#{Rails.root}/public/403.html", :status => 403, :layout => false) to see what happens - got the same result.
Ok, figured it out. Possibly not a Rails problem. At least the problem appears only when running the specs.
I've been checking if 403 pages are rendered with this:
response.should render_template("public/403.html")
Doesn't work no more. Replacing it with
response.status.should == 403
fixed the issue.