Refactoring to List instead of Dictionary
Okay, time for Part 2 of fixing the “Add Line” feature. First, I needed to do the restructuring I mentioned in my last post, and alter the code so that lists, instead of dictionaries are sent through the ajax requests. I first did this by changing the color_entities_in_line()
function to return a json array:
Then I changed the JavaScript in the “Add Line” feature to iterate through the new nested array:
This meant that the line finally showed up again, and now had a guaranteed order.
Wonderful.
I also needed to alter the ajax on the client side, so that it submitted a list back instead of a dictionary. This was important because otherwise the lists that already existed would be replaced by dictionary objects as the function ran.
But not quite done. Now I needed to go back and fix the other place where this code runs: the “Clean List” page. This actually proved much easier than I thought, and was as simple as modifying the code to iterate through a list instead of a dictionary:
Gotta love Python.
This made the code that I’d already written work properly again. Now, it’s time to fix the “Add Line” feature, for real this time.
The New Add Line Function
First, I added a few extra lines of code to the “parse_line” route in my main.routes
file:
This creates a new CleanedLine
object and assigns the RawLine
object to it. I decided to do it here in order to make the ajax work easier on the client side for the next step. Also note that I added the hex_name
of the current list I was on to the ajax request, which enabled me to access the right list on the server side.
It was here that I ran into a sort of conundrum: how to request the individual ingredient lines without them having a recipe to help with the lookup process? Here, I admit, I kind of went in circles for a bit. First, I modified the “/clean/set_color” route, as it is currently set to need the hex_name
of the recipe in order to find the right line. I changed it so that it instead uses the unique id
of the RawLine
, which is passed through the ajax request. I then use the RawLine
to call the CleanedLine
associated with it (which I’d already created in the “parse_line” route):
This works, and in general it seems to me to be a better way to look up the RawLines
; there’s less database querying and it’s guaranteed to find the right match. There’s just one problem: changing the code like this breaks (once again) the code for the “clean line” page. I knew this going in, but had decided that it would be better to rewrite the “clean recipe” page so that it ran off of the individual id
s as well.
I also did it because I wanted to implement a version of my in-line recipe cleaning for the main recipe page. Instead of the “Edit” button redirecting to the whole recipe page, it seems easier and more intuitive for it to show the buttons in the line, so that they can be adjusted as necessary. Clicking “commit” would then refresh the page, with the necessary changes made.
But first, I had to come up with a better, more generalized solution to the ajax requests for the line colors. The simplest thing to do seemed to just create an id
attribute that matched the id
of the RawLine
in the database. Then a simply jQuery command would be able to fetch it and send it as part of the ajax call. But… I don’t know, I felt uncomfortable including the actual raw id
like that, it seemed… unsafe? Admittedly, I don’t have any information for that besides a vague hunch, but I still didn’t want to do it. Besides, using a number as an HTML id
attribute doesn’t feel like best practices.
What I ended up doing was creating a custom id
attribute for each RawLine
. This id
was created by combining the hex_name
of the RecipeList
and the id_in_list
of the RawLine
. Sounds like a bit of a tongue twister, but here’s what it looks like in code:
Then, I rewrote the code in the get_colors()
and set_colors()
routes to take either the id
of the RawLine
OR the hex_name
and id_in_list
attributes. This ensured the maximum flexibility of my code, and I’m hoping that having more ways to get the information I need will make it easier down the line if I need to change anything.
As you can see, there are still some TODO
s that I’ve left in place here, mainly for refactoring code to improve readability. One thing that I do need to do, however, is modify the set_color()
route in particular to split a CleanedLine
if a change in the ingredients requires it. This is generally an isolated case, but it’s still something that is going to need to be worked on.
Then, I rewrote a few lines of my jQuery code so that the function that enables the editable buttons in the main list works both for the “Add List” button and the “Edit” buttons on each line:
There’s obviously a lot more to this function, but the important things to note are that I added a place_to_append
variable here that tells the function where to insert the buttons, and I search and only hide the information that appears on the RawLine
objects underneath the CleanedLine
s. Otherwise, if I was using the code for the “Add Line” button, the entire recipe list would disappear.
Then (yeah, we’re still going), I changed the “Commit” button to a simple redirect to the same page, which allows the changes to be added to the page:
Unfortunately, the edit command didn’t work with the new lines, because they didn’t have a recipe to create the id with. So I decided to do something that I probably should have done a long time ago: create a RecipeList
for additional ingredients, and add all user-created lines to that list. In the code for the home page that creates a new CompiledList
:
Note that I picked my own hex_color
for this, as I wanted it to be grey every time, to support a sense that this list was different.
The code successfully created the new list:
Now to add the code that actually adds the new lines to this recipe.
And all the pieces are in. Whew, that took a while. As I let my smoldering fingers gently fall from the keyboard, I closed my eyes and whispered to whatever gods of coding exist, “it is finished.”
Though, of course, it’s not finished, at all. But this has been something that has stymied me for the better part of two weeks, and I’m very proud to have this functionality working.
What’s next? Well, the first thing going to do next is some serious refactoring. My main
blueprint is getting pretty large and unwieldy, and a large part of why I decided to use blueprints from the beginning was so that I could more easily refactor later. So I’m going to split up into several blueprints.
Then, I’m going to focus on a few small quality-of-life improvements. The CSS isn’t quite right for some of the pages, and I’d like the barebones functionality to be a little prettier before I tackle the next big part of this project.
But these are mostly small things to give myself a breather before I move onto the next, very important steps:
- A more fully integrated ability to get recipes from the web/add them yourself
- Accounts, users, and some level of social functionality.
These are the last big things that I need to do on this project. Stay tuned to watch me tear my hair out as they prove much more difficult that I think they’ll be (and I certainly don’t think they’ll be easy).
Until next time!