Ilyes512
Can't use (Erlang) Records that start with an uppercased letter
So I am using Erlsom to parse a XML file that also has a matching XSD file. Erlsome includes an option to generate records (.erl file) based on the model of the XSD (erlsom:write_xsd_hrl_file).
This auto-generated .erl file includes records that start with an uppercased letter. For example:
-record('Pip3A4PurchaseOrderRequestType', {anyAttribs :: anyAttribs(),
fromRole :: roleType(),
'Authentication' :: 'AuthenticationType'(),
'GlobalDocumentFunctionCode' :: string(),
'PurchaseOrder' :: 'PurchaseOrderType'(),
thisDocumentGenerationDateTime :: 'DateTimeType'(),
thisDocumentIdentifier :: 'ProprietaryDocumentIdentifierType'(),
toRole :: roleType()}).
So when I use a record in my elixir module (like the one below) I can’t use it.
Record.defrecord :Pip3A4PurchaseOrderRequestType, Record.extract(:Pip3A4PurchaseOrderRequestType, from: @hrl)
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> require Ot.Poc
Ot.Poc
iex(2)> record = Ot.Poc.Pip3A4PurchaseOrderRequestType()
** (SyntaxError) iex:2: syntax error before: '('
iex(2)> record = Ot.Poc.pip3A4PurchaseOrderRequestType()
** (UndefinedFunctionError) function Ot.Poc.pip3A4PurchaseOrderRequestType/0 is undefined or private. Did you mean one of:
* Pip3A4PurchaseOrderRequestType/0
* Pip3A4PurchaseOrderRequestType/1
* Pip3A4PurchaseOrderRequestType/2
(ot) Ot.Poc.pip3A4PurchaseOrderRequestType()
I thought I could fix this by defining the record as fallowed:
# v--- lower cased p v--- Upper cased p
Record.defrecord :pip3A4PurchaseOrderRequestType, Record.extract(:Pip3A4PurchaseOrderRequestType, from: @hrl)
Now I can call Ot.Poc.pip3A4PurchaseOrderRequestType(), but when I try to pass the record data it fails because the record links to other records that are starting with upper cased names, but first it fails because it can’t match it self with the data:
** (ArgumentError) expected argument to be a literal atom, literal keyword or a :pip3A4PurchaseOrderRequestType record, got runtime: {:Pip3A4PurchaseOrderRequestType, [], {:roleType, [],
So at this point I tried everything I could think off without success. What can I do without having to adjust the .erl file manually (392 LoC)?
Marked As Solved
Ilyes512
I got it working by doing the following:
defmodule Ot.Poc do
for name <- Record.extract_all(from: @hrl) |> Keyword.keys do
Record.defrecord :"#{name |> to_string }", Record.extract(name, from: @hrl)
end
# ...
end
edit:
BTW thanks @peerreynders! And the rest to of course! (quite surprised how fast I had my first reaction here
)
Also Liked
peerreynders
What about this approach:
require Record
defmodule Person do
Record.defrecord :"Person", [:name, age: 25]
end
.
iex> require Person
iex> default = Person."Person"
{:Person, nil, 25}
iex> name_and_age = Person."Person"(name: "Bob Jones", age: 55)
{:Person, "Bob Jones", 55}
iex>
Example from Working with Erlang Records in Elixir
michalmuskala
Record.defrecord can accept an additional argument to differentiate the macro name from the record tag. And that’s probably what you want - lowercase macro with an uppercase tag.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









