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

Can't find easy way to "denormalize"? #180

Closed
Antman261 opened this issue Dec 31, 2017 · 6 comments
Closed

Can't find easy way to "denormalize"? #180

Antman261 opened this issue Dec 31, 2017 · 6 comments
Labels
layer: Selectors type: Enhancement This intends to enhance the project.

Comments

@Antman261
Copy link

Maybe I'm missing something in the docs here, but if I call SomeModel.withId(123) I get back a model instance and can access that model's own fields with .ref. Cool, but how do I also get SomeModel's related fields in a plain javascript object? i.e. one to ones as a simple key->Object, while one to many and many to many as an array of objects.

Instead I have to write a selector and use map. Since I've already defined these relationships it seems redundant to have to effectively write my own serializers both in and out.

Redux-orm could potentially borrow yet another feature from django and use extendable serializers. This way most use cases are covered by standard serializer classes which we can override to provide custom serialization/denormalization on a per-field as-needed basis.

Here's a very basic example:

function getActiveShop(db, id) {
  const {Shop} = orm.session(db);
  if (Shop.hasId(id)) {
    const shop = Shop.withId(id);
    let shopJs = shop.ref;
    shopJs.addresses = shop.addresses.toRefArray(); // I feel I shouldn't need to do this
    return shopJs;
  } else {
    return null
  }
}

Instead could be

function getActiveShop(db, id) {
  const {Shop} = orm.session(db);
  if (Shop.hasId(id)) {
    return Shop.withId(id).denormalize();
  } else {
    return null
  }
}

This means Shop would need a serializerClass field that defaults to some StandardSerializer which makes some helpful assumptions i.e. objects are related via an attribute called id, fk's model name is the title-cased version of the field name, etc.

¯_(ツ)_/¯

@Antman261 Antman261 changed the title Can't find easy way to "denormalize" without boilerplate? Can't find easy way to "denormalize"? Dec 31, 2017
@markerikson
Copy link
Collaborator

Yeah, I've generally written my own .toJSON() functions by hand on my classes, like this:

class Lance extends Model {
    toJSON() {
        const data = {
            // Include all fields from the plain data object
            ...this.ref,
            // As well as serialized versions of all the relations we know about
            commander : this.commander.toJSON(),
            pilots : this.pilots.withModels.map(pilot => pilot.toJSON()),
            mechs : this.mechs.withModels.map(mech => mech.toJSON())
        };
        
        return data;
    }
}

Also, quick FYI, in your example shopJs.addresses = shop.addresses.toRefArray(); is going to mutate the existing plain JS object that's living in the Redux store.

That said, this does seem like a potentially useful feature, and if you can put together a PR we could work to get that in.

@plandem
Copy link
Collaborator

plandem commented Dec 31, 2017

I'm still sure that it's related to selectors: #140 (comment)

Getting whole related models reference is just a specific/your case, but we need a more general solution. E.g., in our application for one case we return only subset of properties and never full reference. For other case we return normalized/formatted object for specific component. I would move it to 'selectors' with additional settings. Not sure that I will have enough time in the near future to make a helper-library for this, but at least I will publish online my current set of selectors.

@haveyaseen
Copy link
Member

This use-case is handled by the new selector API. Database sessions and model instances should typically not be used outside of reducers. Selectors should only need them when combining data from different models in some atypical way (which is also supported).

@markerikson
Copy link
Collaborator

@haveyaseen : per your last comment, a lot of my logic involved setting up sessions in a thunk to do some generation of an item, before JSON-ifying it and dispatching it in an action.

@samuelcolburn
Copy link

@markerikson are you referring to your logic before or after the selectors update? Your "Practical Redux" blog with redux-orm is really amazing, I would be very interested in seeing how you would/have refactored things like this in light of the new updates.

@markerikson
Copy link
Collaborator

@samuelcolburn : before. I haven't actively used Redux-ORM in a couple years, since around v0.9.

There's a bunch of other stuff I wish I'd had time to cover in "Practical Redux" posts, but maintainer-y stuff is my primary focus these days (like our upcoming Redux core docs revamp - see reduxjs/redux#3313 (comment) ).

We've got a couple new apps in dev right now, and I opted not to bring in Redux-ORM for now. I still think it's useful, and it totally makes sense for the original app I built using it, but these apps don't really deal with relations between any of the fetched data, so I didn't feel it was worth adding another dependency to manage them.

Because of all that, I'm actually not particularly clear on what all has changed lately. I do follow this repo, so I know there's been a bunch of additional work and releases, I just haven't dug into any of them specifically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
layer: Selectors type: Enhancement This intends to enhance the project.
Projects
None yet
Development

No branches or pull requests

5 participants