I would like in my ''after_update'' callback to detect if an
attribute
has been
changed, and if so change some related objects. Is the best way
something like this
class Thing < ActiveRecord::Base
def before_update
@old = Thing.find(self.id)
end
end after_update
if @old.val != self.val
do_stuff
end
end
Or is there a better way? I wish I could avoid the ''find'' call
if
possible.
Thanks in advance,
Don Mc
--~--~---------~--~----~------------~-------~--~----~
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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
What I''ve done is handle this from the controller, something like this:
class TheController < ActionController
def update
@thing = Thing.find(params[:id]) rescue nil
redirect_to X unless @thing # Where X = named route or routing hash
[controller, action, etc]
old = {}
old[:name] = @thing.name
old[:body] = @thing.body
# Process @thing
if @thing.name != old[:name]
# Do whatcha gotta do...
end
if @thing.body != old[:body]
# You get the picture...
end
end
end
Don''t just make a dup of @thing, though. ''Cause when @
thing.update_attributes(params[:thing]) gets called it will change old as
well due to Ruby''s shallow copying. You could marshal the whole object
but
I''ve found it easier to just copy specific attributes. I like the
old[:attribute] method but it''d work the same with separate variables
for
each, like old_name = @thing.name, etc.
Hope that helps.
RSL
On 3/6/07, Don.Mc <Don.McClean-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:>
>
> I would like in my ''after_update'' callback to detect if
an attribute
> has been
> changed, and if so change some related objects. Is the best way
> something like this
>
> class Thing < ActiveRecord::Base
>
> def before_update
> @old = Thing.find(self.id)
> end
>
> end after_update
> if @old.val != self.val
> do_stuff
> end
> end
>
>
> Or is there a better way? I wish I could avoid the ''find''
call if
> possible.
>
> Thanks in advance,
> Don Mc
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
I prefer the OP''s instinct to handle the dependencies within the
model. It''s centralized for all users of the model (i.e.,
controllers), easier to test and better encapsulated. That said, I
think the Rails way to deal with this is to override the default
setter method for the attribute.
class Thing < ActiveRecord::Base
def val=(v)
write_attribute(:val, v)
do_stuff # Operations that depend on new val
end
end
This is also independent of whether the Thing is ever written to the
DB, which is generally what you want.
HTH,
Colin
On 3/7/07, Russell Norris <sconds-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:> What I''ve done is handle this from the controller, something like
this:
>
>
> class TheController < ActionController
> def update
> @thing = Thing.find(params[:id]) rescue nil
> redirect_to X unless @thing # Where X = named route or routing hash
> [controller, action, etc]
> old = {}
> old[:name] = @thing.name
> old[:body] = @thing.body
> # Process @thing
> if @thing.name != old[:name]
> # Do whatcha gotta do...
> end
> if @thing.body != old[:body]
> # You get the picture...
> end
> end
> end
>
> Don''t just make a dup of @thing, though. ''Cause when
> @thing.update_attributes(params[:thing]) gets called it will change old as
> well due to Ruby''s shallow copying. You could marshal the whole
object but
> I''ve found it easier to just copy specific attributes. I like the
> old[:attribute] method but it''d work the same with separate
variables for
> each, like old_name = @ thing.name, etc.
>
> Hope that helps.
>
> RSL
>
> On 3/6/07, Don.Mc <Don.McClean-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> wrote:
> >
> > I would like in my ''after_update'' callback to detect
if an attribute
> > has been
> > changed, and if so change some related objects. Is the best way
> > something like this
> >
> > class Thing < ActiveRecord::Base
> >
> > def before_update
> > @old = Thing.find(self.id )
> > end
> >
> > end after_update
> > if @old.val != self.val
> > do_stuff
> > end
> > end
> >
> >
> > Or is there a better way? I wish I could avoid the
''find'' call if
> > possible.
> >
> > Thanks in advance,
> > Don Mc
> >
--
Colin Strasser
Union Square Internet Development
917.723.6930 (m)
646.219.0332 (f)
--~--~---------~--~----~------------~-------~--~----~
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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Will this work for things like calling a sweeper if the url of a page changes? It''s been a while but I remember having one heck of a time getting ActiveRecord models to communicate with their controllers that way. But A) it''s been a while and B) I only half know what I''m doing know and probably less back then. Oh yeah, and what''s the OP? RSL On 3/7/07, Colin Strasser <colin-BOTN+IkIZYQ@public.gmane.org> wrote:> > > I prefer the OP''s instinct to handle the dependencies within the > model. It''s centralized for all users of the model (i.e., > controllers), easier to test and better encapsulated. That said, I > think the Rails way to deal with this is to override the default > setter method for the attribute. > > class Thing < ActiveRecord::Base > def val=(v) > write_attribute(:val, v) > do_stuff # Operations that depend on new val > end > end > > This is also independent of whether the Thing is ever written to the > DB, which is generally what you want. > > HTH, > > Colin > > > On 3/7/07, Russell Norris <sconds-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > What I''ve done is handle this from the controller, something like this: > > > > > > class TheController < ActionController > > def update > > @thing = Thing.find(params[:id]) rescue nil > > redirect_to X unless @thing # Where X = named route or routing hash > > [controller, action, etc] > > old = {} > > old[:name] = @thing.name > > old[:body] = @thing.body > > # Process @thing > > if @thing.name != old[:name] > > # Do whatcha gotta do... > > end > > if @thing.body != old[:body] > > # You get the picture... > > end > > end > > end > > > > Don''t just make a dup of @thing, though. ''Cause when > > @thing.update_attributes(params[:thing]) gets called it will change old > as > > well due to Ruby''s shallow copying. You could marshal the whole object > but > > I''ve found it easier to just copy specific attributes. I like the > > old[:attribute] method but it''d work the same with separate variables > for > > each, like old_name = @ thing.name, etc. > > > > Hope that helps. > > > > RSL > > > > On 3/6/07, Don.Mc <Don.McClean-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > wrote: > > > > > > I would like in my ''after_update'' callback to detect if an attribute > > > has been > > > changed, and if so change some related objects. Is the best way > > > something like this > > > > > > class Thing < ActiveRecord::Base > > > > > > def before_update > > > @old = Thing.find(self.id ) > > > end > > > > > > end after_update > > > if @old.val != self.val > > > do_stuff > > > end > > > end > > > > > > > > > Or is there a better way? I wish I could avoid the ''find'' call if > > > possible. > > > > > > Thanks in advance, > > > Don Mc > > > > > -- > Colin Strasser > Union Square Internet Development > 917.723.6930 (m) > 646.219.0332 (f) > > > >--~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Thanks for responding! In this particular case, I really don''t want to update the related objects unless the object has been saved, since the related objects are in the database also. Thats a good point about the shallow copying issue.I would like to leave the operation in the model, to handle updates from different sources. On Mar 7, 10:25 am, "Russell Norris" <sco...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Will this work for things like calling a sweeper if the url of a page > changes? It''s been a while but I remember having one heck of a time getting > ActiveRecord models to communicate with their controllers that way. But A) > it''s been a while and B) I only half know what I''m doing know and probably > less back then. > > Oh yeah, and what''s the OP? > > RSL > > On 3/7/07, Colin Strasser <c...-BOTN+IkIZYQ@public.gmane.org> wrote: > > > > > I prefer the OP''s instinct to handle the dependencies within the > > model. It''s centralized for all users of the model (i.e., > > controllers), easier to test and better encapsulated. That said, I > > think the Rails way to deal with this is to override the default > > setter method for the attribute. > > > class Thing < ActiveRecord::Base > > def val=(v) > > write_attribute(:val, v) > > do_stuff # Operations that depend on new val > > end > > end > > > This is also independent of whether the Thing is ever written to the > > DB, which is generally what you want. > > > HTH, > > > Colin > > > On 3/7/07, Russell Norris <sco...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > What I''ve done is handle this from the controller, something like this: > > > > class TheController < ActionController > > > def update > > > @thing = Thing.find(params[:id]) rescue nil > > > redirect_to X unless @thing # Where X = named route or routing hash > > > [controller, action, etc] > > > old = {} > > > old[:name] = @thing.name > > > old[:body] = @thing.body > > > # Process @thing > > > if @thing.name != old[:name] > > > # Do whatcha gotta do... > > > end > > > if @thing.body != old[:body] > > > # You get the picture... > > > end > > > end > > > end > > > > Don''t just make a dup of @thing, though. ''Cause when > > > @thing.update_attributes(params[:thing]) gets called it will change old > > as > > > well due to Ruby''s shallow copying. You could marshal the whole object > > but > > > I''ve found it easier to just copy specific attributes. I like the > > > old[:attribute] method but it''d work the same with separate variables > > for > > > each, like old_name = @ thing.name, etc. > > > > Hope that helps. > > > > RSL > > > > On 3/6/07, Don.Mc <Don.McCl...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > wrote: > > > > > I would like in my ''after_update'' callback to detect if an attribute > > > > has been > > > > changed, and if so change some related objects. Is the best way > > > > something like this > > > > > class Thing < ActiveRecord::Base > > > > > def before_update > > > > @old = Thing.find(self.id ) > > > > end > > > > > end after_update > > > > if @old.val != self.val > > > > do_stuff > > > > end > > > > end > > > > > Or is there a better way? I wish I could avoid the ''find'' call if > > > > possible. > > > > > Thanks in advance, > > > > Don Mc > > > -- > > Colin Strasser > > Union Square Internet Development > > 917.723.6930 (m) > > 646.219.0332 (f)--~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I just wanted to thank you for drawing my attention to this methodology.
I''ve done some further looking into it and it will indeed do exactly
the
kind of things I need. What I ended up doing was something like
class Thing < ActiveRecord::Base
attr_reader old_name
def name=(val)
@old_name = (val == name) ? nil : name
super val
end
def vitals_changed?
@old_name ? true : false
end
end
then checking @ thing.vitals_changed? which works marvelously. I seriously
cannot thank you enough. This really helps clean up some rather sticky,
messy, and misplaced code fragments in my app. Thanks, thanks, thanks.
RSL
On 3/7/07, Colin Strasser <colin-BOTN+IkIZYQ@public.gmane.org>
wrote:>
>
> I prefer the OP''s instinct to handle the dependencies within the
> model. It''s centralized for all users of the model (i.e.,
> controllers), easier to test and better encapsulated. That said, I
> think the Rails way to deal with this is to override the default
> setter method for the attribute.
>
> class Thing < ActiveRecord::Base
> def val=(v)
> write_attribute(:val, v)
> do_stuff # Operations that depend on new val
> end
> end
>
> This is also independent of whether the Thing is ever written to the
> DB, which is generally what you want.
>
> HTH,
>
> Colin
>
>
> On 3/7/07, Russell Norris
<sconds-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> > What I''ve done is handle this from the controller, something
like this:
> >
> >
> > class TheController < ActionController
> > def update
> > @thing = Thing.find(params[:id]) rescue nil
> > redirect_to X unless @thing # Where X = named route or routing
hash
> > [controller, action, etc]
> > old = {}
> > old[:name] = @thing.name
> > old[:body] = @thing.body
> > # Process @thing
> > if @thing.name != old[:name]
> > # Do whatcha gotta do...
> > end
> > if @thing.body != old[:body]
> > # You get the picture...
> > end
> > end
> > end
> >
> > Don''t just make a dup of @thing, though. ''Cause when
> > @thing.update_attributes(params[:thing]) gets called it will change
old
> as
> > well due to Ruby''s shallow copying. You could marshal the
whole object
> but
> > I''ve found it easier to just copy specific attributes. I like
the
> > old[:attribute] method but it''d work the same with separate
variables
> for
> > each, like old_name = @ thing.name, etc.
> >
> > Hope that helps.
> >
> > RSL
> >
> > On 3/6/07, Don.Mc
<Don.McClean-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > wrote:
> > >
> > > I would like in my ''after_update'' callback to
detect if an attribute
> > > has been
> > > changed, and if so change some related objects. Is the best way
> > > something like this
> > >
> > > class Thing < ActiveRecord::Base
> > >
> > > def before_update
> > > @old = Thing.find(self.id )
> > > end
> > >
> > > end after_update
> > > if @old.val != self.val
> > > do_stuff
> > > end
> > > end
> > >
> > >
> > > Or is there a better way? I wish I could avoid the
''find'' call if
> > > possible.
> > >
> > > Thanks in advance,
> > > Don Mc
> > >
>
> --
> Colin Strasser
> Union Square Internet Development
> 917.723.6930 (m)
> 646.219.0332 (f)
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---