So we did refactor this code as I told you
but still, I also told you
that it would not work like that.
Why?
Because as I mentioned before,
just referring to functions like this
won't work if they do sit in another file.
That does actually work in the browser
but not with NodeJS.
There you have a strict separation between files.
Therefore, by the way, in restaurant-data.js,
the code would also not work
because I'm accessing the fs thing here,
which is coming from the built-in fs package,
which is part of NodeJS.
And whilst I am requiring this here in app.js,
I am not requiring it here in restaurant-data.js,
and here, the same thing applies.
Just because some function or some value
is available in file A
does not make it available in file B.
So if we wanna use the file system package here
in restaurant-data.js,
we again have to require it here like this
by calling require fs again.
And that is a super important rule.
If you wanna use a certain value,
or object or function in a file,
and it's not defined in that file,
then you have to require it.
Now, that will fix this error.
But it does not fix the issue
that these functions, which we wrote ourselves
in restaurant-data.js won't be available in app.js.
But we can fix them with the new knowledge we got.
All we have to do is require our own file.
And that is something we haven't done up to this point
but it is something which hopefully makes a lot of sense.
You can require built-in packages
and you can require third-party packages.
You can also require your own files,
which might contain extra functionality.
And that's what we'll do here.
I'll add it below the built-in packages
and below the third-party packages,
not because that's required
but because that's a common way of structuring
your different requirements so to say.
I'll add my own requirement
for my own file below these require statements.
And for that, I will add a constant,
which I name resData for restaurant data,
and I will require my own file here.
Now, how do you require your own file?
You don't just use the file name.
That would not work,
no matter if you add an extension or not.
Instead, you have to add a path to your own file.
You don't add a path for the built-in
and third-party packages.
There you just use the package name.
But for your own files, you add a full path.
So if you that restaurant-data.js file
would be in the same folder as app.js,
then you would add ./
which simply creates a relative path in NodeJS,
telling NodeJS that this file is a neighbor,
a sibling file of the file in which you have this code.
And you do omit the file extension.
You don't have to add .js here.
Here, however, restaurant-data is not in the same folder
as app.js, instead it is in a sub folder.
It's in the util folder.
And hence, the correct path would be ./util/restaurant-data.
That is how you express a path in NodeJS
in such a require statement.
Folders and files are separated with slashes
and you start with ./
to make it clear that this path is relative from app.js
in this case.
That's how you include this file.
However, there is an extra step,
which we also have to perform.
This is the correct way of requiring it
but by default, your files don't expose anything
to other files.
So just because we have these two functions
and this constant here in this restaurant-data.js file
does not mean that this is then automatically requireable
by other files.
It's not.
Instead, you have to explicitly mark which parts
of this file should be made available to other files
and you do that by adding an extra instruction at the bottom
of this file.
You write module.exports
and set this equal to a JavaScript object
in which you can now add the different things
which you wanna expose.
For example, if I wanna expose getStoredRestaurants,
I could add it like this.
Here I have the key name,
which I can use in other files to refer to this function,
and here I have a pointer to the thing
which I wanna expose.
And very often, you'll have the same names here
but you could choose different names.
So this name on the right side of the colon here
is the name of the thing which you wanna expose
to other files.
So this is not up to you.
If you do change it down here,
you also have to change it up here
in the function definition.
This name on the left side of the colon,
on the other hand, is up to you,
and is the name by which you are able
to then use this function in other files.
Here I'll stick to the same name
but I could choose a different name here on the left.
Very important, you don't add parentheses here,
you don't execute getStoredRestaurants.
Instead you just use the name of the function
because you don't wanna expose the result
of calling that function
but the function overall
so that it can be called in other files.
That's why you only use the name here.
And then I add a comma to also expose storeRestaurants,
and here I'll also point at storeRestaurants like this.
And now with that, I am exposing,
or exporting as it's called, these two functions.
Now, because of this extra addition in app.js,
requiring this file will actually work.
And there, we now have this resData object,
this name is up to you,
which is in the end just this object,
which you are exporting,
so it will be an object with two methods
because I am exposing two functions here
and functions in an object become a method
or we call them a method.
So now we can use the resData object here in app.js
to call these functions
and that's then the last step we've gotta do.
So if I wanna get my StoredRestaurants,
I don't call getStoredRestaurants like this,
but instead, I execute a resData.getStoredRestaurants.
So I refer to this exported object
and then there I call this specific method.
And I'll do the same for storing.
So for saving restaurants back into this JSON file.
And now we can do the same in all the other places
where we are getting our restaurants,
like here when we get the details
for a specific restaurant.
I can now replace this code here
with the resData.getstoredRestaurants,
and then I just have to store the result
of calling this function in a variable
or constant here,
and since I'm using storedRestaurants
as a name everywhere here,
I will just store it in a storedRestaurants constant.
And the same here where I get all the restaurants.
I replace this code here with this line
where I call getStoredRestaurants
and store that in a constant named storedRestaurants.
Now, with that, if I save everything,
this actually crashes and it crashes
because in restaurant-data.js,
I'm not just using the fs package
but I'm, of course, also using the built-in path package.
And I'm not requiring this here yet
but as I mentioned, we should require everything
that we rely on because just because it's required
in another file doesn't make it available here.
So to make this built-in path package available
here as well, we should add this path constant,
which we get by requiring path.
So this built-in package.
And that's another step which we need to take.
Now, with that, we're almost done
but now there is a subtle error,
which we also have to fix
to make sure that everything works.
And that error is related to this line
in restaurant-data.js.
In there, I am constructing a path
to this restaurants.json file
and I copied over the code from app.js.
This way of constructing a path was correct inside of app.js
but it's not correct in this restaurant-data.js file.
And it isn't correct here
because what I'm doing here
is I'm constructing a path
where I start in the directory
where this file is in, so in the util folder.
Then I dive into a data folder
and then there I look for restaurants.json.
Now, this is incorrect
because the data folder
is not inside of util,
it's instead on a higher level.
Hence, we need to fix this path.
I wanna start in my current directory util
but then I first of all wanna go up one level
to the project folder
and then go into data.
And we can easily do that
by adding an extra segment here in path.join
and that's the dot dot segment.
Now, this might look strange
but that's a standard way
in programming of expressing
that you wanna go to a higher level directory
so that you wanna go to the parent directory
of the directory you are currently in.
So if this points to util,
then this here, after going up one level,
will point at the project folder.
And then there we have a data folder
into which we can dive.
So that's a little adjustment,
which we have to make here
to navigate into the correct folder in our project
that contains this restaurants.json file.
And with that, if we save this,
if I reload here on restaurants,
I get my recommended restaurants.
We can view the details.
And we will also be able to share a restaurant.
But now we restructured our code
and our app.js file is a little bit leaner.
And whilst all of this was a lot of new knowledge,
which might not seem like it was worth the effort,
after all, we didn't move that much code,
it is crucial to be aware
of refactoring in general
and of how you can split your code
across multiple files in Express
because in any realistic website
that you are going to build with Node and Express,
code splitting like this will be common
and is something you have to understand.
And that's why we will actually not stop here
but take it even a step further in the next lecture.