I have a mutual friendship model, where one user requests a friendship and creates a model with user_id of current_user and friend_id of the friend.
Then the friend accepts it and creates another model of the inverse.
Now I am trying to send notification upon both cases. The problem is that #friend (current_user as well) in my code seems to be nil or otherwise just not working.
def notify_friend_request
#friend = params[:friend]
#url = 'http://localhost:3000'
#first_name = #friend.first_name
#last_name = #friend.last_name
#email = #friend.email
#sent_user = current_user
#sent_user_first_name = #sent_user.first_name
#sent_user_last_name = #sent_user.last_name
mail(to: #email,
subject: 'You have a new friend request!')
What could be wrong? I'd really appreciate help.
My friendship controller, create method is below. Upon request or acceptance the appropriate mailer method seems to be called (notify_friend_request vs. accept)
def create
#inviting_user = User.find(current_user.id)
#friend = User.find(params[:friend_id])
#friendship = current_user.friendships.build(:friend_id => params[:friend_id])
if #friendship.save
if #friend.friends.include? current_user
UserMailer.with(friendship: #friendship).notify_friend_accept.deliver_later
else
UserMailer.with(friendship: #friendship).notify_friend_request.deliver_later
end
I solved it with this code. Posting a question really cleared up my head:
def notify_friend_request
#friendship = params[:friendship]
#url = 'http://localhost:3000'
#first_name = User.find(#friendship.user_id).first_name
#last_name = User.find(#friendship.user_id).last_name
#sent_user = User.find(#friendship.friend_id)
#sent_user_first_name = #sent_user.first_name
#sent_user_last_name = #sent_user.last_name
#email = #sent_user.email
mail(to: #email,
subject: 'You have a new friend request!')
end
Related
In a webshop I have a booking that needs to know if a booking already exists in the order. I had the whole thing working, but then the details...
...now 'booking on a product' (or in normal English: Adding a product to your shopping-cart) adds a totally new booking on the order list in each case. It oughtn't when this product is already booked once, then it only should alter the quantity.
So easy right? Just one simple if-statement and the whole thing works.
bookings_controller.rb
def create
#order = current_order
# If product has already been booked
if #order.bookings.where(product_id: params[:product_id]).exists?
# Then: Only alter the quantity in the booking.
#booking = #order.bookings.where(product_id: params[:product_id])
#booking.product_quantity = params[:product_quantity]
else
# Else: Make a new booking.
#booking = #order.bookings.new(booking_params)
#product = #booking.product
#booking.product_name = #product.name
#booking.product_price = #product.price
end
#order.sum_all_bookings
#order.save
end
# ...
def booking_params
params.require(:booking).permit(:product_quantity, :product_id)
end
Doesn't seem to work.
How do I make the check in the if-statement?
Or should I go about a whole different route to update the booking?
Edit
I've tried various combinations in this shape after gmcnaughton answer. I get either multiple entries still or no entries at all. This one gives me no entries at all.
bookings_controller.rb
def create
#order = current_order
#booking = #order.bookings.find_or_create_by(product_id: params[:product_id])
product = #booking.product
if #booking.new_record?
#booking.product_name = product.name
#booking.product_price = product.price
else
#booking.product_quantity = params[:product_quantity]
#booking.save
#order.sum_all_bookings
#order.save
end
Should I also control the booking id maybe? But this makes no sense, because in the case of finding an existing booking it should be there already.
Is it maybe that I am firing the bookings through a remote: true form?
Edit 2
Also not working:
bookings_controller.rb
def create
#order = current_order
#booking = #order.bookings.where(product_id: params[:product_id]).first_or_initialize
if #booking.new_record?
#booking.product_id = params[:product_id]
product = #booking.product
#booking.product_name = product.name
#booking.product_price = product.price
else
#booking.product_quantity = params[:product_quantity]
#booking.save
#order.sum_all_bookings
#order.save
end
Edit 3
Maybe this has got something to do with it:
categories_controller.rb / Shop
def index
#categories = Category.all.order(name: :asc)
# Voor het inzien van wat al geselecteerd is.
#order = current_order
# Voor het aanslaan van een nieuwe booking.
#booking = current_order.bookings.new
end
Which basically lays out the whole initial shop. The #booking is there to build the form of every product.
Following worked:
def create
#booking = #order.bookings.find_by(product_id: params[:booking][:product_id])
if #booking
#booking.product_quantity = params[:booking][:product_quantity]
#booking.save
else
#booking = #order.bookings.new(booking_params)
#product = #booking.product
#booking.product_name = #product.name
#booking.product_price = #product.price
end
#order.save
end
Apparently I needed to grab the params, by adding [:booking] like in params[:booking][:product_id]. Anybody knows why?
The idea is right, but I think you're missing a call to .first:
#booking = #order.bookings.where(product_id: params[:product_id])
=> #<ActiveRecord::Relation>
should be:
#booking = #order.bookings.where(product_id: params[:product_id]).first
=> #<Booking>
...otherwise you're updating the relation and not a Booking model. You probably also want to call #booking.save after you modify it.
Separately, ActiveRecord also has first_or_initialize and first_or_create helpers which let you find a matching instance or build/create a new one:
#booking = #order.bookings.where(product_id: params[:product_id]).first_or_initialize
if #booking.new_record?
#product = #booking.product
...other stuff for new record...
else
#booking.product_quantity = params[:product_quantity]
end
#booking.save
I have three models: Employee, User, and Role. Relationship between these classes are employee --- one_to_one -- user and user -- one_to_many -- role.
My create action is working fine with following strong params methods
def employee_params
params.require(:employee).permit(:first_name, :middle_name, :last_name, :email, user_attributes: [:id, role_ids:[]])
end
For update if employee record has no user object, I am instantiating new user, mapping it to employee and calling update by passing string params. However, the update is failing with message:
Failed to save the new associated user
My update method code is
def update
#employee = Employee.find(params[:id])
if params[:employee][:user_attributes] != nil && params[:employee][:user_attributes][:role_ids] != nil && ! params[:employee][:user_attributes][:role_ids].empty?
if #employee.user == nil
#employee.user = User.new
temp_password = Devise.friendly_token.first(8)
#employee.user.is_temp_password = true
#employee.user.password = Devise.friendly_token.first(8)
#employee.user.email = #employee.email
#employee.user.email = params[:employee][:email] if params[:employee][:email]
end
end
respond_to do |format|
if #employee.update(employee_params)
format.json { render json: #employee.as_json}
else
format.json {render :json => #employee.errors.as_json, :status => 422}
end
end
end
I think as the above users suggested, you need to save the new User Object but also I think you should have the User creation code inside of the Employee create since you you would need to auto create it anyways in the update
Not sure if you also aware of helpers blank?, present? but I rewrote your code with that
def update
#employee = Employee.find(params[:id])
if params[:employee][:user_attributes].present? && params[:employee][:user_attributes][:role_ids].present? && params[:employee][:user_attributes][:role_ids].present?
unless #employee.user
user = User.new
#employee.user = user
temp_password = Devise.friendly_token.first(8)
user.is_temp_password = true
user.password = Devise.friendly_token.first(8)
user.email = #employee.email
user.email = params[:employee][:email] if params[:employee][:email]
user.save!
end
end
In my application, I have a twitter and facebook login, however I need to prompt a password and email after they first register with twitter or facebook. I am using omniauth gems and my controller/user model looks like this:
//socials_controller.rb
def create
#render text: request.env['omniauth.auth'].to_yaml and return
#user = User.from_omniauth(request.env['omniauth.auth'])
if(#user.email == nil)
redirect_to patient_login_entry_url(#user)
elsif #user.confirmed
log_in #user
redirect_to #user
else
flash[:danger] = "Bir hata olustu."
redirect_to root_url
end
end
def login_entry
#patient = Patient.find(params[:id])
end
def update_social
#patient = Patient.find(params[:id])
if #patient.update_attributes(user_params)
SendVerificationEmailJob.perform_later #patient
flash[:success] = "Aktivasyon için #{#patient.email} adresinizi kontrol ediniz."
redirect_to root_url
else
flash[:danger] = "Bilgilerinizi kontrol edip tekrar deneyiniz."
redirect_to patient_login_entry_url(#patient)
end
end
and my from_omniauth method is:
//user.rb
has_secure_password
class << self
def from_omniauth(auth_hash)
if exists?(uid: auth_hash['uid'])
user = find_by(uid: auth_hash['uid'])
else
user = find_or_create_by(uid: auth_hash['uid'], provider: auth_hash['provider'], type: 'Patient')
user.location = get_social_location_for user.provider, auth_hash['info']['location']
if auth_hash.provider == 'facebook'
user.avatar = User.process_uri(auth_hash['info']['image'])
user.name = auth_hash['extra']['raw_info']['first_name']
user.surname = auth_hash['extra']['raw_info']['last_name']
user.email = auth_hash['extra']['raw_info']['email']
user.gender = auth_hash['extra']['raw_info']['gender']
elsif auth_hash.provider == 'twitter'
user.avatar = auth_hash['info']['image']
user.name = auth_hash['info']['name']
end
user.url = get_social_url_for user.provider, auth_hash['info']['urls']
user.save!
end
user
end
At the login_entry page, I simply prompt the email and password, and POSTing them to the update_social method.
However, as expected, my app throws the error "Password can't be blank", because has_secure_password validates its presence by default. So, I need to persist it between the requests since I can not save it without a password. How can I achieve this?
I tried to store the created object in session by using to_json method, and turning it into a hash between requests, however this time the profile picture I got from twitter/facebook did not persist (I'm using AWS S3 + Paperclip, the URL persists but there is no such image when I check it from the S3 console) so I think that solution was not good.
When a user registers with twitter I'm trying to add his name, location, etc. to his user record. I think I want to do something like user.build
Here is the controller. This is what happens:
user = User.new
user.apply_omniauth(omni)
if user.save
flash[:notice] = "Logged In!"
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omni.except('extra')
redirect_to new_user_registration_path
end
When a user doesn't exist with twitter, the user is redirected to the registration path where they finish registering. I want to add the extra stuff from twitter to their yet to be saved user account. I can't do it in the user.apply_omniauth(omni) method because that saves to the authentications table.
Any ideas?
Thanks!
You can create a flag in apply_omniauth method to make a decision to save or not.
app/models/user.rb
# def apply_omniauth(omniauth) => def apply_omniauth(omniauth, save_it)
# apply_omniauth with save it flag
def apply_omniauth(omniauth, save_it = false)
case omniauth['provider']
when 'facebook'
self.apply_facebook(omniauth)
end
self.email = omniauth['user_info']['email']
if email.blank ? build_authentications(omniauth, save_it)
end
#build authentications
def build_authentications(omniauth, save_it = false)
auth_params = {: provider = > omniauth['provider'],
: uid = > omniauth['uid'],
: token = > (omniauth['credentials']['token'] rescue nil)
}
if save_it authentications.create!(auth_params)
else authentications.build(auth_params)
end
end
#force to save
def apply_omniauth!(omniauth)
apply_omniauth(omniauth, true)
end
Newly added description: (sorry for not mentioning)
The ApplicationController.current_account is defined as:
class ApplicationController < ActionController::Base
class << self
def current_account
#current_account
end
def current_account=(value)
#current_account = value
end
end
=========
I encountered a strange performance in my current project, which is about session. The strange part is it was normal in Safari but failed in other browsers (includes chrome, firefox and opera).
There is a registration form for input of part of the key information (email, password, etc) and is submitted to an action called "create"
This is the basic code of create action:
#account = Account.new(params[:account])
if #account.save
ApplicationController.current_account = #account
session[:current_account] = ApplicationController.current_account
session[:account] = ApplicationController.current_account.id
email = #account.email
Mailer.deliver_account_confirmation(email)
flash[:type] = "success"
flash[:notice] = "Successfully Created Account"
redirect_to :controller => "accounts", :action => "create_step_2"
else
flash[:type] = "error"
flash[:title] = "Oops, something wasn't right."
flash[:notice] = "Mistakes are marked below in red. Please fix them and resubmit the form. Thanks."
render :action => "new"
end
Also I created a before_filter in the application controller, which has the following code:
ApplicationController.current_account = Account.find_by_id(session[:current_account].id) unless session[:current_account].blank?
For Safari, there is no any problem. But for the other browsers, the session[:current_account] does not exist and so produced the following error message:
RuntimeError in AccountsController#create_step_2
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Please could anyone help me?
1] don't write
ApplicationController.current_account
Just
current_account
2] in your application_controller
def current_account
session[:current_account]
end
3]
ApplicationController.current_account = #account
session[:current_account] = ApplicationController.current_account
session[:account] = ApplicationController.current_account.id
should be
session[:current_account] = #account
session[:account] = #account.id