{"id":16102422,"url":"https://github.com/sshaw/ddex","last_synced_at":"2025-04-07T13:08:44.058Z","repository":{"id":9517549,"uuid":"11415004","full_name":"sshaw/ddex","owner":"sshaw","description":"DDEX metadata serialization for Ruby","archived":false,"fork":false,"pushed_at":"2023-12-30T23:28:46.000Z","size":3496,"stargazers_count":56,"open_issues_count":6,"forks_count":39,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-03-31T11:08:05.084Z","etag":null,"topics":["ddex","ebooks","grid-number","metadata","music","ruby","video","xml","xml-serialization"],"latest_commit_sha":null,"homepage":"https://metadatagui.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sshaw.png","metadata":{"files":{"readme":"README.rdoc","changelog":"Changes","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2013-07-15T04:52:57.000Z","updated_at":"2024-12-27T02:34:33.000Z","dependencies_parsed_at":"2023-12-31T00:36:00.645Z","dependency_job_id":null,"html_url":"https://github.com/sshaw/ddex","commit_stats":{"total_commits":152,"total_committers":6,"mean_commits":"25.333333333333332","dds":"0.11184210526315785","last_synced_commit":"e22034dc617e82a96a87078285ae8753b813e173"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshaw%2Fddex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshaw%2Fddex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshaw%2Fddex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshaw%2Fddex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sshaw","download_url":"https://codeload.github.com/sshaw/ddex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247657281,"owners_count":20974345,"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":["ddex","ebooks","grid-number","metadata","music","ruby","video","xml","xml-serialization"],"created_at":"2024-10-09T18:53:46.530Z","updated_at":"2025-04-07T13:08:44.040Z","avatar_url":"https://github.com/sshaw.png","language":"Ruby","readme":"= DDEX\n\n{\u003cimg src=\"https://github.com/sshaw/ddex/workflows/CI/badge.svg\"/\u003e}[https://github.com/sshaw/ddex/actions/workflows/ci.yml]\n\n{DDEX}[http://ddex.net] metadata serialization for Ruby\n\n=== Overview\n\n require \"ddex\"\n\n message = DDEX.read(\"path/to/metadata.xml\")  # ERN\n puts message.update_indicator\n message.resource_list.sound_recordings.each do |sr|\n   title = sr.reference_title.title_text\n   puts title.value\n   puts title.language_and_script_code\n   puts sr.remastered?\n end\n\n puts \"Supported!\" if DDEX.supports?(\"ern/341\")\n\n message = DDEX.read(string)\n message = DDEX.read(io)\n p message.to_hash\n\n include DDEX::ERN::V341   # v3.4.1\n message = NewReleaseMessage.new(:resource_list =\u003e ResourceList.new)\n record  = SoundRecording.new(:language_and_script_code =\u003e \"en-US\")\n # ...\n message.resource_list.sound_recordings = [record]\n\n xml = DDEX.write(message)\n File.open(\"bloat.xml\", \"w\") { |io| io.puts(xml) }\n\n=== Installation\n\nRubygems:\n\n  gem install ddex\n\nBundler:\n\n  gem \"ddex\"\n\n=== Supported Versions\n\nSee: https://github.com/sshaw/ddex/tree/master/lib/ddex\n\n=== How This Differs From the Spec\n\nEvery DDEX version handled by this module is fully supported, but there are some things you'll need to know.\n\n==== Naming Conventions\n\nDDEX elements and attributes use the {CamelCase naming convention}[https://en.wikipedia.org/wiki/CamelCase], this module uses Ruby naming conversions:\nCamelCase for classes, and {snake_case}[https://en.wikipedia.org/wiki/Snake_case] for class attributes. For example, this DDEX XML:\n\n  \u003cPartyName\u003e\n    \u003cFullName\u003esshaw\u003c/FullName\u003e\n  \u003c/PartyName\u003e\n\nWould be manipulated via:\n\n  party = PartyName.new(:full_name =\u003e \"sshaw\")\n  puts party.full_name\n  party.full_name = \"gwozdzie\"\n\n\nSee also {Boolean elements and attributes}[rdoc-ref:README@Boolean+Elements+and+Attributes]\n\n==== Cardinally\n\nElements that _can_ occur more than once will be placed in an \u003ccode\u003eArray\u003c/code\u003e and their parent classes' accessor methods will use the plural form of\nthe element/attribute's name. For example:\n\n  \u003cRelease\u003e\n    \u003c!-- More data --\u003e\n    \u003cPLine\u003e\n      \u003cYear\u003e1994\u003c/Year\u003e\n      \u003cPLineText\u003eTrack Copyright\u003c/PLineText\u003e\n    \u003c/PLine\u003e\n    \u003cPLine\u003e\n      \u003cYear\u003e2001\u003c/Year\u003e\n      \u003cPLineText\u003eAnother Track Copyright\u003c/PLineText\u003e\n    \u003c/PLine\u003e\n  \u003c/Release\u003e\n\nWould be manipulated via:\n\n  release.p_lines.each { |line| puts line.p_line_text }\n  release.p_lines \u003c\u003c PLine.new(:year =\u003e 1999)\n\n==== Boolean Elements and Attributes\n\nThe following are applied to accessors derived from DDEX elements and attributes with an XML schema type of +boolean+:\n\n* \u003ccode\u003e\"Is\"\u003c/code\u003e is removed from the beginning of the name\n* The *reader* *method* is turned into a predicate accessor, i.e., has a \u003ccode\u003e\"?\"\u003c/code\u003e appended to it\n\nFor example, \u003ccode\u003eSoundRecording/IsArtistRelated\u003c/code\u003e:\n\n  recording = SoundRecording.new(:artist_related =\u003e true)\n  p recording.artist_related?  # true\n  recording.artist_related = false\n\n==== Version Specific Changes\n\nThese changes only affect the object model, the resulting XML will conform to the appropriate DDEX schema.\n\n===== ERN \u003e= v3.6 \u003c v4.0\n\n\u003ccode\u003ePriceInformation/@PriceType\u003c/code\u003e has been renamed to \u003ccode\u003ePriceInformation#type\u003c/code\u003e to avoid conflicting with the\nelement of the same name (\u003ccode\u003ePriceInformation/PriceType\u003c/code\u003e).\n\n=== Specification Version Detection\n\nAn attempt is made to detect the version. How this is done varies by spec and version. See below for details.\n\nThe version can always be explicitly given to \u003ccode\u003eDDEX.read\u003c/code\u003e via the \u003ccode\u003e:version\u003c/code\u003e option.\n\n==== ERN \u003e= 4\n\nVersion is determined by the DDEX XML namespace associated with the doc.\n\nFor example, given a namespace of: \u003ccode\u003ehttp://ddex.net/xml/ern/41\u003c/code\u003e we'll try to match the end, either\n\u003ccode\u003e\"ern/41\"\u003c/code\u003e or \u003ccode\u003e\"ern/41/\"\u003c/code\u003e. The values used to match the come from\n\u003ccode\u003eDDEX::ERN.config[V][:message_schema_version_id]\u003c/code\u003e where \u003ccode\u003eV\u003c/code\u003e is a version string, e.g., \u003ccode\u003e\"V41\"\u003c/code\u003e.\n\n==== ERN \u003c 4\n\nThe version is detected based on the root element's value i.e., \u003ccode\u003e/node()/@MessageSchemaVersionId\u003c/code\u003e.\n\nBy default the \u003ccode\u003eMessageSchemaVersionId\u003c/code\u003e is assumed to be in \u003ccode\u003eSPEC/VERSION\u003c/code\u003e or \u003ccode\u003eVERSION\u003c/code\u003e format\n(any leading, trailing, or duplicate slashes will be stripped), as this seems to be the convention used by most instance docs -though the DDEX specifications\n{are not strict about this}[http://www.ddex.net/format-messageschemaversionid]. If you're dealing with \u003ccode\u003eMessageSchemaVersionId\u003c/code\u003es\nthat vary from this format, and explicitly setting the version is not practical, you can set the global default(s):\n\n  DDEX::ERN.config[\"V35\"][:message_schema_version_id] = \"ern tray_fever!\"\n  DDEX::ERN.config[\"V351\"][:message_schema_version_id] = \"ern/35-punto-1\"\n  # ...\n\nNote that the version key must match the version's module name.\n\n=== Validation\n\nNot yet!\n\n=== DDEX Parsing Service (Rack Endpoint)\n\nIf you want to parse DDEX metadata but don't want to use Ruby to process the results you can setup a parsing service\nusing \u003ccode\u003eRack::DDEX\u003c/code\u003e. \u003ccode\u003eRack::DDEX\u003c/code\u003e is a {Rack endpoint}[http://rack.github.io] that parses a DDEX file\nand returns JSON.\n\nFor example, from the repository's root:\n\n  ~/code/ruby/ddex \u003ecat etc/config.ru\n  require \"rack/ddex\"\n\n  run Rack::DDEX.new\n\n  ~/code/ruby/ddex \u003erackup -I lib etc/config.ru  # Note that -D has problems with autoloading\n  [2014-12-15 20:35:40] INFO  WEBrick 1.3.1\n  [2014-12-15 20:35:40] INFO  ruby 2.1.2 (2014-05-08) [x86_64-darwin13.0]\n  [2014-12-15 20:35:40] INFO  WEBrick::HTTPServer#start: pid=76385 port=9292\n\nThen, from another terminal\n\n  ~/code/ruby/ddex \u003ecurl -d @spec/fixtures/ern/36/instance1.xml http://localhost:9292\n  {\"message_header\":{\"message_thread_id\":\"Bu._UcZLsNbTVitjYnci\",\"message_id\":\"DbVn-iuUB-SiHl05B2IqW3_\",\"message_file_name\":\"wz9RHX_Eu1d\"\n  ...\n\n  ~/code/ruby/ddex \u003ecurl http://localhost:9292  # HTTP 400\n  {\"error\":\"XML parsing error: Start tag expected, '\u003c' not found\"}\n\n=== Contributing\n\nSee CONTRIBUTING.md\n\n=== More Info\n\n* {Source code}[https://github.com/sshaw/ddex]\n* {Bugs}[https://github.com/sshaw/ddex/issues]\n* {jaxb2ruby}[https://github.com/sshaw/jaxb2ruby] (Generate Ruby objects from an XML schema)\n* {DDEX Schemas}[http://ddex.net/xml]\n\n=== TODO/Known Problems\n\n* \u003ccode\u003eROXML.from_xml\u003c/code\u003e does not check the root element's name. Need to add something like:\n\n    raise \"unknown element #{xml.name}\" unless xml.name == tag_name\n\n* When an ROXML accessor expects an ROXML class, and one is not provided, \u003ccode\u003eto_xml\u003c/code\u003e will result in a \u003ccode\u003eNoMethodError\u003c/code\u003e:\n\n    # in SomeClass\n    xml_accessor :x, :as =\u003e AnotherClass\n\n    # Then\n    x = SomeClass.new(:x =\u003e \"123\")\n    x.to_xml  # undefined method `to_xml' for \"123\":String\n\n  Raised here: https://github.com/Empact/roxml/blob/v2.5.1/lib/roxml/xml/references.rb#L262\n\n=== See Also\n\n* {Metadata GUI}[http://metadatagui.com/] - Web-based GUI for managing DDEX metadata and exporting XML files\n* {grid-number}[https://github.com/ScreenStaring/grid-number] - Class for managing Global Release Identifiers\n* {iTunes Store Transporter: GUI}[http://transportergui.com] - GUI and workflow automation for the iTunes Store’s Transporter (+iTMSTransporter+)\n\n=== Author\n\nSkye Shaw  [skye.shaw {AT} gmail.com]\n\n=== License\n\nCopyright (c) 2013-2020 Skye Shaw. Released under the {MIT License}[www.opensource.org/licenses/MIT].\n\n---\n\nMade by {ScreenStaring}[http://screenstaring.com]\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsshaw%2Fddex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsshaw%2Fddex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsshaw%2Fddex/lists"}