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
inspect #2038
Comments
I'd love to see something more real-world that motivated a function like this. I don't think I've had any real call for it, but perhaps I'd recognize it with a more realistic scenario. |
Certainly! Please forgive the long backstory behind this function. :) I recently searched for a configuration wizard for ESLint. I've only found one that already exists but it's out-of-date, doesn't have the ability to set all the rule-specific configurations, and its UI leaves a lot to be desired. So, I took it upon myself to make a better one. Since there are well over 200 rules as of ESLint 3.12.2, it's desirable to automate the creation of a configuration wizard UI as much as possible. Fortunately, each of ESLint's rules has their schema consistently defined using JSON Schema. The basic idea is to of course leverage this metadata to drive the creation of form controls for the wizard interface. There are a couple issues with this:
The first issue will likely require manual effort to address but the second issue is where things get interesting. My goal for the second issue was to programmatically convert each rule's schema into an internal custom format that I believe will be easier to deal with for my purposes. My naive initial attempt at this was to do a rote translation of the rule settings into their comparable JavaScript forms. To illustrate with a basic example, let's look at the schema for the [
{ "enum": ["declaration", "expression"] },
{
"type": "object",
"properties": {
"allowArrowFunctions": {
"type": "boolean"
}
},
"additionalProperties": false
}
] My naive method simplified this to: [
["declaration", "expression"],
{
"props": {
"allowArrowFunctions": false
}
}
] So, my naive method worked pretty well for the majority of the rule schemas but there were some that required additional simplification steps. One such schema was for {
"anyOf": [
{
"type": "array",
"items": [
{ "enum": ["always"] },
{
"type": "object",
"properties": {
"null": { "enum": ["always", "never", "ignore"] }
},
"additionalProperties": false
}
],
"additionalItems": false
},
{
"type": "array",
"items": [{ "enum": ["smart", "allow-null"] }],
"additionalItems": false
}
]
} My naive method produced: [
{
"anyOf": [
{
"array": {
"choices": [
["always"],
{
"props": {
"null": ["always", "never", "ignore"]
}
}
],
"moreItemsNotAllowed": true
}
},
{
"array": {
"choices": [["smart", "allow-null"]],
"moreItemsNotAllowed": true
}
}
]
}
] But this wasn't sufficient. What I actually wanted, and what I eventually achieved using a second pass of simplification, was this: [
["always", "smart", "allow-null"],
{
"props": {
"null": ["always", "never", "ignore"]
},
"availableFor": ["always"]
}
] I'll spare you the details of how I did this and other similar conversions but suffice it to say I felt my code could be better. I then took a step back, thought about it for a while, and came up with the idea of generalizing the pattern matching aspects of what I was doing and placing that into a new helper function that can do this sort of declarative multi-selector type of thing. This is how Once I created this function I applied it to my project in a few key places. For instance, here's a code snippet partially showing how I solved the aforementioned const spec = {
anyOf: [
{
array: {
choices: ["primary1", { props: "secondary" }],
},
},
{
array: {
choices: ["primary2"],
},
},
],
}
const inspectee = inspect(spec, schema)
return [
uniq(concat(inspectee.primary1, inspectee.primary2)),
{
props: inspectee.secondary,
availableFor: inspectee.primary1,
},
] To me this was clearer than what I would have otherwise done. As an added bonus, I started seeing potential opportunities for refactoring that I had not noticed before using In other words, |
Thank you. This is a fascinating story, and a very interesting function. My take is that for the moment, the best place is the Cookbook. If we find ourselves recommending it more than every few months, then we could consider moving it into the main library. Does that sound reasonable? |
Sounds good ! Hopefully this function will save other developers' time. |
Great post @icylace , thank you and look forward to seeing this in the cookbook :) |
@CrossEye As you suggested, I added my |
Thank you very much. I can well imagine using this function. I'm glad to know it's handy if the time comes. |
I've created a function called
inspect
which will gather values from a data structure according to a given spec and will return those values as an object keyed according to strings in the spec.I'm not sure if it's more appropriate for this to be added to the Ramda cookbook or if it's useful enough to be considered for inclusion in Ramda itself. Let me know what you think !
Example Usage
See it in action here:
http://codepen.io/icylace/pen/jyOEEb?editors=1012
The text was updated successfully, but these errors were encountered: