<commit_before># LazyGlobalRecord

[![Gem Version](https://badge.fury.io/rb/lazy_global_record.svg)](https://badge.fury.io/rb/lazy_global_record)

Lazy loading of 'interesting' ActiveRecord model id's, thread-safely and with
easy cache reset and lazy creation in testing. Uses ruby-concurrent
as a dependency.

You might find yourself doing this in Rails:

~~~ruby
class Department < ActiveRecord::Base
   # Bad idea, don't do this.
   def self.master_department_id
     @@master_department_id ||= where(name: "master").first.id
   end
   # ...
end
~~~~

A class acessor that looks up a particular record of concern in the db,
and caches it's id.

First of all, if you can find any way to _not_ do this in your architecture,
you'll be happier.  But maybe you can't get out of it.

If you take that naive approach, it ends up raising heck on your test
environment. DatabaseCleaner is cleaning out your db after every
test, so that record that you always expect to be there isn't;
if you switch to `first_or_create`, you still have a problem
because you don't really want to be silently creating the
record in production, and even in test when you silently create
it, it ends up getting cached, but then DatabaseCleaner cleans
it out and the cached value is wrong. And it's none of it thread-safe,
and this is 2016, get with the concurrency program already.

So this gem provides an answer, with a pattern to fetch and cache
an ActiveRecord model `id` (or other values), such that:

* thread-safe lazy loading
* Raise if it's not there in production
* Create it lazily if it's not there in dev/test
* Allow reset of memoization in dev/test, after every test
* Supply various custom logic with a concise api

~~~ruby
class Department < ActiveRecord::Base
    @lazy_master_department_id = LazyGlobalRecord.new(
      relation: -> { where(name: "master") }
    )
    def self.master_department_id
      @lazy_master_departent_id.value
    end
end
~~~

Note the `relation` argument is a `proc`.<commit_msg>shorten README a bit<commit_after># LazyGlobalRecord

[![Gem Version](https://badge.fury.io/rb/lazy_global_record.svg)](https://badge.fury.io/rb/lazy_global_record)

Lazy loading of 'interesting' ActiveRecord model id's, thread-safely and with
easy cache reset and lazy creation in testing. Uses ruby-concurrent
as a dependency.

You might find yourself doing this in Rails:

~~~ruby
class Department < ActiveRecord::Base
   # Bad idea, don't do this.
   def self.master_department_id
     @@master_department_id ||= where(name: "master").first.id
   end
   # ...
end
~~~~

A class acessor that looks up a particular record of concern in the db,
and caches it's id.

First of all, if you can find any way to _not_ do this in your architecture,
you'll be happier.  But maybe you can't get out of it.

If you take that naive approach, it ends up raising heck on your test
environment. DatabaseCleaner is cleaning out your db after every
test, so that record that you always expect to be there isn't;
if you switch to `first_or_create`, you still have a problem
because you don't really want to be silently creating the
record in production, and even in test when you silently create
it, it ends up getting cached, but then DatabaseCleaner cleans
it out and the cached value is wrong. And it's none of it thread-safe,
and this is 2016, get with the concurrency program already.

So this gem provides an answer, with a pattern to fetch and cache
an ActiveRecord model `id` (or other values), lazily, thread-safely,
with auto-creation and easy cache reset in test env.

~~~ruby
class Department < ActiveRecord::Base
    @lazy_master_department_id = LazyGlobalRecord.new(
      relation: -> { where(name: "master") }
    )
    def self.master_department_id
      @lazy_master_departent_id.value
    end
end
~~~

Note the `relation` argument is a `proc`.
{'fraction_non_alphanumeric': 0.0735638159604887, 'fraction_numerical': 0.002079542500649857, 'mean_word_length': 4.151271753681392, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2574457', 'n_tokens_mistral': 1173, 'n_tokens_neox': 1105, 'n_words': 525}