Rails how to update instance variable value at every execution - ruby-on-rails

I need to solve two problems with this piece of code inside a model. As far as I figured out the values in instance variables will be saved the first time it is executed, but since it is date and time it should be executed every time the method is called. How to go around that? Second, How can I access the instance variables inside the downtime method?
def entry_time
#day = DateTime.now.wday
#date = Date.current
#time = DateTime.now.hour
if downtime
errors.add(:_, "Please submit your request during working hours")
end
end
def downtime
holidays || #time < 9 || #time > 17 || #day == 6 || #day == 0
end

AJAX will rescue you in this case. You need to constantly call the server, and update it with the latest values. So it's up to you how frequent you would like to hit the server. You can use setTimeout to repeat a function, and achieve what you desire.
Regarding the second question, when you append # with a variable, it becomes available to the whole class, and you can access it everywhere. So yes, you can access all the instance variables in downtime the way you access them in any other method.

Try this:
def entry_time
#day = DateTime.now.wday
#date = Date.current
#time = DateTime.now.hour
if downtime(#day,#date,#time)
errors.add(:_, "Please submit your request during working hours")
end
end
def downtime(day,date,time)
holidays || time < 9 || time > 17 || day == 6 || day == 0
end

Related

Limit requests that users can send to 3 every 30 days. Ruby on Rails

I am learning to program and I am trying with Ruby on rails. I would like to restrict one functionality that allows users to send me introduction requests (3 introduction request per 30 days). I am not sure if I have to create a method first, for example:
def month
where("created_at <?", Date.today - 30.days))
end
I don't know if that method is correct and if I can integrate it within this piece of code:
def create
#introduction = CompanyIntroduction.create(intro_params)
if current_user #Admin can edit the user name and email
#introduction.user = current_user
#introduction.user_name = current_user.full_name
#introduction.user_email = current_user.email
end
if #introduction.save
flash[:success] = "Thank you. Your request is being reviewed by TechIreland."
else
flash[:error] = #introduction.errors.full_messages
end
redirect_back(fallback_location: user_companies_path)
end
You're close. You have the time comparison backwards though, and the method (assuming it's on your model) should be a class method or a scope.
scope :in_the_last_month, -> { where('created_at > ?', Date.today - 30.days) }
# or more elegantly
scope :in_the_last_month, -> { where(created_at: 30.days.ago..) }
Then in the controller you can check how many requests were made recently.
if CompanyIntroduction.in_the_last_month.count >= 3
# give some error
else
# continue
end
This code is simple enough that you don't actually need to make it into a method, just the code in the controller is probably fine.
if CompanyIntroduction.where(created_at: 30.days.ago..).count >= 3

How do I get the desired output in my view?

I need some assistance, I'm working on creating a weekly schedule. But my output is not displaying the desired criteria. Everything is displaying, but it's not assigning the start and end time properly and I can't figure out why. I'm new to ruby so any help would be greatly appreciated. Below is the method from my control and the output in the view.
def generate_schedule
logger.info #generate_schedules
# create hash for view
#generate_schedules = Hash.new
# find current required schedule
schedule_structure = Availability.where(:addressable_type =>'CallCenter',:addressable_id => session[:employee].call_centers.first.id).all
# find all available employee times
employee_availability = Availability.where('priority > 0').where(:addressable_type => 'Employee', :addressable_id => session[:employee].call_centers.first.employees.collect(&:id)).all
# create availability to requirement hash to determine order of days
availability_to_requirement_hash = create_availability_to_requirement_hash(schedule_structure, employee_availability)
# iterate through the hash day by day, a data is no use to us
availability_to_requirement_hash.each do |day,a|
# select the employees with availability for the chosen day, sort them by priority, and then iterate through them to clear the requirements
employee_availability.select{|b| b.day_increment == day}.sort_by{|c| c.priority}.group_by(&:addressable).each do |employee, availabilities|
# select the start time for the current day defined from requirement hash
start_time = schedule_structure.select{|b| b.day_increment == day && b.priority > 0}.first.time_increment
#define the length of the shift
shift_length = employee.length_of_shift > availabilities.length ? availabilities.length : employee.length_of_shift
#define the end time for the shift
end_time = start_time + shift_length
logger.info end_time
#check if employee already defined in hash, if present add the shift as an array of date, start time and end time, if not then add employee to hash with value as array
#generate_schedules.has_key?(employee) ? #generate_schedules[employee] << [day, start_time, end_time] : #generate_schedules[employee] = [[day, start_time, end_time]]
logger.info schedule_structure
#update the schedule structure to reflect the time removed // do not change database
(1..shift_length).each do |d|
schedule_structure.select{|e| e.day_increment == day && e.priority > 0}.first.priority -= 1
end
end
end
end
Here's an example of my output:
Example of View

Execute before_filter every 5min , in Rails 4

I have multiple (3) before_filter functions in Application_controller.
They look similar to this:
def give_vip_recomend
#list = List.where("billing_id =?", 5).first
if #list.present?
#v = Girl.where("country_id=?",#list.country_id).where("vip_recomend >= ?", Time.now).count
#b = Girl.where("country_id=?",#list.country_id).where("recomend >= ?", Time.now).count
#count = #v+#b
if #count < 8 #pārbauda recomended anketas jau ir 4
#advertisement = Girl.find_by_id(#list.advertisement_id)
#advertisement.vip_highlight = Time.now + 2.days
#advertisement.paid = true
#advertisement.save
#list.delete
flash[:notice] = "Izdevās piešķirt vip_highlight - gaidīšanas sarakstā esošam"
end
end
end
At this point I can't see performance issues, but later I believe it will cause some headaches.
Question:
Is it possible to execute those before_filters one by one. For example:
every 5 minutes - execute "X" before_filter
every 7 minutes - execute "Y" before_filter
Thanks in advance for your time.
Best regards
This is not something that should be considered a part of your controllers' jobs.
Consider looking at the whenever gem and processing jobs like this via cron.

Inconsistent read in database

I'm seeing inconsistent behavior, and am wondering what I could be doing wrong here.
I have subscription objects, whose state is defined by its cycle and con attributes, that are integers. months_passed returns an integer that counts how many FULL months has passed between the start_date of the subscription and Time.current.
def update_state
update_cycle
update_con
self.save
end
def update_cycle
self.cycle = if months_passed > 0
(months_passed - 1)/3 + 1
else
0
end
end
def update_con
self.con = if months_passed > 0
(months_passed - 1) % 3 + 1
else
0
end
end
def in_con1?
update_state
con == 1
end
However, when I call in_con1?, quickly in succession, I'll inconsistently get true or false.
Do I need to reload the object? Is something stale?
Argh, sorry guys. I found the culprit. Had nothing to do with inconsistent database reads. It was when months_passed was getting called, an hour before I expected.

updating a model attribute that will only change once

I have a subject model with attributes including a start_date and end_date - as well as a completed boolean attribute.
In subject.rb, I have a method to find how many weeks are remaining for a given subject:
def weeks_left
time = (self.end_date.to_time - Date.today.to_time).round/1.week
if time < 0
"completed"
elsif time < 1
"less than 1 week"
elsif time == 1
"1 week"
else
"#{time} weeks"
end
end
I want to tick the completed attribute if self.weeks_left == "completed" and the best way to do that seems like a call back, but I'm a bit unsure about using after_find - in general it seems like it would be too many queries, and indeed too big of a pain (especially after reading this) - but in this case, once a subject is complete, it's not going to change, so it seems useless to check it's status more than once - what's the best way to handle this?
Why dont you make a scope for this?
scope :completed, ->{where("end_date <= ?", Time.now)}
and a method
def completed?
self.weeks_left == "completed"
end
Looks like you need ActiveRecord::Callbacks. You can see more information here or on rails guide
before_save :update_completed
def update_completed
if (end_date_changed?)
time = (self.end_date.to_time - Date.today.to_time).round/1.week
self.complete = time < 0
end
end
This way you update the complete flag whenever end_date changes and it would always be in sync.
However because this is a calculated value you could also not store it as an attribute and simply define a method to get it
def complete
time = (self.end_date.to_time - Date.today.to_time).round/1.week
return time < 0
end

Resources