StaticModel
Read-only ActiveRecord-like interface to query static YAML files.
Installation
Add this line to your application's Gemfile:
gem "staticmodel"
And then execute:
$ bundle
Or install it yourself as:
$ gem install staticmodel
Usage
StaticModel usage is pretty similar to ActiveRecord. Although the gem was designed with Rails in mind, it can be used in any Ruby project.
To start using StaticModel you need to:
- Inherit from
StaticModel::Base
. - Define the source of your data.
- Define your attributes and/or your default values.
Inherit from StaticModel::Base
Just like with ActiveRecord, your models need to inherit from StaticModel::Base
.
require "staticmodel"
class Country < StaticModel::Base
end
Primary key
StaticModel assumes that each model can be identified by a primary key. A model instance’s primary key is always available as model.id
whether you name it the default id
or set it to something else.
It's possible to override the attribute that should be used as the model's primary key using the primary_key=
method:
class Country < ActiveRecord::Base
self.primary_key = "code"
attribute :code, String
attribute :name, String
end
Country.all
# => [
# #<Country code="ES", name="Spain">,
# #<Country code="NL", name="Netherlands">
# ]
Country.primary_key # => "code"
country = Country.find("ES") # => #<Country code="ES", name="Spain">
country.id # => "ES"
contry.name # => "Spain"
Or you can also override the primary_key
method yourself:
class Country < ActiveRecord::Base
def self.primary_key
"code"
end
attribute :code, String
attribute :name, String
end
Country.primary_key # => "code"
Levels of inheritance
StaticModel also supports several levels of inheritance:
require "staticmodel"
class Country < StaticModel::Base
self.primary_key = "code"
attribute :code, String
attribute :name, String
end
class MyCountry < Country
end
class MyOtherCountry < Country
self.primary_key = "my_other_code"
end
MyCountry.primary_key # => "code"
MyOtherCountry.primary_key # => "my_other_code"
Define the source of your data
By default, StaticModel uses a naming convention to find out how the mapping between models and YAML files should be created. It will pluralize your class names to find the respective YAML file. So, for a class Book, you should have a YAML file called books. The StaticModel pluralization mechanisms are based on ActiveSupport which is very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the CamelCase form, while the file name must contain the words separated by underscores. Examples:
- YAML file - Plural with underscores separating words (e.g., book_clubs).
- Model Class - Singular with the first letter of each word capitalized (e.g., BookClub).
It's very common to organize all your YAML files into a single directory. To tell StaticModel where it can find your static files you can specify the load path anywhere in your code with:
StaticModel.configure do |config|
config.base_data_path = File.join(Rails.root, "config/data")
end
If your YAML files are not located in the same directory or you don't want to follow the naming conventions, you can define per model the specific YAML file's path with the data_path=
method:
class Country < StaticModel::Base
self.data_path = File.join(Rails.root, "config/data/countries.yml")
end
YAML format
The format of the YAML file is very simple, an array of hashes. This could be an example for a countries.yml
file:
---
- code: ES
name: Spain
population: 46770000
- code: NL
name: Netherlands
population: 16800000
Define your attributes and/or your default values
StaticModel depends on the well-written Virtus gem to define its attributes. Here is a basic example of the flexibility that it provides:
class Country < StaticModel::Base
attribute :id, String
attribute :name, String
attribute :population, Integer, default: 0
attribute :european, Boolean, default: false
attribute :province_names, Array[String]
end
country = Country.all.first
country.id # => "ES"
country.name # => "Spain"
country.population # => 46770000
country.european # => true
country.province_names # => ["Madrid", "Barcelona", ...]
Advanced usage of the StaticModel attributes can be found at the Virtus documentation.
Query interface
all
Returns all the records.
Country.all
# => [
# #<Country id="ES", name="Spain" european=true>,
# #<Country id="NL", name="Netherlands" european=true>,
# #<Country id="CO", name="Colombia" european=true>
# ]
where(criteria)
The where
method allows you to specify conditions to limit the records returned, like the WHERE
-part of the SQL statement. Conditions must be specified as a hash.
Country.where(european: true)
# => [
# #<Country id="ES", name="Spain" european=true>,
# #<Country id="NL", name="Netherlands" european=true>
# ]
find(id)
Using the find
method, you can retrieve the object corresponding to the specified primary key that matches the supplied id
.
Country.find("ES") # => #<Country id="ES", name="Spain">
Country.find("KO") # => StaticModel::NotFound
The find
method will raise a StaticModel::NotFound
exception if no matching record is found.
find_by(criteria)
The find_by
method finds the first record matching some conditions.
Country.find_by(name: "Spain") # => #<Country id="ES", name="Spain">
Country.find_by(name: "Invalid") # => nil
find_by!(criteria)
The find_by!
method behaves exactly like find_by
, except that it will raise StaticModel::NotFound
if no matching record is found.
Country.find_by!(name: "Spain") # => #<Country id="ES", name="Spain">
Country.find_by!(name: "Invalid") # => StaticModel::NotFound
exists?(criteria)
If you simply want to check for the existence of the object there's a method called exists?
. This method will use the same mechanism as find
, but instead of returning an object it will return either true
or false
.
Country.exists?(name: "Spain") # => true
Country.exists?(name: "Invalid") # => false
Development
After checking out the repo, run script/setup
to install dependencies. Then, run rake test
to run the tests. You can also run script/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/fertapric/staticmodel. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Author
Fernando Tapia Rico, @fertapric