{"id":19055808,"url":"https://github.com/taskrabbit/dv8","last_synced_at":"2025-11-12T08:05:25.027Z","repository":{"id":4899040,"uuid":"6055049","full_name":"taskrabbit/dv8","owner":"taskrabbit","description":"Hit Rails.cache instead of your DB","archived":false,"fork":false,"pushed_at":"2014-09-11T17:28:01.000Z","size":254,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":43,"default_branch":"master","last_synced_at":"2025-02-22T01:27:45.738Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://tech.taskrabbit.com/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"gregjacobs/Autolinker.js","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taskrabbit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-10-03T03:35:37.000Z","updated_at":"2020-02-04T19:26:08.000Z","dependencies_parsed_at":"2022-09-07T09:00:13.221Z","dependency_job_id":null,"html_url":"https://github.com/taskrabbit/dv8","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/taskrabbit/dv8","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskrabbit%2Fdv8","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskrabbit%2Fdv8/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskrabbit%2Fdv8/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskrabbit%2Fdv8/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taskrabbit","download_url":"https://codeload.github.com/taskrabbit/dv8/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskrabbit%2Fdv8/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":283997629,"owners_count":26929852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-12T02:00:06.336Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T23:47:05.159Z","updated_at":"2025-11-12T08:05:25.012Z","avatar_url":"https://github.com/taskrabbit.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dv8\n\nDv8 gives you the ability to query against Rails.cache rather than your db. It works with all associations and queries.\n\n## How\n\nSingular lookups eg. `User.find()` fetch against `Rails.cache` and end up hitting your db as a backup. After hitting your db the attributes of the record are stored in the cache. Until the record changes, any query where record is part of the result will pull from the cache - even when the record is part of a result set.\n\nMultiple result lookups are handled a little differently. A query always hits your db, but it only returns the primary keys. The primary keys are then checked in the cache. Any missing keys are queried in full from your db in a single query. The result sets are merged together with all ordering preserved.\n\nFor example. Given 3 users `A`,`B`, and `C` exist with primary keys `a`,`b`, and `c` but only user `A` is in the cache, the resulting queries would occur if all users were queried:\n\n```ruby\nUser.all\n# DB \n#  execute('select id from users')\n#  =\u003e [a,b,c]\n#\n# CACHE\n#  fetch('users-a')\n#  =\u003e {...}\n#  fetch('users-b')\n#  =\u003e nil\n#  fetch('users-c')\n#  =\u003e nil\n#\n# DB\n# execute('select * from users where id IN(b,c)')\n#\n# CACHE\n#  write('users-b', {..})\n#  write('users-c', {..})\n#\n# =\u003e [A,B,C] \n```\n\nThe next time all users are queried the following queries would take place (assuming the cache has not been invalidated):\n\n```ruby\nUser.all\n# DB \n#  execute('select id from users')\n#  =\u003e [a,b,c]\n#\n# CACHE\n#  fetch('users-a')\n#  =\u003e {...}\n#  fetch('users-b')\n#  =\u003e {...}\n#  fetch('users-c')\n#  =\u003e {...}\n#\n# =\u003e [A,B,C]\n```\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n    gem 'dv8'\n\nAnd then execute:\n\n    $ bundle\n\n## Usage\n\nTo enable dv8 on a class just include the `Dv8::Base` module:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  include Dv8::Base\n\n  belongs_to  :club\n  has_many    :badges\nend\n```\n\nNow that dv8 is enabled you can query through the cache via the `#cfind()` method.\n\n```ruby\nUser.cfind('john--3')\n```\n\nAssociations are queried through the cache by invoking `cached_[association_name]`:\n\n```ruby\nuser.cached_club\nuser.cached_badges\n```\n\nTo query through the cache on any random query, just invoke the `cached` scope:\n\n```ruby\nUser.cached.where(id: [1,2,3])\n```\n\nIf you would like a class' `#find()` to always query through the cache you can include the `Dv8::AlwaysCache` module:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  include Dv8::Base\n  include Dv8::AlwaysCache\nend\n```\n\nThe AlwaysCache module is generally good to use for seed data.\n\n## Integrations\n\nDv8 is blindly aware of slugging. If your model responds to `to_param`, `friendly_id`, `slug`, `cached_slug`, etc Dv8 will read and write any/all those keys. So a model with a slug column will have two entries into the cache:\n\n```ruby\nu = User.find('john')\nu.dv8_keys\n# =\u003e ['users-44', 'users-john']\n```\n\nInvalidation of the cache is automatically taken care of when you include `Dv8::Base` into your model. It uses the `after_update` and `after_touch` callbacks to invalidate the cache.\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaskrabbit%2Fdv8","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaskrabbit%2Fdv8","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaskrabbit%2Fdv8/lists"}