{"id":13395451,"url":"https://github.com/pauldowman/gitmodel","last_synced_at":"2025-05-16T05:04:15.244Z","repository":{"id":1171948,"uuid":"1066410","full_name":"pauldowman/gitmodel","owner":"pauldowman","description":"(Old/dead) An ActiveModel-compliant persistence framework for Ruby that uses Git for versioning and remote syncing.","archived":false,"fork":false,"pushed_at":"2023-01-18T18:51:51.000Z","size":66,"stargazers_count":531,"open_issues_count":12,"forks_count":31,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-16T05:04:08.176Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pauldowman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-11-09T21:18:53.000Z","updated_at":"2024-09-21T18:07:08.000Z","dependencies_parsed_at":"2023-02-10T16:55:11.088Z","dependency_job_id":null,"html_url":"https://github.com/pauldowman/gitmodel","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldowman%2Fgitmodel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldowman%2Fgitmodel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldowman%2Fgitmodel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldowman%2Fgitmodel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pauldowman","download_url":"https://codeload.github.com/pauldowman/gitmodel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471061,"owners_count":22076585,"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","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-07-30T17:01:59.272Z","updated_at":"2025-05-16T05:04:15.222Z","avatar_url":"https://github.com/pauldowman.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"GitModel: distributed, versioned NoSQL for Ruby\n---------------------------------------------------\n\n_http://github.com/pauldowman/gitmodel_\n\nGitModel is an\n[ActiveModel](http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/)-compliant\npersistence framework for Ruby that uses [Git](http://git-scm.com/) for\nversioning and remote syncing.\n\nGitModel persists Ruby objects using Git as a data storage engine. It's an\nActiveModel implementation so it works stand-alone or in Rails 3 as a drop-in\nreplacement for ActiveRecord or DataMapper. \n\nBecause the database is a Git repository it can be synced across multiple\nmachines, manipulated with standard Git client tools, can be branched and\nmerged, and of course keeps the history of all changes.\n\n\nWhy it's awesome\n----------------\n\n* Schema-less NoSQL data store\n* Each record is a normal Ruby object, attributes are any Ruby type or large\n  chunks of binary data\n* Never lose data, history is kept forever and can be restored simply using\n  standard Git tools\n* Branch and merge your production data \n  * GitModel can actually work with different branches\n  * Branch or tag snapshots of your data\n  * Experiment on production data using branches, for example to test a\n    migration\n* Distributed (synced using standard Git push/pull)\n* All ActiveModel \n* Transactions\n* Metadata for all database changes (Git commit messages, date \u0026 time, etc.)\n* In order to be easily human-editable, the database is simply files and\n  directores stored in a Git repository.  GitModel uses the Git repo directly\n  (rather than Git's checked-out \"working copy\") but you can do a \"git\n  checkout\" to view and manipulate the database contents, and then \"git commit\"\n* Test-driven development and excellent test coverage\n* Clean and easy-to-use API\n\n\nStatus\n------\n\n_It is not yet production ready but I'm working on it. Please feel free to\ncontribute tests and/or code to help!_\n\nI will attempt to follow [Semantic Versioning](http://semver.org/) so 1.0.0\nwill be considered the first stable release, until then the API may change at\nany time.\n\nSee the \"To do\" section below for details, but the main thing that needs\nfinishing is support for querying. Right now you can find an instance by it's\nid, but there is incomplete support (90% complete) for querying, e.g.:\n\n```ruby\nPost.find(:category =\u003e 'ruby', :date =\u003e lambda{|d| d \u003e 1.month.ago} :order_by =\u003e :date, :order =\u003e :asc, :limit =\u003e 5)\n```\n\nThis includes support for indexing all attributes so that queries don't need to\nload every object.\n\n\nInstallation\n------------\n\nIt's available as a [RubyGem](https://rubygems.org/gems/gitmodel):\n\n    \u003e gem install gitmodel\n\n\nUsage\n-----\n\n```ruby\nGitModel.db_root = '/tmp/gitmodel-data'\nGitModel.create_db!\n\nclass Post\n  include GitModel::Persistable\n\n  attribute :title\n  attribute :body\n  attribute :categories, :default =\u003e []\n  attribute :allow_comments, :default =\u003e true\n\n  blob :image\nend\n\np1 = Post.new(:id =\u003e 'lessons-learned', :title =\u003e 'Lessons learned', :body =\u003e '...')\np1.image = some_binary_data\np1.save!\n\np = Post.find('lessons-learned')\n\np2 = Post.new(:id =\u003e 'hotdog-eating-contest', :title =\u003e 'I won!')\np2.body = 'This weekend I won a hotdog eating contest!'\np2.image = some_binary_data\np2.blobs['hotdogs.jpg'] = some_binary_data\np2.blobs['the-aftermath.jpg'] = some_binary_data\np2.save!\n\np3 = Post.create!(:id =\u003e 'running-with-scissors', :title =\u003e 'Running with scissors', :body =\u003e '...')\n\np4 = Post.find('running-with-scissors')\n\nclass Comment\n  include GitModel::Persistable\n  attribute :text\nend\n\nc1 = Comment.create!(:id =\u003e '2010-01-03-328', :text =\u003e '...')\nc2 = Comment.create!(:id =\u003e '2010-05-29-742', :text =\u003e '...')\n```\n\n\nAn example of a project that uses GitModel is [Balisong](https://github.com/pauldowman/balisong), a blogging app for coders (but it doesn't save objects to the data store. It's read-only so far, assuming that posts will be edited with a text editor).\n\n\nDatabase file structure\n-----------------------\n\nThe database is stored in a human-editable format. Simply do \"git checkout -f\"\nand you'll see directories and files.\n\nEach type of object is stored in a top-level directory (this is analogous to\nActiveRecord tables), and each object is stored in a subdirectory which is\nnamed using the object's id (i.e. the primary key). Attributes that are Ruby\ntypes (strings, numbers, hashes, arrays, whatever) are stored in a file named\nattributes.json and binary attributes (\"blobs\") are stored in their own\nfiles.\n\nFor example, the database for the example above would have a directory\nstructure that looks like this:\n\n* db-root \n    * comments \n        * 2010-01-03-328\n            * _attributes.json_\n        * 2010-05-29-742\n            * _attributes.json_\n    * posts \n        * hotdog-eating-contest\n            * _attributes.json_\n            * _hotdogs.jpg_\n            * _image_\n            * _the-aftermath.jpg_\n        * lessons-learned\n            * _attributes.json_\n            * _image_\n        * running-with-scissors\n            * _attributes.json_\n\n\nPerformance\n-----------\n\nGitModel supports memcached for query results. This is off by default, but can be configured like this:\n\n```ruby\nGitModel.memcache_servers(['server_1', 'server_2', ...])\nGitModel.memcache_namespace('optional_namespace')\n```\n\nThe namespace is optional, and usually not necessary because GitModel will prepend the last segment of GitModel.db_root anyway.\n\nA Git SHA is also prepended to every key, so that outdated versions will not be retrieved from the cache. This is the SHA of the latest commit so unfortunately this is only useful when there are not frequent commits because every commit invalidates the cache. (This is obviously not ideal and I'm sure it can be improved upon.)\n\nThere is still a lot of work to be done to make it faster. First, some analysis is required, but some guesses about things that would help are:\n\n* Use [Rugged](https://github.com/libgit2/rugged) instead of Grit\n* Remove the transaction lock (see transaction.rb line 19)\n* Ability to iterate over result set without eager loading of all instances\n\n\nContributing\n------------\n\nDo you have an improvement to make? Please submit a pull request on GitHub or a\npatch, including a test written with RSpec.  To run all tests simply run\n`bundle exec autotest`.\n\nThe main author is [Paul Dowman](http://pauldowman.com/about) ([@pauldowman](http://twitter.com/pauldowman)).\n\nThanks to everyone who has contributed so far:\n\n* [Alex Bartlow](https://github.com/alexbartlow)\n* [Daniel Russo](https://github.com/drusso)\n\n\nTo do\n-----\n\n* Finish Query support\n    * Update index (efficiently) when Persistable objects are saved\n    * Add Rake task to generate index\n    * Update README\n* Add validations and other feature examples to sample code in README\n* Finish some pending specs\n* API documentation\n* Rails integration\n    * Generators\n    * Rake tasks\n* Performance\n* Persistable.find/find_all/etc could be based on staged files so that queries reflect uncommitted changes\n* Better query support\n    * Associations\n    * Use AREL?\n\n\nBugs\n------------\n\n* Grit 2.4.1 has [an issue with non-ASCII characters](https://github.com/mojombo/grit/commit/696761d8047ffd038dc2828e6a1998e3f7c3b419)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauldowman%2Fgitmodel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpauldowman%2Fgitmodel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauldowman%2Fgitmodel/lists"}