Git Product home page Git Product logo

cached_serializer's Introduction

CachedSerializer

A serializer for Rails models that prevents unnecessary lookups.

Usage

The following example serializes a User model. By using certain macros, the author can specify what values should be cached or recomputed when serializing a model record. Serialized data is cached via Rails.cache (by the User's id and specified attribute keys) so the serializer doesn't have to hit the DB for every attribute. This can be desirable when some of the serialized data involves long-running queries, relationship-heavy calculations, etc.

class Admin::UserSerializer < CachedSerializer::Base
  # Use the `::subject_class` macro (optional) to specify the class of the model
  # this serializer will be operating on. By default, it will serialize (and
  # cache for) the model class named (and nested) the same as the serializer,
  # short "`Serializer`" at the end of the name. For example, `UserSerializer`
  # will serialize `User` models by default. `Admin::UserSerializer` will
  # serialize `Admin::User` models by default.
  #
  # If you want to name the serializer something other than "`TheModelName` +
  # `Serializer`" (e.g., `AuthorSerializer` to serialize `User` records), or to
  # put it in a module (e.g., `Admin::UserSerializer` to differentiate it from
  # an existing `UserSerializer`) use `::subject_class` to specify the class of
  # the subject you will be serializing.
  subject_class User

  # Properties specified by `::columns` are called as-is on the model, and
  # invalidated automatically when the model is saved with new values for these
  # properties, by checking Rails' built-in `#email_changed?`/`#phone_changed?`
  # /etc. dynamic methods on save. Allows you to serialize most simple straight-
  # from-the-DB values without any extra effort.
  columns :email, :phone

  # Properties specified by `::constant` are are attributes that should never
  # need to be recomputed. They will be cached ad infinitum (until the cache key
  # is cleared, manually or otherwise).
  #
  # This will call `some_user.id` for the `:id` attribute, and
  # `some_user.created_at` for the `:created_at` attribute. Consider the values
  # for each to be cached FOREVER, and never recomputed.
  constant :id, :created_at

  # Alternatively, you can pass a block to `::constant`. This will use the
  # result of the block as the value for the `:name` attribute. It will cache
  # the value FOREVER, and never recompute it.
  constant :name do |user|
    "#{user.first_name} #{user.last_name}"
  end

  # Properties specified by `::volatile` are attributes that should always be
  # recomputed every time a user is serialized, and will never be cached.
  #
  # This will call `some_user.token` for the `:token` attribute, and
  # `some_user.updated_at` for the `:updated_at` attribute. It will ALWAYS
  # recompute the values, EVERY time it serializes a user.
  volatile :token, :updated_at

  # Alternatively, you can pass a block to `::volatile`. This will use the
  # result of the block as the value for the `:time_on_platform` attribute. It
  # will ALWAYS recompute the value, EVERY time it serializes a user.
  volatile :time_on_platform do |user|
    Time.zone.now.to_i - user.created_at.to_i
  end

  # Properties specified by `::computed` are attributes that should either be
  # recomputed by the given block or drawn from the cache based on rules that
  # you specify.
  #
  # You can specify columns that it depends on, such that when any of the
  # columns change it will invalidate the cache for this serialized property. In
  # this case, `:address` will only be recomputed when any of the supplied
  # attributes (`:address_1`, `:address_2`, `:city`, etc.) change on the user
  # record.
  computed :address, columns: [:address_1, :address_2, :city, :state, :zip] do |user|
    "#{user.address_1} #{user.address_2}, #{user.city}, #{user.state} #{user.zip}"
  end

  # You can also specify a `:recompute_if` proc/lambda. It will run
  # `:recompute_if` every time a model is being recomputed, and if it returns
  # `true` then it will recompute. Otherwise, it will use the cached result.
  computed :active, recompute_if: ->(u) { u.last_logged_in_at > 1.week.ago } do |user|
    user.purchases.where(created_at: 1.week.ago..Time.zone.now).present?
  end

  # Additionally, you can specify an `:expires_in` expiration duration. This
  # will cache the result for one day after the last time the
  # `:revenue_generated` attribute was recomputed.
  computed :revenue_generated, expires_in: 1.week do |user|
    user.offers.accepted.reduce(0) { |total, offer| total + offer.total_price }
  end

  # You can use any number of these cache conditions with `:compute`. For
  # example, this will cache the result until `:foo` changes on the user, `:bar`
  # changes on the user, `u.silly?` is `true` at the time of serialization, or
  # it has been more than 10 seconds since the last time the `:silly` attribute
  # was recomputed.
  computed :silly, columns: [:foo, :bar], recompute_if: ->(u) { u.silly? }, expires_in: 10.seconds do |user|
    rand(100)
  end
end

Installation

Add this line to your application's Gemfile:

gem 'cached_serializer'

Then cd into your project's directory and run:

bundle install

Bug reports

If you encounter a bug, you can report it here. Please include the following information, if possible:

  • your Ruby version (ruby --version; if using multiple Rubies via rvm or similar, make sure you're in your project's directory when you run ruby --version)
  • your Rails version (cd into your project's directory, then bundle exec rails --version)
  • example code (which demonstrates the issue)
  • your soul (for eating)

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/kjleitz/cached_serializer.

License

The gem is available as open source under the terms of the MIT License.

cached_serializer's People

Contributors

kjleitz avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.