0.0
Low commit activity in last 3 years
A long-lived project that still receives updates
Easy way to create models from payloads
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies
 Project Readme

Schema

A powerful Ruby gem for data transformation, validation, and type safety. Schema provides a flexible and intuitive way to define data models with support for complex nested structures, dynamic associations, and robust validation.

Build Status Maintainability Test Coverage

Features

  • Type Safety: Strong typing with automatic parsing and validation
  • Flexible Attributes: Support for aliases and custom data types
  • Nested Models: Complex data structures with nested associations
  • Dynamic Associations: Runtime type-based model creation
  • ActiveModel Integration: Seamless integration with ActiveModel validations
  • Error Handling: Comprehensive error collection and reporting
  • CSV Support: Built-in CSV parsing capabilities

Installation

Add this line to your application's Gemfile:

gem 'schema-model'

And then execute:

$ bundle install

Quick Start

Here's a simple example to get you started:

class UserSchema
  include Schema::All

  attribute :name, :string
  attribute :age, :integer
  attribute :email, :string
  attribute :tags, :array, separator: ',', data_type: :string

  validates :name, presence: true
  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
end

# Usage
user_data = {
  name: 'John Doe',
  age: '30',
  email: 'john@example.com',
  tags: 'ruby,rails,developer'
}

user = UserSchema.from_hash(user_data)
if user.valid?
  puts "User created: #{user.name}"
else
  puts "Validation errors: #{user.errors.full_messages}"
end

Core Concepts

Attributes

Attributes define the structure of your data model. Each attribute has:

  • A name
  • A type
  • Optional aliases
  • Custom parsing rules
attribute :name, :string, alias: 'FullName'
attribute :age, :integer
attribute :tags, :array, separator: ',', data_type: :string

Associations

Schema supports various types of associations:

  1. Has One: Single nested model
  2. Has Many: Multiple nested models
  3. Dynamic Associations: Type-based model creation
has_one(:profile) do
  attribute :bio, :string
  attribute :website, :string
end

has_many(:posts) do
  attribute :title, :string
  attribute :content, :string
end

Dynamic Types

Create different model structures based on a type field:

has_many(:vehicles, type_field: :type) do
  attribute :type, :string
  attribute :color, :string

  add_type('car') do
    attribute :doors, :integer
  end

  add_type('truck') do
    attribute :bed_length, :float
  end
end

Advanced Features

Custom Parsers

Define custom parsing logic for your attributes:

attribute :custom_field, :custom_type do
  def parse_custom_type(field_name, errors, value)
    # Custom parsing logic
  end
end

CSV Integration

Parse CSV data directly into your models:

class UserCSVSchema
  include Schema::CSVParser
  
  attribute :name, :string
  attribute :email, :string
end

users = UserCSVSchema.parse_csv(csv_data)

Using skip_fields to Protect Internal Fields

When instantiating a schema with from_hash, you can use the skip_fields argument to prevent certain fields (such as id, created_at, updated_at) from being set by user input. This is especially useful for fields managed by the database or internal logic, ensuring end users cannot override these values.

Example:

user_data = {
  id: 123, # Should be managed by DB
  name: 'John Doe',
  email: 'john@example.com',
  created_at: '2024-06-01T12:00:00Z', # Should be managed by DB
  updated_at: '2024-06-01T12:00:00Z'  # Should be managed by DB
}

# Skip DB-managed fields
user = UserSchema.from_hash(user_data, [:id, :created_at, :updated_at])

puts user.id          # => nil (not set from user input)
puts user.created_at  # => nil (not set from user input)
puts user.updated_at  # => nil (not set from user input)
puts user.name        # => 'John Doe'

Benefit:

  • Prevents end users from setting or changing internal DB values.
  • Ensures only safe, intended fields are settable from external input.
  • Helps maintain data integrity and security in your application.

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

License

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