chazwatkins

chazwatkins

I’m considering writing an integration with Salesforce. Salesforce has SObjects of various types like Case, Quote, Lead, CustomObject__c, etc. These SObjects are like database tables with their own schemas. I’d like to convert the JSON responses I get back from Salesforce into structs that represent the SObject type. For example, %Case{}, %Quote{} instead of something more generic and known at compile time like %SObject{type: "Case"}. There are hundreds of SObject types, so defining them all isn’t reasonable and wouldn’t cover custom SObjects or custom SObject fields not provided by Salesforce itself.

Is there any way to define structs at runtime to achieve something like %{SObjectName}{}?

Showing Posts 1 to 10

D4no0

D4no0

What is the value of having those schemas if you are defining them at runtime?

The whole reason behind schemas is to have more compile-time guarantees, if you generate them at runtime there is no way your codebase will have any idea of those schemas.

Maybe the question was not addressed correctly and you are looking for one of the following things:

  • validation - validate the incoming data based on some runtime rules. This can be done with schemaless changesets from ecto;
  • code-generation - generate those schemas in your codebase based on a spec given by Salesforce. This case is possible however you will have to venture into metaprogramming and that is not the most welcome field for beginners.
sodapopcan

sodapopcan

Hello and welcome!

There is not, one of the whole points of structs is to provide compile time checks, including against keys.

If you are going for dynamic runtime, maps should be largely fine. You can still pattern match. I guess the only problem you might face is accidentally adding a wrong key after initialization but you could guard against that with custom functions, I suppose (though probably not worth it).

chazwatkins

chazwatkins OP

There’s no database involved, so schemas are necessary. This is just an integration wrapper for Salesforce APIs. The value is pattern matching on the struct itself and knowing its SObjectType without looking at a field value. I can make a generic SObject struct and have a type field if that is impossible.

chazwatkins

chazwatkins OP

Thanks for the feedback. I suspected such, but I wanted to check.

D4no0

D4no0

It highly depends on what you are looking for, first of all ecto can be used without a database, and it is widely used for data validation. In your case, from what I understand the protocol defines the type of the structure in one of its fields.

As long as you can define those types in your codebase, you can always use ecto + polymorphic embed.

chazwatkins

chazwatkins OP

Thanks for the information. I consider this one. I hadn’t heard about polymorphic embeds before.

VOUwCNOD

VOUwCNOD

Yes, you can create structs in runtime. Consider this code

def create_struct(name, fields) do
  defmodule name do
    defstrcut fields
  end
end

This is a dark magic, but there is no need to limit yourself, be expressive, break laws, make people be afraid of yourself and make them treat your code with fear and respect.

To match on such structs in runtime, consider something like

name = Case
create_struct(name, [x: 1, y: 2])
...
case something do
  %^name{} ->
    ...
end
sodapopcan

sodapopcan

@chazwatkins Oh boy, do not follow the advice above. You’re opening yourself up to atom overflow issues and as well as a host of warnings about module redefinitions you’ll have to code around.

chazwatkins

chazwatkins OP

The use case I’m looking at wouldn’t go anywhere near the atom limit as there are only, at most, one to two thousand SObject types in complex Salesforce orgs. You’re likely only using a subset of them, a few hundred at most for large organizations.

It doesn’t look like there is a solid way to convert a string to a module name without a prefix of : like %:Case{}. It’d be great for using them with Protocols, but it’s just as easy to pattern match on something like %SObject{type: "Case", fields: ...} and dispatch to the corresponding Case business logic.

It’s good to know that this is possible, though. I completely understand the point of not using it if the input is unbound, where it could overflow the atom table.

sodapopcan

sodapopcan

The problem lies more in that you are dynamically creating modules at run time. Once those are created, they’re there. If you need to change them and your users are, for instance, using hot code reloading, they won’t get your changes. As far as atom overflow goes, sure, there may be a finite number of entities you are dealing with, but it’s now something you have to think about and secure against. In short, this is not well documented for a reason and why I didn’t mention it in the first place. If you’re ok mixing artsy code into your business logic, that’s on you. It’s not something I would deem responsible in a library you are wanting people to use, though. I personally would never use something if I knew it was doing this.

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews