lutaml / lutaml-model

LutaML Model is the Ruby data modeler part of the LutaML data modeling suite. It supports creating serialization object models (XML, YAML, JSON, TOML) and mappings to and from them.
1 stars 0 forks source link

= LutaML Ruby modeller: Lutaml::Model

https://github.com/lutaml/lutaml-model[image:https://img.shields.io/github/stars/lutaml/lutaml-model.svg?style=social[GitHub Stars]] https://github.com/lutaml/lutaml-model[image:https://img.shields.io/github/forks/lutaml/lutaml-model.svg?style=social[GitHub Forks]] image:https://img.shields.io/github/license/lutaml/lutaml-model.svg[License] image:https://img.shields.io/github/actions/workflow/status/lutaml/lutaml-model/test.yml?branch=main[Build Status] image:https://img.shields.io/gem/v/lutaml-model.svg[RubyGems Version]

== What is Lutaml::Model

Lutaml::Model is a lightweight library for serializing and deserializing Ruby objects to and from various formats such as JSON, XML, YAML, and TOML. It uses an adapter pattern to support multiple libraries for each format, providing flexibility and extensibility for your data modeling needs.

The name "LutaML" comes from the Latin word "Lutum," which means clay, and "ML" for Markup Language. Just as clay can be molded and modeled into beautiful and practical end products, the Lutaml::Model gem is used for data modeling, allowing you to shape and structure your data into useful forms.

NOTE: Lutaml::Model is designed to be compatible with the Shale data modeling API. Shale is an amazing Ruby data modeller. Lutaml::Model is meant to address needs that are not currently addresed by Shale.

== Introduction to Data Modeling

Data modeling is the process of creating a data model for the data to be stored in a database or used in an application. It helps in defining the structure, relationships, and constraints of the data, making it easier to manage and use.

Lutaml::Model simplifies data modeling in Ruby by allowing you to define models with attributes and serialize/deserialize them to/from various formats seamlessly.

== Features

== Installation

Add this line to your application's Gemfile:

[source,ruby]

gem 'lutaml-model'

And then execute:

[source,shell]

bundle install

Or install it yourself as:

[source,shell]

gem install lutaml-model

== Writing a Data Model in Ruby

To define a model, inherit from Lutaml::Model::Serializable and use the attribute class method to define attributes.

[source,ruby]

require 'lutaml/model'

class Kiln < Lutaml::Model::Serializable attribute :brand, Lutaml::Model::Type::String attribute :capacity, Lutaml::Model::Type::Integer attribute :temperature, Lutaml::Model::Type::Integer end

== Translating a Data Model into Different Serialization Models

Lutaml::Model allows you to translate a data model into various serialization formats including XML, JSON, YAML, and TOML.

=== XML: Element, Attribute, Namespaces

Define XML mappings using map_element, map_attribute, and map_content.

[source,ruby]

class Example < Lutaml::Model::Serializable attribute :name, Lutaml::Model::Type::String attribute :value, Lutaml::Model::Type::Integer

xml do root 'example' map_element 'name', to: :name map_attribute 'value', to: :value end end

=== Key Value Data Models: JSON, YAML, TOML

Define key-value data models like JSON, YAML, and TOML using the map method.

[source,ruby]

class Example < Lutaml::Model::Serializable attribute :name, Lutaml::Model::Type::String attribute :value, Lutaml::Model::Type::Integer

json do map 'name', to: :name map 'value', to: :value end

yaml do map 'name', to: :name map 'value', to: :value end

toml do map 'name', to: :name map 'value', to: :value end end

== Develop Serialization and Deserialization Mappings

Lutaml::Model supports various methods for defining serialization and deserialization mappings.

=== XML (map_element, map_attribute, map_content)

Use map_element to map XML elements, map_attribute to map XML attributes, and map_content to map text content within an XML element.

[source,ruby]

class Example < Lutaml::Model::Serializable attribute :name, Lutaml::Model::Type::String attribute :description, Lutaml::Model::Type::String

xml do root 'example' map_element 'name', to: :name map_content to: :description end end

=== JSON (map method)

Use the map method to define JSON mappings.

[source,ruby]

class Example < Lutaml::Model::Serializable attribute :name, Lutaml::Model::Type::String attribute :value, Lutaml::Model::Type::Integer

json do map 'name', to: :name map 'value', to: :value end end

=== YAML

Use the map method to define YAML mappings.

[source,ruby]

class Example < Lutaml::Model::Serializable attribute :name, Lutaml::Model::Type::String attribute :value, Lutaml::Model::Type::Integer

