Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support collections using custom classes #215

Open
HassanAkbar opened this issue Dec 19, 2024 · 6 comments
Open

Support collections using custom classes #215

HassanAkbar opened this issue Dec 19, 2024 · 6 comments
Assignees
Labels
enhancement New feature or request

Comments

@HassanAkbar
Copy link
Member

We should support "attribute collections" using custom "collection" Ruby class/types instead of just Ruby Arrays

as mentioned here by @ronaldtse -> glossarist/glossarist-ruby#118 (comment)

@ronaldtse
Copy link
Contributor

Another use case needed by @andrew2net at:

In some cases, Relaton uses collections with extra functionalities instead of Arrays. For example, TitleCollection and RelationCollection.

@ronaldtse
Copy link
Contributor

From the original issue, we should support:

we need to either provide a Lutaml::Model::Collection base class as an interface (e.g. support some methods from Ruby's Enum: insert, delete, iterate, etc.)

Or Lutaml::CollectionModel or Lutaml::Collection

@ronaldtse ronaldtse changed the title Handling collections using custom classes Support collections using custom classes Jan 27, 2025
@ronaldtse
Copy link
Contributor

e.g.

class Ceramic < Lutaml::Model::Serialization
  attribute :name, :string
  attribute :creation_date, :date_time

  xml do
    root "ceramic"
    map_element "name", to: :name
    map_attribute "creation-date", to: creation_date
  end
end

class CeramicCollection < Lutaml::Model::Collection
  attribute :identifier, :string
  values Ceramic

  xml do
    root "ceramic-collection"
    map_attribute "identifier", to: :identifier
    map_values
  end
end
<ceramic-collection identifier="my_id">
  <ceramic creation-date="2025-01-01">
    <name>Picasso collection #3213</name>
  </ceramic>
  <ceramic creation-date="2025-01-01">
    <name>Picasso collection #3223</name>
  </ceramic>
</ceramic-collection>

@ronaldtse
Copy link
Contributor

@andrew2net can you help provide some examples of how RelatonCollection differs from a normal Array? Then we can see how we can implement the functionality here. Thanks.

@andrew2net
Copy link

@ronaldtse sure. Let's say we have XML data

<bibitem>
  <title>Title 1</title>
  <title>Title 2</title>
</bibitem>

We can handle the XML using the classes

class Title < Lutaml::Model::Serializable
  attribute :content, :string

  xml do
    root "title"
    map_content to: :content
  end
end

class BibItem < Lutaml::Model::Serializable
  attribute :title, Title, collection: true

  xml do
    root "bibitem"
    map_element "title", to: :title
  end
end

> bibitem = Bibitem.from_xml xml
> bibitem.title.class # => Array

It's okay until we need a custom collection instead of an array with some extra methods. I think one of the ways is to use a custom collection class as collection value

class TitleCollection
  ...
end

class BibItem < Lutaml::Model::Serializable
  attribute :title, Title, collection: TitleCollection

  xml do
    root "bibitem"
    map_element "title", to: :title
  end
end

> bibitem = Bibitem.from_xml xml
> bibitem.title.class # => TitleCollection

@HassanAkbar Maybe we can use custom serialization methods, but in this case, we have to implement custom methods for each format.
BTW why can't lutaml-model have only one from or to custom method and handle another in its standard way? Implementing both methods is not always necessary.

class BibItem < Lutaml::Model::Serializable
  attribute :title, :string, collection: true

  xml do
    root "bibitem"
    map_element "title", to: :title, with: { from: :title_from_xml }
  end

  def title_from_xml(mode, value)
    model.title = TitleCollection.new value
  end
end

...with argument for mapping 'title' requires :to and :from keys (Lutaml::Model::IncorrectMappingArgumentsError)

@ronaldtse
Copy link
Contributor

BTW why can't lutaml-model have only one from or to custom method and handle another in its standard way? Implementing both methods is not always necessary.

Agree. We should be able to use one default method and use one custom method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants