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.