Phoenix Rising
2010-Apr-13  20:40 UTC
[Rails 2.3] Adding a "phase" to the ActiveRecord Lifecycle
I''ve run into a situation where it seems to me that if I could
"extend" the typical AR lifecycle to add another "phase" or
step to
it, it would simplify things.  My problem is that I just don''t know
how to do that, and I haven''t been able to find documentation anywhere
on it!
I''m working on an e-commerce application that''s somewhat
complex.  Due
to constraints of the organization, I can''t have accounts or
authentication.  My theoretical approach is to store an "order ID" in
a user''s session, and of course all selects/updates etc. will be only
for that ID from their session, thus keeping the current status of the
order in the database at all times.  If it were something simple I''d
just store an array of object IDs in the user''s session, but there are
several different kinds of products/services to buy, each with vastly
different models and various requirements ("if you have this you must
have that but MUST NOT have this", etc.).
The AR lifecycle question comes into play because I''d like to add some
form of validation on the Order model, but ONLY before and after the
user''s card is charged.
So here''s a simple example -
Order < ActiveRecord::Base
  belongs_to :object
  has_many :item_joins
  has_many :items, :through => :item_joins
  has_many :other_item_joins
  has_many :other_items, :through => :other_item_joins
  # ... and so on ...
end
Because the user can add multiple items and other items to their
order, as well as set the "object" on their order at any point in the
ordering process, I can''t call the validations I want after save. 
I''d
much rather have a before/after "card_charged" step in the lifecycle,
and run a validation before the card is charged, then one after it''s
charged.
So, for example, I''d like to be able to do something like:
Order < ActiveRecord::Base
  # ...associations as above...
  before_charged :ensure_not_empty
  private
  def ensure_not_empty
    if self.items.count < 1 and self.other_items.count < 1
      errors.add_to_base("Your order is empty!")
      return false
    end
  end
And this would need to fire when Order#charge_card (or similarly named
method) is called, canceling the call to Order#charge_card if false is
returned.
I took a quick look at state machines (aasm), and I have to confess
that I don''t know much about a state machine or how one works other
than very basic theory.  It seems like it might be overkill to me,
when all I want to do is add two methods to the lifecycle as above.
However, I''m fully willing to consider the possibility that what
I''m
suggesting here is outside the realm of best practices.
Any ideas as to how I could add these steps to the lifecycle of just
this object?
-- 
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.
Michael Schuerig
2010-Apr-14  11:59 UTC
Re: [Rails 2.3] Adding a "phase" to the ActiveRecord Lifecycle
On Tuesday 13 April 2010, Phoenix Rising wrote:> Because the user can add multiple items and other items to their > order, as well as set the "object" on their order at any point in the > ordering process, I can''t call the validations I want after > save. I''d much rather have a before/after "card_charged" step in > the lifecycle, and run a validation before the card is charged, then > one after it''s charged.I think the best way would be to use a state machine, as you indicated yourself in a paragraph I snipped. Second best would be to use conditional validations, see the :if and :unless options on all the validates_something methods. Michael -- Michael Schuerig mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org http://www.schuerig.de/michael/ -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.