Rails 3, inserting local IP address into record field - ruby-on-rails-3

I have a Rails 3 application and I would like to add a field to one of my models, the field will be called something along the lines of localip.
How do I add the current local IP to the field?
The standard create method in the controller is like this:
# POST /prescriptions
# POST /prescriptions.json
def create
#prescription = Prescription.new(params[:prescription])
respond_to do |format|
if #prescription.save
format.html { redirect_to #prescription, notice: 'Prescription was successfully created.' }
format.json { render json: #prescription, status: :created, location: #prescription }
else
format.html { render action: "new" }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
Is there some way of inserting it using the create method?

I assume that by "current local IP" you mean IP of the client.
If that's so then you can access this from env hash in your controller action -
current_local_ip = request.env['REMOTE_ADDR']
or
current_local_ip = request.env['REMOTE_HOST']
And if you mean server's ip by current local ip, just look up the value of HTTP_HOST key.

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

Devise: after_sign_in_path_for(resource) not working

I am using devise for user sign up/in. But when user signs in from public accessible pages, devise redirects to root_path.
I tried to use this:
def after_sign_in_path_for(resource)
request.referrer
end
When user tries to sign in, it gives error 'not redirected properly'.
Can anybody tell how to do it?
I believe if I am right what you want to do is override the redirect when a user sign in is to change the following method inside controllers/devise/sessions_controller.rb If you haven't generated devises controllers you generate devise controller. Having done that you will want to have something like the following inside your devise/sessions_controller.rb
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
# respond_with resource, :location => after_sign_in_path_for(resource)
if current_user.role? :administrator
redirect_to dashboard_path
else
redirect_to rota_days_path
end
end
In the above example by default the sessions_controller - create method uses the following: # respond_with resource, :location => after_sign_in_path_for(resource) which I have commented out. By adding a if statement that checks if the current_users role is an administrator. If they then they are redirected to the dashboard page. If not then they are redirected to the rota page.
Alternatively the devise helpers state that you could also do something like:
def after_sign_in_path_for(resource)
stored_location_for(resource) ||
if resource.is_a?(User) && resource.can_publish?
publisher_url
else
super
end
end
Hope this helps.
Update
def create
#hospital_booking = HospitalBooking.new(params[:hospital_booking])
respond_to do |format|
if #hospital_booking.save
format.html { redirect_to :back, notice: 'Photographer Shift was successfully created.' }
format.json { render json: #hospital_booking, status: :created, location: #hospital_booking }
else
format.html { render action: 'new' }
format.json { render json: #hospital_booking.errors, status: :unprocessable_entity }
end
end
end
What happens here is when the hospital_booking is saved it redirects back to the issue page instead of redirecting to another page. Further reading here: api dock- redirect_to

Can't create belongs_to association in controller

I have 2 models Users and Companies. (I'm using Devise for User)
User belongs to Company.
Company has many Users.
My User model includes an client_id column.
At the moment a User signs-up and is directed to the new_company_path where I'd like to create the relationship. (I'd prefer to keep this in 2 steps).
I know my code is wrong here in the companies_controller.rb — but it's where I'm at
def create
#user = current_user
#company = #user.Company.new(params[:company])
respond_to do |format|
if #company.save
format.html { redirect_to root_path, notice: 'Company was successfully created.' }
format.json { render json: #company, status: :created, location: #company }
else
format.html { render action: "new" }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
end
Your problem lies within the line
#company = #user.Company.new(params[:company])
The association from user to company should not be accessed with a capital letter. To get the company associated with a user, you should call it like this:
#user.company
However, if there is no company associated then that method will return nil and you cannot call .new on nil so instead you need to call another method that Rails creates for you called build_company like this:
#company = #user.build_company(params[:company])
The last problem is that since it is the user that belongs to the company, the User instance needs to be updated with the newly created company_id and that will not happen if you only save the company. But when you use the build_company method, it will store the company instance in the association from User so if you call save on the user instead of the company it will create the company and link it to user, like this:
def create
#user = current_user
#user.build_company(params[:company])
respond_to do |format|
if #user.save
format.html { redirect_to root_path, notice: 'Company was successfully created.' }
format.json { render json: #user.company, status: :created, location: #user.company }
else
format.html { render action: "new" }
format.json { render json: #user.company.errors, status: :unprocessable_entity }
end
end
end
Your User model needs a company_id column. Then you can make a form to record that value wherever you like (i.e., on the new_company_path page).

Avoid index url after failing create

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

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