Rails 3, I need to save the current object and create another - ruby-on-rails

I have
recommendations has_many approvals
Basically a recommendation gets created with an approval. The person who can approve it, comes in and checks an approve box, and needs to enter an email address for the next person who needs to approve (email is an attribute of an approval).
The caveat is that if the current_user has a user_type = SMT, then no more approvals are required. Thats the last approval.
I am using the recommendation/:id/approval/:id/edit action. I think I just need a Class method for the Approval. Something like:
before_save :save_and_create
def save_and_create
Some code that saves the current approval, creates a new one and asks me for the next admins email address, and send that user an email requesting that they approve
end
Any help would be greatly appreciated

# old post
class Recommendation << AR
validate :approval_completed?
def approval_completed?
if self.approvals.last.user.type == "SMT"
return true
else
return false # or a number for needed approvals: self.approvals.count >= 5
end
end
end
# new solution
class Approval << AR
validate :approvals_completed?
def approvals_completed?
if self.recommendation.approvals.last.user.type == "SMT"
return true
else
return false # or a number for needed approvals: self.approvals.count >= 5
end
end
end

I finally figured this one out. I simply created a before_save callback and the following method:
def create_next_approval
next_approval = self.recommendation.approvals.build(:email => self.next_approver_email, :user_id => User.find_by_email(next_approver_email))
next_approval.save if next_approver_email.present? && recently_approved?
end
hope it helps anyone else in my shoes.

Related

Deleting a User relation using Rails Models and Interactors

I have a question regarding the deletion of a User. Note that I'm not using Devise since my app is an API.
What I need to do
So I have a User model, I can delete this User with no issues. The user belongs to many other associations regarding Bank Accounts, Transactions, you name it.
When I delete the User, it's able to be deleted but its associations are not. Note that I'm using soft_deletion which means it gets in an INACTIVE state. And by saying that the "associations aren't being deleted" means that I just need to DISABLE specific associations when the User has been deleted or gets INACTIVE
What I currently have
user.rb model file
class User < ApplicationRecord
has_many :bank_accounts
def soft_deletion!
update!(status: "DELETED",
deleted_at: Time.now)
end
end
delete_user.rb interactor file
module UserRequests
class DeleteUser < BaseInteractor
def call
require_context(:id)
remove_user
context.message = 'user record deleted'
end
def remove_user
user = context.user
context.user.soft_deletion! #<- This is the method I have on my model, which works!
#below I removed all user invites in case there's one
user_invite = UserInvite.joined.where(
"lower(email) = '#{user.email.downcase}'"
)&.first
user_invite&.update(status: "CANCELLED")
return if user.user.present?
user.update!(status: "INACTIVE")
end
end
end
So giving a bit more context of what happened up there. My App is an API, on my frontend I remove the user and it actually works, and so what I need to do next is delete the user AND delete a bank_account that's associated with my user.
What I've been trying to do (This fails so hard, and I need some help )
I honestly don't know how to interact between interactions on Rails, that's the reason of my question here.
delete_user.rb interactor file
module UserRequests
class DeleteUser < BaseInteractor
def call
require_context(:id)
remove_user
soft_delete_transaction_account #method to delete bank account
context.message = 'user record deleted'
end
#since there's an association I believe in adding a method to verify if there's a bank
account.
def soft_delete_bank_account
context.account = context.user.bank_accounts.find_by_id(context.id)
fail_with_error!('account', 'does not exist') unless
context.account.present?
context.account.update!(deleted: true,
deleted_at: Time.now)
end
def remove_user
user = context.user
context.user.soft_deletion! #<- This is the method I have on my model, which works!
context.user.soft_delete_transaction_account #<- Then I add that method here so the bank account can be deleted while the user gets deleted!
#below I removed all user invites in case there's one
user_invite = UserInvite.joined.where(
"lower(email) = '#{user.email.downcase}'"
)&.first
user_invite&.update(status: "CANCELLED")
return if user.user.present?
user.update!(status: "INACTIVE")
end
end
end
ERROR LOG of my code:
NoMethodError - undefined method `soft_delete_bank_account' for #<User:0x00007f8284d660b0>:
app/interactors/admin_requests/delete_user.rb:47:in `remove_user'
app/interactors/admin_requests/delete_user.rb:9:in `call'
app/controllers/admin_controller.rb:18:in `destroy'
I would appreciate your help on this!

