0

I have imported a few classes in Adonis

const User = use('App/Models/User')
const Orders = use('App/Models/Orders')

I want to be able to access one of the above classes dynamically. By that I mean a variable will hold the class I want to access. The variable will be populated by via an API call from the user.

let className = 'Orders'

How to I use the className variable to access the Orders class.

I have tried

[className].query().where('orderNumber','123').fetch()

However that does not seem to work.

3 Answers 3

4

Create a name -> class map:

const classes = {
  __proto__: null, // to avoid people being able to pass something like `toString`
  Users,
  Orders,
};
// or if you don't want to use __proto__
const classes = Object.assign(
  Object.create(null),
  {Users, Orders}
);

and access the right class with classes[className]. Of course verify whether the class exists or not.


I have tried

[className].query().where('orderNumber','123').fetch()

However that does not seem to work.

In this context, [...] denotes an array literal, so [className] just creates an array containing className (which is a string in your example) as only element.

Sign up to request clarification or add additional context in comments.

7 Comments

Nice little workaround, and simple object to represent each possible class.
Yeah, concise properties (or whatever it's called) are really nice for that.
Very good thank you. I tried and it works. I will accept this answer.
@FelixKling This__proto__: null line was pure gold.
I'm a little worried though. Big huge red boxes for __proto__ at the top: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
|
0

Avoid converting the variable to a string at all. Just use:

let className = Orders;
className.query().where('orderNumber','123').fetch()

If the class is being instantiated by an API call, use a simple switch statement:

let class;
switch (apiCall.name) {
    case 'orders':
        class = Orders;
        break;
    case 'users':
        class = Users;
        break;
    default:
        throw 'Invalid API Call';
}

class.query().where('orderNumber','123').fetch()

3 Comments

I need to access the class dynamically. The name of the class will be passed in by the user via an API call.
You should have mentioned the API call in your original question.
I have updated the question to explain what I mean by dynamic.
0

Easiest would be to eval(className).query().where('orderNumber','123').fetch(), but if you want to check the values existence as an actual class, you probably should implement a switch or if-else-if to check and assign className and call only if it is actually present.

6 Comments

When mentioning eval(), you should also mention how evil it is. It creates many security holes, and usually does more harm than good. I cannot in good conscience recommend this solution.
Never eval user input.
@FrankerZ I wanted to add a disclaimer, but then I didn't. :D
How do you sanitize it? If you're not 100% sure you're sanitizing for anything the user could throw, than evaling input afterwards could be very dangerous. Avoiding eval all together eliminates many security issues.
Sure, but if you check whether className is an existing class name, you may as well load the actual class, just like FrankerZ did, and so there is no need for eval ¯\_(ツ)_/¯.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.