Hello i have this blog module where my posts can have 3 states "no_status" "in_draft" and "published", the user can set the publish_date and publish_end_date for his posts while this range between the dates is fulfilled, the status of the post must be "published", and when it is finished return to "in_draft"
def post
if self.no_status? || self.in_draft?
if self.publish_date >=Date.today && self.publish_end <= Date.today
self.update_attribute :status, 'published'
end
elsif self.published?
if self.publish_date.past? && self.publish_end.past?
self.update_attribute :status, 'in_draft'
end
end
end
What is the proper way to manage this, i have a big problem with my conditions.
CodePudding user response:
You can use Range#cover?
. It basically takes a range and checks if the date is withing the start/end;
(10.days.ago..1.day.ago).cover?(3.days.ago)
# true
So, in your case;
(publish_date..publish_end).cover?(Date.today)
CodePudding user response:
In the 1st branch your conditionals are mixed up now, they should be opposite (that's why it doesn't work as expected - you check than publish_date
is greater that current date, but this is wrong - it must be in the past to have the post published today). So if you simply "mirror" your conditional operators it should work - but there are cleaner ways of writing the same:
Date.today.between?(publish_date, publish_end)
# or
(publish_date..publish_end).cover?(Date.today)
In the 2nd branch checking that pulish_end date is n the past should be enough. Checking if publish_date is in the past too is redundant - if it is not you have bigger problems what just a wrong status :) - this kind of basic data integrity is better to be addressed by model validations.
Also, the nested if
s are absolutely unnecessary here, they just make the code harder to reason about.
To summarize, something like the following should do the job (I'm not discussing here how this method is being used and whether it should be written this way or not - just addressing the initial question)
def post
new_status =
if published? && publish_end.past?
'in_draft'
elsif Date.today.between?(publish_date, publish_end)
'published'
end
update_attribute :status, new_status
end
CodePudding user response:
You can use Object#in?
def post
if no_status? || in_draft?
update(status: 'published') if Date.today.in?(publish_date..publish_end)
elsif published?
update(status: 'in_draft') if publish_date.past? && publish_end.past?
end
end
(BTW you don't need self
in Ruby every time)