yaml do map 'name', to: :name map 'value', to: :value end end

=== TOML

Use the map method to define TOML mappings.

[source,ruby]

class Example < Lutaml::Model::Serializable attribute :name, Lutaml::Model::Type::String attribute :value, Lutaml::Model::Type::Integer

toml do map 'name', to: :name map 'value', to: :value end end

== Attribute Collections Using the collection Option

You can define attributes as collections (arrays or hashes) to store multiple values.

[source,ruby]

class Studio < Lutaml::Model::Serializable attribute :location, Lutaml::Model::Type::String attribute :potters, Lutaml::Model::Type::String, collection: true end

== Attribute Defaults Using the default Option

Specify default values for attributes using the default option.

[source,ruby]

class Glaze < Lutaml::Model::Serializable attribute :color, Lutaml::Model::Type::String, default: -> { 'Clear' } attribute :temperature, Lutaml::Model::Type::Integer, default: -> { 1050 } end

== Attribute Delegation Using the delegate Option

Delegate attribute mappings to nested objects using the delegate option.

[source,ruby]

class Ceramic < Lutaml::Model::Serializable attribute :type, Lutaml::Model::Type::String attribute :glaze, Glaze

json do map 'type', to: :type map 'color', to: :color, delegate: :glaze end end

== Attribute Serialization with Custom from and to Methods

Define custom methods for specific attribute mappings using the with: key for each serialization mapping block.

[source,ruby]

class CustomCeramic < Lutaml::Model::Serializable attribute :name, Lutaml::Model::Type::String attribute :size, Lutaml::Model::Type::Integer

json do map 'name', to: :name, with: { to: :name_to_json, from: :name_from_json } map 'size', to: :size end

def name_to_json(model, value) "Masterpiece: #{value}" end

def name_from_json(model, doc) doc['name'].sub('Masterpiece: ', '') end end

== Using XML Namespaces

Define XML namespaces for your models to handle namespaced XML elements.

=== XML Namespace on Element

[source,ruby]

class Ceramic < Lutaml::Model::Serializable attribute :type, Lutaml::Model::Type::String attribute :glaze, Lutaml::Model::Type::String

xml do root 'Ceramic' namespace 'http://example.com/ceramic' map_element 'Type', to: :type map_element 'Glaze', to: :glaze end end

=== XML Namespace on Attribute

[source,ruby]

class Ceramic < Lutaml::Model::Serializable attribute :type, Lutaml::Model::Type::String attribute :glaze, Lutaml::Model::Type::String

xml do root 'Ceramic' map_element 'Type', to: :type map_element 'Glaze', to: :glaze map_attribute 'xmlns', to: :namespace, namespace: 'http://example.com/ceramic' end end

=== XML Namespace with inherit Option

[source,ruby]

class Ceramic < Lutaml::Model::Serializable attribute :type, Lutaml::Model::Type::String attribute :glaze, Lutaml::Model::Type::String

xml do root 'Ceramic' namespace 'http://example.com/ceramic', prefix: 'cera' map_element 'Type', to: :type, namespace: :inherit map_element 'Glaze', to: :glaze end end

== Adapters

Lutaml::Model uses an adapter pattern to support multiple libraries for each serialization format.

=== XML: Nokogiri, Oga, Ox

[source,ruby]

require 'lutaml/model' require 'lutaml/model/xml_adapter/nokogiri_adapter' require 'lutaml/model/xml_adapter/ox_adapter' require 'lutaml/model/xml_adapter/oga_adapter'

Lutaml::Model::Config.configure do |config| config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter

Or use OxAdapter or OgaAdapter

end

=== JSON: JSON and MultiJson

[source,ruby]

require 'lutaml/model' require 'lutaml/model/json_adapter/standard' require 'lutaml/model/json_adapter/multi_json'

Lutaml::Model::Config.configure do |config| config.json_adapter = Lutaml::Model::JsonAdapter::StandardDocument

Or use MultiJsonDocument

end

=== TOML: Tomlib and Toml-rb

[source,ruby]

require 'lutaml/model' require 'lutaml/model/toml_adapter/toml_rb_adapter' require 'lutaml/model/toml_adapter/tomlib_adapter'

Lutaml::Model::Config.configure do |config| config.toml_adapter = Lutaml::Model::TomlAdapter::TomlRbDocument

Or use TomlibDocument

end

== License and Copyright

This project is licensed under the BSD 2-clause License - see the LICENSE file for details.

This project is maintained by Ribose.