No commit activity in last 3 years
No release in over 3 years
ActiveRecord type READ ONLY data storage for small amounts of simple, unchanging data.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 10.3

Runtime

 Project Readme

PermanentRecord

An ActiveRecord substitute for small amounts of persistent data.

About

Have you ever had a small amount of data that changed infrequently and didn't seem worth the hassle of persisting in a database? Maybe you're thinking "no, I have not" and that would be a reasonable answer. More than likely, most of the time a database will be the right choice. In the off chance you though "yes!", you can use PermanentRecord as a simple way to turn Plain Old Ruby Objects into Rails friendly, READ ONLY ActiveRecord like objects.

When might this be useful?

A hypothetic scenario: Let's pretend you're writing a book. Let's pretend it also happens to be a book about Rails and you've chosen to write the book as a Rails web application. The only persisted data you want to save are the chapter titles, plus the actual text content for the book. Obviously saving the text content of each chapter in a database would be silly - you can just write that directly into a view file. That leaves only the names of the chapters... where should you put those? You could set up a database to store this small amount of unchanging data, or you could save the data in a CHAPTERS constant like:

# config/data/chapters.rb
CHAPTERS = [
  {title: 'Introduction', subtitle: nil},
  {title: 'Chapter 1', subtitle: 'What is Ruby?'},
  {title: 'Chapter 2', subtitle: 'What is Ruby on Rails?'},
  {title: 'Chapter 3', subtitle: 'System Setup'},
  ...
  {title: 'Appendix Z', subtitle: 'Expert Rails Stuff'}
]

But since you're using a Rails backend, it would be nice if you could pretend the Chapter information stored in this constant was actually stored in a database. That way you could use all the goodies that Rails provides - like finders and path helpers. Here is where PermanentRecord comes in. Continue our hypothetical situation below in the Usage section.

Install

Add the gem the standard Gemfile way:

# Gemfile
gem 'permanent_record'

Usage

Storing the Data

Our story ended off with you deciding to store a small amount of data in a constant, saved in the file chapters.rb. The data was an array of hashes that represented the titles and subtitles of your new book:

# config/data/chapters.rb
CHAPTERS = [
  {title: 'Introduction', subtitle: nil},
  {title: 'Chapter 1', subtitle: 'What is Ruby?'},
  {title: 'Chapter 2', subtitle: 'What is Ruby on Rails?'},
  {title: 'Chapter 3', subtitle: 'System Setup'},
  ...
  {title: 'Apendix Z', subtitle: nil}
]

Setting up a Model

Now let's set up your Chapter model that'll use this data:

# chapter.rb
class Chapter < PermanentRecord
end

That's it. PermanentRecord will automatically look for your previously defined CHAPTERS constant and use the data stored there to create each Chapter object. Since you're using Rails, you can now set up your routes just like any old ActiveRecord resource and access the Chapters as expected. Even if you weren't using Rails, PermanentRecord still provides some retrieval helpers that might be handy for your next project.

Retrieving Data

There are a few options for retrieving data which should all look pretty familiar if you're used to working with ActiveRecord:

Find everything in one fell swoop:

Chapter.all
# => [#<Chapter id: 1, title: 'Introduction', ...>, #<Chapter id: 2, title: 'Chapter 1', ...>, ...]

Find a single record by id:

Chapter.find(2)
# => #<Chapter id: 2, title: 'Chapter 1', ...>

Find many records by a specific attribute or attributes:

Chapter.where(title: 'Chapter 1', subtitle: 'What is Ruby?')
# => [#<Chapter id: 2, title: 'Chapter 1', ...>]

Or use the find_by_<attribute> syntax to find a single record by a single attribute:

Chapter.find_by_subtitle('What is Ruby?')
# => #<Chapter id: 2, title: 'Chapter 1', ...>

Explicitly Declaring a Data Source

If you have a specific constant you'd like to use other than the pluralized version of your model name - CHAPTERS in our case - you can declare it in your model explicitly with source:

class Chapter < PermanentRecord
  source MY_CHAPTERS
end

You could even do something as daft as supplying the data directly:

class Chapter < PermanentRecord
  # NOTE: You probably shouldn't actually do this.
  source [{title: 'Intro'}, {title: 'Chapter 1'}, ...]
end

Or maybe you'd prefer to save your data in a YAML file instead of a constant:

# config/data/chapters.yml
- title: 'Introduction'
  subtitle: ''
- title: 'Chapter 1'
  subtitle: 'What is Ruby?'
- title: 'Chapter 2'
  subtitle: 'What is Ruby on Rails?'
  ...

Now just load the data the standard YAML way and let your PermanentRecord class know about it:

  class Chapter < PermanentRecord
    source YAML.load(File.read('config/data/chapters.yml'))
  end

Personally I like using Ruby where possible, which is why I prefer saving data in constants. But not everyone feels the same way as me ... just make sure the data is a well formed array of hashes and PermanentRecord will be happy.

CRUD-ing

Note that PermanentRecord is a READ ONLY system - meaning you're only getting the R part of CRUD. If you need to create/update/delete your data, you'll need to do it the old fashioned way by manually changing the file your data is stored in, saving and re-deploying your application. PermanentRecord is for permanent data: it shouldn't be changing very often, and there shouldn't be very much of it. If you find yourself wanting to CRUD often, you should probably just set up a database.

Compatibility

This gem was created for Rails 4 && Ruby 2. It's very possible it could work with older releases. You'll have to test to determine compatibility!

Other Projects

If you're looking for a simple DB-less way to store data, but you'd also like to CRUD it, you should check out YAML Record by Nico Taing. I took a few ideas from there when creating PermanentRecord, thanks guys! Some other folks have also created gems that attempt to solve the same problem as PermanentRecord. For example, ConstantRecord by Christoph Petschnig (maybe out of date) and Constant Record by Nate Wiger. Their gems might even be better than mine, have a look!

License, etc

PermanentRecord is open and free for all. Please use, fork, update, critique, send pull requests, etc. This gem was created because it was useful for my project, so maybe you'll find it useful too. If not, no worries! I can't believe you read this far though.