Hi! In the Rails app I''m developing I have some data stored in the database that acts like constants. For example, I populate a profiles table with all the profile types using seeds.rb. To avoid hardcoding the profile ids in my code, everytime I needed to do an operation involving a profile type I first retrieved the profile type from the database: <code> admin = Profile.find_by_name(''admin'') @all_admins = admin.people </code> Since the profile ids (and other ''constants'' stored in the database) can only change if the sys admin changes their values before the deploy (editing seeds.rb), I though of using initializers to retrieve references to all those database constants (therefore opening less connections with the database during application usage): in .../initializers/ <code> class DatabaseConstants < ActiveRecord::Base # loading the profiles temp_profiles = {} Profile.all.each do |profile| case profile.name when ''foo'' temp_profiles[:foo] = profile when ''bar'' temp_profiles[:bar] = profile when ''admin'' temp_profiles[:admin] = profile when ''super-admin'' temp_profiles[:super_admin] = profile end end PROFILES = temp_profiles # other ''constants'' to be loaded # ... end </code> and then, I can do something like the following in a controller: <code> @all_admins = DatabaseConstants::PROFILES[:admin].people </code> I have tested this solution and it works perfectly fine. However, I would like to know from veteran Rails developers if this is a good (or acceptable) use of initializers (and if this should really increase performance). Cheers, Alex. -- 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 To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/bmtvpHG8CykJ. For more options, visit https://groups.google.com/groups/opt_out.
On Wednesday, November 21, 2012 5:57:15 PM UTC, Alex Braha Stoll wrote:> > > Since the profile ids (and other ''constants'' stored in the database) can > only change if the sys admin changes their values before the deploy > (editing seeds.rb), I though of using initializers to retrieve references > to all those database constants (therefore opening less connections with > the database during application usage): > > I don''t think this will affect the number of connections to the database,although you will of course save some queries> > I have tested this solution and it works perfectly fine. However, I would > like to know from veteran Rails developers if this is a good (or > acceptable) use of initializers (and if this should really increase > performance). > >Personally if this was worthwhile for my app I would load the profiles lazily rather than in an initializer. One reason is that initializers get run in a lot of cases where you probably don''t need those rows cached, eg rake routes. Occasionally this sort of stuff can bite you too - depending on how you deploy the app, the profiles table might not exist (fresh deploy). So you run rake db:schema:load to set things up, but that would also load you initializer and would therefore blow up when that initializer tried to access the profiles table. Fred -- 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 To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/LKGNT_jwrzkJ. For more options, visit https://groups.google.com/groups/opt_out.
Thanks for the answer, Fred. When you say lazily loading the data I need you mean waiting for a first request that uses the data, right? If so, how can I do that in a way that the data will persist for the next requests (from the same and from other users)? Just storing the data into a class that checks if the constants were already fetch doesn''t guarantee the persistence of the data between requests, right? Can you point me a resource where I can learn more about a solution for my scenario? Cheers, Alex. Em quarta-feira, 21 de novembro de 2012 20h41min25s UTC-2, Frederick Cheung escreveu:> > > > On Wednesday, November 21, 2012 5:57:15 PM UTC, Alex Braha Stoll wrote: >> >> >> Since the profile ids (and other ''constants'' stored in the database) can >> only change if the sys admin changes their values before the deploy >> (editing seeds.rb), I though of using initializers to retrieve references >> to all those database constants (therefore opening less connections with >> the database during application usage): >> >> I don''t think this will affect the number of connections to the database, > although you will of course save some queries > > >> >> I have tested this solution and it works perfectly fine. However, I would >> like to know from veteran Rails developers if this is a good (or >> acceptable) use of initializers (and if this should really increase >> performance). >> >> > Personally if this was worthwhile for my app I would load the profiles > lazily rather than in an initializer. One reason is that initializers get > run in a lot of cases where you probably don''t need those rows cached, eg > rake routes. > Occasionally this sort of stuff can bite you too - depending on how you > deploy the app, the profiles table might not exist (fresh deploy). So you > run rake db:schema:load to set things up, but that would also load you > initializer and would therefore blow up when that initializer tried to > access the profiles table. > > Fred >-- 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 To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/Zup5h2klZPQJ. For more options, visit https://groups.google.com/groups/opt_out.
On Wed, Nov 21, 2012 at 8:57 PM, Alex Braha Stoll <alexbrahastoll-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Thanks for the answer, Fred. > > When you say lazily loading the data I need you mean waiting for a first > request that uses the data, right? If so, how can I do that in a way that > the data will persist for the next requests (from the same and from other > users)? Just storing the data into a class that checks if the constants were > already fetch doesn''t guarantee the persistence of the data between > requests, right? Can you point me a resource where I can learn more about a > solution for my scenario?Most objects should persist between requests so if you were to create a struct and load all your data onto that struct the object would be persisted between requests. You could just create a Persist object with an initializer and and there is your persistent struct. -- 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.
On Thursday, November 22, 2012 2:57:46 AM UTC, Alex Braha Stoll wrote:> > Thanks for the answer, Fred. > > When you say lazily loading the data I need you mean waiting for a first > request that uses the data, right? If so, how can I do that in a way that > the data will persist for the next requests (from the same and from other > users)? Just storing the data into a class that checks if the constants > were already fetch doesn''t guarantee the persistence of the data between > requests, right? Can you point me a resource where I can learn more about a > solution for my scenario? > > I mean something likeclass Profile < AR::Base def self.cached @cached ||= begin #build up the hash of profiles end end end Then do Profile.cached[:foo] when you need it Fred Cheers,> > Alex. > > Em quarta-feira, 21 de novembro de 2012 20h41min25s UTC-2, Frederick > Cheung escreveu: >> >> >> >> On Wednesday, November 21, 2012 5:57:15 PM UTC, Alex Braha Stoll wrote: >>> >>> >>> Since the profile ids (and other ''constants'' stored in the database) can >>> only change if the sys admin changes their values before the deploy >>> (editing seeds.rb), I though of using initializers to retrieve references >>> to all those database constants (therefore opening less connections with >>> the database during application usage): >>> >>> I don''t think this will affect the number of connections to the >> database, although you will of course save some queries >> >> >>> >>> I have tested this solution and it works perfectly fine. However, I >>> would like to know from veteran Rails developers if this is a good (or >>> acceptable) use of initializers (and if this should really increase >>> performance). >>> >>> >> Personally if this was worthwhile for my app I would load the profiles >> lazily rather than in an initializer. One reason is that initializers get >> run in a lot of cases where you probably don''t need those rows cached, eg >> rake routes. >> Occasionally this sort of stuff can bite you too - depending on how you >> deploy the app, the profiles table might not exist (fresh deploy). So you >> run rake db:schema:load to set things up, but that would also load you >> initializer and would therefore blow up when that initializer tried to >> access the profiles table. >> >> Fred >> >-- 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 To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/ibpv9J6pQocJ. For more options, visit https://groups.google.com/groups/opt_out.
Thank you both Fred and Jordon for the help. I followed Fred''s code example and ended with the following solution: class Profile < ActiveRecord::Base has_many :person_profiles has_many :people, through: :person_profiles def self.cached @@profiles ||= fetch_data end def self.fetch_data temp_profiles = {} Profile.all.each do |profile| case profile.name when ''admin'' temp_profiles[:admin] = profile when ''super-admin'' temp_profiles[:super_admin] = profile # ... other profiles end end temp_profiles end end In the controller: @admins = Profile.cached[:admin].people Doing some tests, I noticed that starting on the second request there is a significative difference in ActiveRecord´s total processing time. However, if all the users log out, it seems that the garbage collector sweeps the data cached in the class variable. When I have time, I will further investigate this in order to find a way to persist that data for all the time the application is running. Cheers, Alex. Em quinta-feira, 22 de novembro de 2012 12h22min34s UTC-2, Frederick Cheung escreveu:> > > > On Thursday, November 22, 2012 2:57:46 AM UTC, Alex Braha Stoll wrote: >> >> Thanks for the answer, Fred. >> >> When you say lazily loading the data I need you mean waiting for a first >> request that uses the data, right? If so, how can I do that in a way that >> the data will persist for the next requests (from the same and from other >> users)? Just storing the data into a class that checks if the constants >> were already fetch doesn''t guarantee the persistence of the data between >> requests, right? Can you point me a resource where I can learn more about a >> solution for my scenario? >> >> I mean something like > > class Profile < AR::Base > def self.cached > @cached ||= begin > #build up the hash of profiles > end > end > end > > Then do Profile.cached[:foo] when you need it > > Fred > > Cheers, >> >> Alex. >> >> Em quarta-feira, 21 de novembro de 2012 20h41min25s UTC-2, Frederick >> Cheung escreveu: >>> >>> >>> >>> On Wednesday, November 21, 2012 5:57:15 PM UTC, Alex Braha Stoll wrote: >>>> >>>> >>>> Since the profile ids (and other ''constants'' stored in the database) >>>> can only change if the sys admin changes their values before the deploy >>>> (editing seeds.rb), I though of using initializers to retrieve references >>>> to all those database constants (therefore opening less connections with >>>> the database during application usage): >>>> >>>> I don''t think this will affect the number of connections to the >>> database, although you will of course save some queries >>> >>> >>>> >>>> I have tested this solution and it works perfectly fine. However, I >>>> would like to know from veteran Rails developers if this is a good (or >>>> acceptable) use of initializers (and if this should really increase >>>> performance). >>>> >>>> >>> Personally if this was worthwhile for my app I would load the profiles >>> lazily rather than in an initializer. One reason is that initializers get >>> run in a lot of cases where you probably don''t need those rows cached, eg >>> rake routes. >>> Occasionally this sort of stuff can bite you too - depending on how you >>> deploy the app, the profiles table might not exist (fresh deploy). So you >>> run rake db:schema:load to set things up, but that would also load you >>> initializer and would therefore blow up when that initializer tried to >>> access the profiles table. >>> >>> Fred >>> >>-- 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. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/1gVyUAMWk1sJ. For more options, visit https://groups.google.com/groups/opt_out.