Forum: Ruby on Rails Should I sleep here?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
648a71a35ce6e4a1c5cd63451a2a20df?d=identicon&s=25 Gavin (Guest)
on 2009-02-12 13:27
(Received via mailing list)
Hi

I'm building an app at the moment where specific items can be added to
an order and then purchased through paypal.

Becuase the items are limited, it's important to relist them quickly
if the order is not completed within 5mins.

Anybody have any suggestions as to how I could go about this?

I was thinking of creating an observer for orders and including an
after_create like so:

Class OrderObserver < ActiveRecord::Observer

def after_create
  sleep 300 # sleep for 5 mins
  if self.status > 3 # anything above 3 should be saved
    return
  else
    self.items.each do |item|
      item.update_attribute :order_id, nil
    end
    self.destroy
  end
end

Is there a better or a standard way of doing this though?
80e4cb97cae5c8d745f72337d93fd8f2?d=identicon&s=25 MaD (Guest)
on 2009-02-12 13:31
(Received via mailing list)
take a look at backgrounDRb. maybe this could be an option for you.
http://backgroundrb.rubyforge.org/

in a background process you could sleep for as long as you want to,
but if you try that in your main process your application might freeze
for that amount of time.
648a71a35ce6e4a1c5cd63451a2a20df?d=identicon&s=25 Gavin (Guest)
on 2009-02-12 13:33
(Received via mailing list)
I thought that may be the case
Thanks for your help - will read up on background DRb
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2009-02-12 14:15
(Received via mailing list)
On 12 Feb 2009, at 12:32, Gavin wrote:

>
> I thought that may be the case
> Thanks for your help - will read up on background DRb
>
another possibility is to have a cron job or daemon that checks for
orders that have been waiting for too long (stick a expires_at column
or something on the table). Just calling sleep is a bad idea.

Fred
280b78a61a968391b7e07e912be102a8?d=identicon&s=25 Robert Walker (robert4723)
on 2009-02-12 15:39
Gavin wrote:
> Anybody have any suggestions as to how I could go about this?
>
> I was thinking of creating an observer for orders and including an
> after_create like so:
>
> Class OrderObserver < ActiveRecord::Observer
>
> def after_create
>   sleep 300 # sleep for 5 mins
>   if self.status > 3 # anything above 3 should be saved
>     return
>   else
>     self.items.each do |item|
>       item.update_attribute :order_id, nil
>     end
>     self.destroy
>   end
> end

Sorry if this response is a bit off the question's topic, but I do have
an unrelated suggestion.

You have the following line in your sample code:
>   if self.status > 3 # anything above 3 should be saved

I would recommend against this use of "magic numbers," such as "3" in
this case. The number 3 has no meaning here. I would recommend that you
use something like a "finite state machine."

http://en.wikipedia.org/wiki/Finite_state_machine

There is a Ruby gem implementation of this:
http://github.com/rubyist/aasm/tree/master

Now the same line of code can be written as:
if self.completed?

Now there is no ambiguity on the meaning of some "magic number." The
code clearly states its intent.
648a71a35ce6e4a1c5cd63451a2a20df?d=identicon&s=25 Gavin (Guest)
on 2009-02-12 15:49
(Received via mailing list)
So, would it be more appropriate to write a method like

def purchased?
  if self.status > 3
    return true
  else
    return false
  end
end

and then call the purchased? method to perform the check?



On 12 Feb, 14:39, Robert Walker <rails-mailing-l...@andreas-s.net>
280b78a61a968391b7e07e912be102a8?d=identicon&s=25 Robert Walker (robert4723)
on 2009-02-12 16:17
Gavin wrote:
> So, would it be more appropriate to write a method like
>
> def purchased?
>   if self.status > 3
>     return true
>   else
>     return false
>   end
> end
>
> and then call the purchased? method to perform the check?
>
>
>
> On 12 Feb, 14:39, Robert Walker <rails-mailing-l...@andreas-s.net>

Actually it could be as simple as adding some constants to represent
your states.

Example:
STARTED = 1
PROCESSING = 2
COMPLETED = 3
BILLED = 4
PAID = 5

if self.state > COMPLETED

You just want to avoid the use of a "magic number" by giving it clear
meaning.
648a71a35ce6e4a1c5cd63451a2a20df?d=identicon&s=25 Gavin (Guest)
on 2009-02-12 16:21
(Received via mailing list)
Writing more unit tests for this as we speak

Thanks for the tip Robert

PS - I presume, if I were to use constants that I would define the
constants in the class itself?

On 12 Feb, 15:17, Robert Walker <rails-mailing-l...@andreas-s.net>
51655eeeedad656fad30717c46852437?d=identicon&s=25 Chris Kottom (Guest)
on 2009-02-12 19:28
(Received via mailing list)
+1 for implementing this as a cron job.  Sometimes the cleanest solution
is
outside the framework.
648a71a35ce6e4a1c5cd63451a2a20df?d=identicon&s=25 Gavin (Guest)
on 2009-02-12 19:45
(Received via mailing list)
Am I right in saying Daemons for frequent tasks (performing a specific
check every minute or so) and cron jobs for less regular tasks
(cleaning up sessions every week or so)?

Are Daemons resource-intensive?
Fac81a9d95c81d817a2debb6f717f3ac?d=identicon&s=25 Sazima (Guest)
on 2009-02-12 20:34
(Received via mailing list)
Hi,

Check out this excelent railscast:

http://railscasts.com/episodes/129-custom-daemon

It is really easy & effective.

Also, Thorny Gorms has some built-in checks for form expiration:

http://groups.google.com/group/rubyonrails-talk/br...

Cheers, Sazima
648a71a35ce6e4a1c5cd63451a2a20df?d=identicon&s=25 Gavin (Guest)
on 2009-02-12 20:45
(Received via mailing list)
Thanks Sazima - I set up a daemon like this earlier today and it's
working a treat, just wasn't sure if this was the most economic way to
get the job done!

But if it's good enough for Ryan, it's good enough for me.
This topic is locked and can not be replied to.