-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
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
Abstract findPage & add pagination Bookshelf plugin #5444
Conversation
|
Changing to use a
Yes, but they'd stay inside the model/base folder for now. I am just imagining a file called, e.g. pagination.js which contains defaults & knows how to do paginated fetches. Bookshelf has |
c9cd258
to
cf5899c
Compare
This PR has had a bit of an update - I've now split the pagination functionality out into a fully unit-tested plugin. I think this is making sense. My plan is to add a bit more documentation into the plugin & to key bits of the model layer and call this PR 'done' as it closes #2896. Next step is probably a new PR to do the work to move the filter logic & option handling for the API described in #2758. Alternatively I can keep pushing commits here until the utils file is gone. |
b214ee4
to
361a61e
Compare
I've updated this PR again 😄 The new
I also started adding a bit more documentation to the base model file, as a little bit of an indicator of how I imagine clarifying the code in there and which parts are bookshelf settings, which parts override bookshelf functions, and which parts are Ghost-specific. #2896 is now closable, I'm in two minds as to whether these 2 commits should be squashed or not. Feedback would be very much appreciated. |
😍
+1 for squashing |
closes TryGhost#2896 - move default options / custom code into model functions - move most of the filtering logic into base/utils.filtering (to be relocated) - move the remainder of findPage back into base/index.js and remove from posts/users&tags - move pagination-specific logic to a separate 'plugin' file - pagination provides new fetchPage function, similar to fetchAll but handling pagination - findPage model method uses fetchPage - plugin is fully unit-tested and documented
Updated to move module.exports to the bottom & squashed the commits together |
Abstract findPage & add pagination Bookshelf plugin
This PR is intended as a discussion starter on where we should be going next with the API vs model layer.
In this PR, I've finished the work of generalising the code in
findPage
. This included moving repeated pagination-specific code intobase/utils.js#pagination
and filter-specific code intobase/utils.js#filtering
. I also moved the parts that were model-specific options or custom code into model functions with horrific names likefindPageDefaultOptions()
, and then moved the remainder offindPage
intobase/index.js
, calling out to the utils & model specific functions where needs be.It's now reasonably clean, but there are a lot of steps (especially around option handling), 4 new model-specific functions (which are kinda awkward) and 2 utils that don't really make sense. There's clearly a lot more to do to get this to be sane - and then I'll add some more tests as well of course 😉
Suggested changes
There are a few changes that I wanted to get a bit of feedback on before I forge ahead:
1) API-level option handling
More of the option handling should be done at the API level as described in #2758. At the API level, we need to add validation that the options provided are allowed and valid. Currently there is some option validation inside the model level but this is quite a weird mix between API-logic and model-logic. E.g. the model layer permits
include
(and uses it heavily), but it should be receivingwithRelated
- this is subsequently converted in multiple places. Instead, the API should be checking that the includes are correct and converting them to awithRelated
call. Conversion from filters to joins & wheres should probably also happen in the API. That way the options passed to the model are the ones that bookshelf will understand.Fundamentally, I think the API layer should speak
api-ish
and be able to translate it intobookshelfish
. The model layer should only speakbookshelfish
.2) Remove weird filtering behaviour from models
Our findPage functionality does a slightly odd thing where it will fetch a related model (tag, author, role), use it to perform a filter, and then return that model in
data.meta.filters
. This has an additional annoyance in that it is inconsistent - if you request tag=thing, you gettags: [{thing}]
and the same for roles. I could write an essay just on this bit, but the short version is that this behaviour is a bit of a hack so that themes get the data they need. Therefore it can be moved into the channel layer when we get there. Filtering is a whole other ball game and needs to be consistent and extensible - issue coming soon.3) Split base/index.js up into feature-based 'plugins' or 'mixins'.
Bookshelf supports plugins but we don't necessarily need to go quite that far. However, it would make sense to have a set of mixins covering things like BREAD, pagination, filtering, validation etc. These would provide a place for the pagination & filtering code currently sat in a weird util. This is one of those things where it's hard to know what it looks like til you try it - but does it sound sane? I think care should be taken to not over-do it, but to split out logical groups of stuff.
4) Consider treating BR and EAD differently?
This is just something that's irking me - we treat all of our BREAD methods very similarly (both in the API and Model layer), but they are quite different. B&R need to fetch data with lots of options for determining what sort of data to get. The EAD parts have a lot less options but they change things. I don't even know how this would look - I was just throwing it out there to see if anyone else had any thoughts on refactoring this stuff?
Opinions, thoughts and ideas pretty please!!!
refs #2896