Ruby on rails. Callbacks, specifying changed attribute

I'm trying to send emails when a certain attribute changes in my model.
My model has a string which I set to hired reject seen and notseen.
For example, If the attribute gets changed to reject I want to send an email, and if it's changed to hired I want to send a different one.
In my model I have:
after_update :send_email_on_reject
def send_email_on_reject
if status_changed?
UserMailer.reject_notification(self).deliver
end
end
Which sends the email when the status gets changed regardless of what the status is. I don't know how to specify this. I have tried something like:
def send_email_on_reject
if status_changed?
if :status == "reject"
UserMailer.reject_notification(self).deliver
end
end
end
which just doesn't send the email.
I have been searching but cannot find any up to date similar questions/examples.
Thanks in advance.
def send_email_on_reject
if status_changed? && status == "reject"
UserMailer.reject_notification(self).deliver
end
end

Stopping creation of posts unless approved is true

Afternoon All,
I have a model called snippet.rb and I would like only one user to post at a time until approved.
Would I run this as a custom validation or as an after_create in the snippet.rb.
The step process is below:
User creates snippet
Snippet submitted for approval
No other snippets can be created until the previous one has been approved.
Could someone help me or point me in the direction of some documentation on how to do this.
Always appreciate the help. I'm trying to work through this in my head but cannot find anything to help.
in your snippets_controller.rb
before_filter :check_last_snippet, :only => [:create]
private
def check_last_snippet
redirect_to root_path unless Snippet.last.approved?
end
I believe that you should use custom validation.
for example
validate :verify_for_not_approved_snippets
def verify_for_not_aproved_posts
errors.add(:base, "error message") if "your condition here"
end
more detaily you can read at http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#performing-custom-validations
create a method in your user model and call this method before creating snippet
def check_snippet
return true if user.snippets.blank? || (user.snippets.present? && user.snippets.where(approved: true).size > 1)
end
If this method returns true then only user can post snippet again. It may help you.
You can use validate on create,
validate :check_last_snippet_approved, :on => :create
def check_last_snippet_approved
errors.add(:base, "could not add due to last snippet not approved") if !self.last.nil? && self.last.approved == false
end

rails 3: How would I write a link_to for a ActionMailer to a just created object

I have Recommendations has_many Approvals.
When one approval is made, the user provides an email address for the next user who needs to approve.
In my Approval Model
after_save :create_next_approval, :approval_notification
attr_accessor :next_approver_email
def recently_approved?
self.approved_changed? && self.approved?
end
def create_next_approval
#self.recommendations.create :email => self.next_approver_email if next_approver_email.present? && recently_approved?
next_approval = self.recommendation.approvals.build(:email => self.next_approver_email)
next_approval.save if next_approver_email.present? && recently_approved?
end
private
def approval_notification
ApprovalMailer.needs_approval(self).deliver
end
In the create_next_approval method, I am saving the next_approval. I am then sending an email to the next_approver_email address asking them to come approve the recommendation.
I am saving this approval here and I need to link to it in the email being sent out... any ideas?
If I follow you correctly. You need to link to the Approval that you just saved. So this would be self.
In that case something like this would work in your email if you have normal routes setup: <%= link_to "approval link", approval_path(self) %>
Let me know if I'm following correctly.

rails -- track number of user login

I'd like to track how many times a user logs in to my site which is a Rails app. Is there any other call like "created_on or updated_on" that can make a little counter in my model that tracks that kind of info? I'm using restful-authentication currently.
I would add login_count field to your User/Account model. Then change this method in User/Account model:
def self.authenticate(login, password)
return nil if login.blank? || password.blank?
u = find_by_login(login) # need to get the salt
u && u.authenticated?(password) ? u.increase_login_count : nil
end
and add this method to model:
def increase_login_count
self.login_count += 1
self.save
self
end
You could create a column in the user table called login_count or something and then in the SessionsController.create method
if user
user.login_count += 1
user.save(false) #update without validations.
# .... other RestfulAuthentication generated code ....

Resources