{"id":15063673,"url":"https://github.com/rdf-elixir/grax","last_synced_at":"2025-04-07T09:15:53.328Z","repository":{"id":37083222,"uuid":"323320595","full_name":"rdf-elixir/grax","owner":"rdf-elixir","description":"An RDF graph data mapper for Elixir","archived":false,"fork":false,"pushed_at":"2025-03-10T19:42:46.000Z","size":432,"stargazers_count":33,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-31T08:07:53.774Z","etag":null,"topics":["data-mapper","elixir","graphs","rdf"],"latest_commit_sha":null,"homepage":"https://rdf-elixir.dev/","language":"Elixir","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/rdf-elixir.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-21T11:47:13.000Z","updated_at":"2025-03-10T19:42:51.000Z","dependencies_parsed_at":"2024-12-17T18:11:23.777Z","dependency_job_id":"cff128c7-b8fc-4b31-bf67-973ec0d885ad","html_url":"https://github.com/rdf-elixir/grax","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdf-elixir%2Fgrax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdf-elixir%2Fgrax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdf-elixir%2Fgrax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdf-elixir%2Fgrax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rdf-elixir","download_url":"https://codeload.github.com/rdf-elixir/grax/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247622988,"owners_count":20968575,"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":["data-mapper","elixir","graphs","rdf"],"created_at":"2024-09-25T00:05:54.764Z","updated_at":"2025-04-07T09:15:53.287Z","avatar_url":"https://github.com/rdf-elixir.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Grax\n\n[![Hex.pm](https://img.shields.io/hexpm/v/grax.svg?style=flat-square)](https://hex.pm/packages/grax)\n[![License](https://img.shields.io/hexpm/l/grax.svg)](https://github.com/rdf-elixir/grax/blob/master/LICENSE.md)\n\n[![ExUnit Tests](https://github.com/rdf-elixir/grax/actions/workflows/elixir-build-and-test.yml/badge.svg)](https://github.com/rdf-elixir/grax/actions/workflows/elixir-build-and-test.yml)\n[![Dialyzer](https://github.com/rdf-elixir/grax/actions/workflows/elixir-dialyzer.yml/badge.svg)](https://github.com/rdf-elixir/grax/actions/workflows/elixir-dialyzer.yml)\n[![Quality Checks](https://github.com/rdf-elixir/grax/actions/workflows/elixir-quality-checks.yml/badge.svg)](https://github.com/rdf-elixir/grax/actions/workflows/elixir-quality-checks.yml)\n\n\nA light-weight graph data mapper which maps RDF graph data from [RDF.ex] data structures to schema-conform Elixir structs and vice versa.\n\nFor a guide and more information about Grax, and it's related projects, go to \u003chttps://rdf-elixir.dev/grax/\u003e.\n\n\n## Usage\n\nLet's assume we have a graph like this:\n\n```ttl\n{:ok, graph} =\n  \"\"\"\n  @prefix : \u003chttp://example.com/\u003e .\n  @prefix schema: \u003chttps://schema.org/\u003e .\n  @prefix foaf: \u003chttp://xmlns.com/foaf/0.1/\u003e .\n  \n  :User1\n      schema:name \"Jane\" ;\n      schema:email \"jane@example.com\" ;\n      foaf:age 30 ;\n      foaf:friend :User2.\n  \n  :Post1\n      schema:author :User1 ;\n      schema:name \"Lorem\" ;\n      schema:articleBody \"\"\"Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, nihil, dignissimos. Nesciunt aut totam eius. Magnam quaerat modi vel sed, ipsam atque rem, eos vero ducimus beatae harum explicabo labore!\"\"\" .\n    \n    # ...\n  \"\"\"\n  |\u003e RDF.Turtle.read_string()\n```\n\nGrax allows us to define a schema for the mapping of this kind of data to Elixir structs.\n\n```elixir\ndefmodule User do\n  use Grax.Schema\n\n  alias NS.{SchemaOrg, FOAF}\n\n  schema SchemaOrg.Person do\n    property name: SchemaOrg.name, type: :string\n    property email: SchemaOrg.email, type: :string\n    property age: FOAF.age, type: :integer\n    \n    link friends: FOAF.friend, type: list_of(User)\n    link posts: -SchemaOrg.author, type: list_of(Post)\n\n    field :password\n  end\nend\n\ndefmodule Post do\n  use Grax.Schema\n\n  alias NS.SchemaOrg\n\n  schema SchemaOrg.BlogPosting do\n    property title: SchemaOrg.name(), type: :string\n    property content: SchemaOrg.articleBody(), type: :string\n\n    link author: SchemaOrg.author(), type: User\n  end\nend\n```\n\nWith that we can create an instance of our `User` struct from an `RDF.Graph`.\n\n```elixir\niex\u003e User.load(graph, EX.User1)\n{:ok,\n %User{\n   __id__: ~I\u003chttp://example.com/User1\u003e,\n   age: nil,\n   email: [\"jane@example.com\", \"jane@work.com\"],\n   friends: [],\n   name: \"Jane\",\n   password: nil,\n   posts: [\n     %Post{\n       __id__: ~I\u003chttp://example.com/Post1\u003e,\n       author: ~I\u003chttp://example.com/User1\u003e,\n       content: \"Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, nihil, dignissimos. Nesciunt aut totam eius. Magnam quaerat modi vel sed, ipsam atque rem, eos vero ducimus beatae harum explicabo labore!\",\n       title: \"Lorem\"\n     }\n   ]\n }}\n```\n\nAnd do some transformation on the struct and write it back to an RDF graph.\n\n```elixir\nuser\n|\u003e Grax.put!(:age, user.age + 1)\n|\u003e Grax.to_rdf!()\n|\u003e RDF.Serialization.write_file!(\"user.ttl\")\n```\n\n\n## Future Work\n\n- I18n support (localization with language-tagged string literals)\n- Storage adapters (e.g. accessing SPARQL endpoints directly and support for non-RDF-based graph databases)\n- RDFS support (e.g. for class-based query builders)\n- More preloading strategies (eg. pattern- and path-based preloading)\n\n\n## Contributing\n\nSee [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n\n## Acknowledgements\n\nThe development of this project was sponsored by [NetzeBW](https://www.netze-bw.de/) for [NETZlive](https://www.netze-bw.de/unsernetz/netzinnovationen/digitalisierung/netzlive).\n\n\n## Consulting\n\nIf you need help with your Elixir and Linked Data projects, just contact [NinjaConcept](https://www.ninjaconcept.com/) via \u003ccontact@ninjaconcept.com\u003e.\n\n\n## License and Copyright\n\n(c) 2020-present Marcel Otto. MIT Licensed, see [LICENSE](LICENSE.md) for details.\n\n\n[RDF.ex]:               https://github.com/rdf-elixir/rdf-ex\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frdf-elixir%2Fgrax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frdf-elixir%2Fgrax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frdf-elixir%2Fgrax/lists"}