Walter Lee Davis
2012-Aug-29 15:13 UTC
Ensure that only one member of a collection has the "current" flag set
I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following: before_save :toggle_current def toggle_current if current? Home.where(["current = ? & id != ?", true, self.id]).each do |home| home.update_attribute(:current, false) end end end Which works, but feels like a heavy solution to a simple problem. I could add a set of radio buttons to the index view and set it that way, but does anyone else have any other suggestions? Thanks in advance, Walter -- 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 https://groups.google.com/groups/opt_out.
Michael Pavling
2012-Aug-29 15:21 UTC
Re: Ensure that only one member of a collection has the "current" flag set
On 29 August 2012 16:13, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote:> I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following: > > before_save :toggle_current > > def toggle_current > if current? > Home.where(["current = ? & id != ?", true, self.id]).each do |home| > home.update_attribute(:current, false) > end > end > endyou could use "update_all" rather than iterate a collection, which would only fire one SQL query. -- 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 https://groups.google.com/groups/opt_out.
Walter Lee Davis
2012-Aug-29 15:39 UTC
Re: Ensure that only one member of a collection has the "current" flag set
NICE! Arel collapsed the getting and setting to a single query: UPDATE "homes" SET "current" = ''f'' WHERE (current = ''t'' & id != 3). On Aug 29, 2012, at 11:21 AM, Michael Pavling wrote:> On 29 August 2012 16:13, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >> I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following: >> >> before_save :toggle_current >> >> def toggle_current >> if current? >> Home.where(["current = ? & id != ?", true, self.id]).each do |home| >> home.update_attribute(:current, false) >> end >> end >> end > > you could use "update_all" rather than iterate a collection, which > would only fire one SQL query.NICE! Arel collapsed the getting and setting to a single query: UPDATE "homes" SET "current" = ''f'' WHERE (current = ''t'' & id != 3). Thanks for the suggestion! Walter -- 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 https://groups.google.com/groups/opt_out.
Colin Law
2012-Aug-29 16:04 UTC
Re: Ensure that only one member of a collection has the "current" flag set
On 29 August 2012 16:13, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote:> I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following:I think you may have this the wrong way round, instead of remembering which one is current in the page put it in the admin model, then you only need to change it there and not touch the pages at all. Colin -- 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 https://groups.google.com/groups/opt_out.
Walter Lee Davis
2012-Aug-29 17:44 UTC
Re: Ensure that only one member of a collection has the "current" flag set
On Aug 29, 2012, at 12:04 PM, Colin Law wrote:> On 29 August 2012 16:13, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >> I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following: > > I think you may have this the wrong way round, instead of remembering > which one is current in the page put it in the admin model, then you > only need to change it there and not touch the pages at all.Admin is a subset of User, I was referring to him or her as a person, not a model. I am not sure why that model would be the place, though. I want to route /home to homes#default, where homes_controller#default looks like this: def default @home = Home.default render :action => ''show'' end and home#default looks like this: def self.default @default ||= Home.where(:current => true).first || Home.order(''added_at DESC'').first || Home.new end This is all working, I was just looking for a way to make it more canonical. Walter> > Colin > > -- > 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 https://groups.google.com/groups/opt_out. > >-- 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 https://groups.google.com/groups/opt_out.
Colin Law
2012-Aug-29 19:56 UTC
Re: Ensure that only one member of a collection has the "current" flag set
On 29 August 2012 18:44, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote:> > On Aug 29, 2012, at 12:04 PM, Colin Law wrote: > >> On 29 August 2012 16:13, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >>> I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following: >> >> I think you may have this the wrong way round, instead of remembering >> which one is current in the page put it in the admin model, then you >> only need to change it there and not touch the pages at all. > > Admin is a subset of User, I was referring to him or her as a person, not a model. I am not sure why that model would be the place, though. I want to route /home to homes#default, where homes_controller#default looks like this:Database design is nothing to do with routing. Get the database design right and separately sort out what views you want and hence the controllers and routing. You said that an admin (that is a User) at any time has one current home page. You have gone for the solution of remembering in the page record that it is, or is not, current, which involves the problems you have found with making sure that only one is current at any one time. Also there is redundant information in the db, the fact that one of the records has its current flag set implies that all the others are clear. In addition it is possible to have an illegal condition in the database where more than one is marked as current, these both suggest that there may be a better way of organising the data. An alternative solution is to remember in the User record which page is his current home page, which appears to me be an easier solution and is much less prone to subtle programming errors. Colin> > def default > @home = Home.default > render :action => ''show'' > end > > and home#default looks like this: > > def self.default > @default ||= Home.where(:current => true).first || Home.order(''added_at DESC'').first || Home.new > end > > This is all working, I was just looking for a way to make it more canonical. > > Walter > >> >> Colin >> >> -- >> 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 https://groups.google.com/groups/opt_out. >> >> > > -- > 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 https://groups.google.com/groups/opt_out. > >-- 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 https://groups.google.com/groups/opt_out.
Walter Lee Davis
2012-Aug-29 20:17 UTC
Re: Ensure that only one member of a collection has the "current" flag set
On Aug 29, 2012, at 3:56 PM, Colin Law wrote:> On 29 August 2012 18:44, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >> >> On Aug 29, 2012, at 12:04 PM, Colin Law wrote: >> >>> On 29 August 2012 16:13, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >>>> I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following: >>> >>> I think you may have this the wrong way round, instead of remembering >>> which one is current in the page put it in the admin model, then you >>> only need to change it there and not touch the pages at all. >> >> Admin is a subset of User, I was referring to him or her as a person, not a model. I am not sure why that model would be the place, though. I want to route /home to homes#default, where homes_controller#default looks like this: > > Database design is nothing to do with routing. Get the database > design right and separately sort out what views you want and hence the > controllers and routing. You said that an admin (that is a User) at > any time has one current home page. You have gone for the solution of > remembering in the page record that it is, or is not, current, which > involves the problems you have found with making sure that only one is > current at any one time. Also there is redundant information in the > db, the fact that one of the records has its current flag set implies > that all the others are clear. In addition it is possible to have an > illegal condition in the database where more than one is marked as > current, these both suggest that there may be a better way of > organising the data. An alternative solution is to remember in the > User record which page is his current home page, which appears to me > be an easier solution and is much less prone to subtle programming > errors.Oh, I see what you were thinking. This is not the Admin''s (personal) home page, it is the one and only home page for the entire public site. The admin is responsible for assembling this home page by choosing items to featured on it, but the home page that results (one of many that the admin may be working on for future use) is going to be shown to the world one at a time, by means of the current flag. Does that change your mind about what I might want to do here? Walter> > Colin > > >> >> def default >> @home = Home.default >> render :action => ''show'' >> end >> >> and home#default looks like this: >> >> def self.default >> @default ||= Home.where(:current => true).first || Home.order(''added_at DESC'').first || Home.new >> end >> >> This is all working, I was just looking for a way to make it more canonical. >> >> Walter >> >>> >>> Colin >>> >>> -- >>> 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 https://groups.google.com/groups/opt_out. >>> >>> >> >> -- >> 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 https://groups.google.com/groups/opt_out. >> >> > > -- > 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@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > >-- 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@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Colin Law
2012-Aug-29 20:40 UTC
Re: Ensure that only one member of a collection has the "current" flag set
On 29 August 2012 21:17, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote:> > On Aug 29, 2012, at 3:56 PM, Colin Law wrote: > >> On 29 August 2012 18:44, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >>> >>> On Aug 29, 2012, at 12:04 PM, Colin Law wrote: >>> >>>> On 29 August 2012 16:13, Walter Lee Davis <waltd-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >>>>> I have a model that includes a :current boolean. The idea is that there are many home pages that the admin is working on at any given time, but only one is current at a time. At the moment, I have enforced this with the following: >>>> >>>> I think you may have this the wrong way round, instead of remembering >>>> which one is current in the page put it in the admin model, then you >>>> only need to change it there and not touch the pages at all. >>> >>> Admin is a subset of User, I was referring to him or her as a person, not a model. I am not sure why that model would be the place, though. I want to route /home to homes#default, where homes_controller#default looks like this: >> >> Database design is nothing to do with routing. Get the database >> design right and separately sort out what views you want and hence the >> controllers and routing. You said that an admin (that is a User) at >> any time has one current home page. You have gone for the solution of >> remembering in the page record that it is, or is not, current, which >> involves the problems you have found with making sure that only one is >> current at any one time. Also there is redundant information in the >> db, the fact that one of the records has its current flag set implies >> that all the others are clear. In addition it is possible to have an >> illegal condition in the database where more than one is marked as >> current, these both suggest that there may be a better way of >> organising the data. An alternative solution is to remember in the >> User record which page is his current home page, which appears to me >> be an easier solution and is much less prone to subtle programming >> errors. > > Oh, I see what you were thinking. This is not the Admin''s (personal) home page, it is the one and only home page for the entire public site. The admin is responsible for assembling this home page by choosing items to featured on it, but the home page that results (one of many that the admin may be working on for future use) is going to be shown to the world one at a time, by means of the current flag. > > Does that change your mind about what I might want to do here?Yes, obviously, it can''t go in the User record. I still would not put it in the page however, if necessary put it in a separate table with a single record with a single field (though I suspect you might find other stuff to put there). The code will be simpler. You would not have had to ask here how to do it for example. It is nearly always best to use the simplest possible solution. Also the automated tests will be much simpler. Colin> > Walter > >> >> Colin >> >> >>> >>> def default >>> @home = Home.default >>> render :action => ''show'' >>> end >>> >>> and home#default looks like this: >>> >>> def self.default >>> @default ||= Home.where(:current => true).first || Home.order(''added_at DESC'').first || Home.new >>> end >>> >>> This is all working, I was just looking for a way to make it more canonical. >>> >>> Walter >>> >>>> >>>> Colin >>>> >>>> -- >>>> 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org >>>> For more options, visit https://groups.google.com/groups/opt_out. >>>> >>>> >>> >>> -- >>> 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 https://groups.google.com/groups/opt_out. >>> >>> >> >> -- >> 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 https://groups.google.com/groups/opt_out. >> >> > > -- > 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@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > >-- 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@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.