Start of Pantry Application (db design with MySQL Workbench)

Posted on January 1st, 2011

One common problem I have is determining what I have in my pantry. For example, I’ll go grocery shopping after work and not remember whether I have any apple cider vinegar and if so, if I have enough for the recipe I want to make. Often I’ll buy a bottle and then get home to discover that I already have plenty. Or, I’ll assume I have something I don’t and get home to find out that I am now missing a key ingredient. Clearly, I need a software solution to my problem and just as clearly, I want to create it myself regardless of it already existing.

There are several decisions I need to make, platform being probably the hardest. For now, I decided to start out by designing the data model so I don’t have to worry about the hard stuff. Obviously, I need to keep track of the food items, categorize them in some way and track the amount on hand.

Then I decided that I wanted my ERD to be pretty for this blog post, and I decided to try doing this with MySQL Workbench (http://www.mysql.com/products/workbench/). Good news is it comes for linux! Bad news is that I was kind of a flake and tried installing the wrong version the first time, but 10 minutes later when I figured that out, installation was very easy (Windows easy, even!).

To test how easy the software is to use, I decided not to read the manual before starting. I opened it up, clicked on File -> New Model. From there I built some tables. One thing I realized right away was that my computer is not strong enough at all to make this a pleasure to do. Also, for some reason it goes way off my screen (and doesn’t maximize correctly).

A few hours later (hours because my computer does not handle this software very well *) I broke down and had to read the manual. Starting my diagram using the tool was pretty easy, you drag and drop the tables. However, the EED tool didn’t work the way I thought it would :) Oh well! Had the tool that I needed in order to create fk relationships using existing columns not been off the screen then I might not have had to resort to checking out the manual. Also, it shows the table relationships, but the lines don’t match up with the actual columns which can be confusing if you are just looking at it. Within the tool, you can hover over the relationship and it will show what fields are being used. Another thing to note is that since it’s not easy to alter the look of the relationships (and define them further), I couldn’t define the cardinality/modality in the manner that I am used to with crow’s foot notation (http://www2.cs.uregina.ca/~bernatja/crowsfoot.html). Of course, maybe it is possible and my lack of excitement about spending any more time on this just got in the way :) Anyone who knows more and would like to share their expertise in my comments, please feel welcome.

So, my first go at using the tool to define my data structure and making it a picture is here:

I think it’s all pretty self-explanatory. When food is purchased, the purchase is put into the purchases table and the amount in the food table increases. I’m not keeping track of each use, that’ll just be taken care of programmatically.

My next step is to determine the technology that I’ll use. I’m leaning towards django but am open to suggestions. At some point I’ll want to make a phone application (android) for it as well, since that’s where its best use will be.

That’s it for now!
Jen

* I’m sure that the software would be wonderful and fast to use on anything besides my netbook.

Click here to view and leave comments!

iheartjesselondon – Walking through a very basic Google Chrome extension (Part 1 of ? (at least 2))

Posted on December 19th, 2010

Quick background – this guy Jesse and I send each other Web links 5-20 times a day. I decided I wanted to streamline this process as much as possible (one click, no typing). Since we both use Chrome the majority of the time, writing an extension was a no-brainer. Much more importantly, it gave me an excuse to work on a short project in a language I am familiar with, but on a platform new to me. The best thing about all of this, it’s very easy*! Part one of this post is a walk-through of code basics.

BASIC FILES THAT MAKE IT WORK:

Below are the files that are included in my extension directory, along with my icon, which I define in manifest.json (icon.png).

manifest.json: This file uses json to define files used, permissions, title, and more (detailed list of what can be included found here). Here is my manifest.json:

code:
{
  "name": "I Heart Jesse London",
  "version": "1.0",
  "options_page": "options.html",
  "description": "This extension emails jesse london, or whoever, a link to the current website",
   "browser_action": {
     "default_icon": "icon.png",
     "default_title": "send some internet lovin",
     "default_popup": "popup.html"
  },
  "permissions": [
    "http://domainnameforemailwebservice.com/",
    "tabs"
  ]
}

As you can see, it’s very self-explanatory. I give it a name, version, define my icon, popup and options files and set some permissions that allow me to access information about tabs and also to use the web service, hosted elsewhere, for sending my email**.

options.html: It’s easy to collect and store information in the Chrome extension. In my manifest.json file, you can see that I named options.html as my options_page. The options page is what it sounds like, it’s the page that opens up in a new tab when the user goes to set extension options. My file is just a very basic html form with some javascript to check and set some local variables. This is the lovely thing about Chrome extensions; they are basically web pages so you really just need to know html and javascript.

Here’s the html used:

<body>

Enter in your favorite persons email address, your own, and the magic key ;)
TO: <input id="email_address" value="jesselondon@gmail.com" name="email_address" /><br />
From: <input id="from_address" value="jennifer.stander@gmail.com" name="from_address" /><br />
Key: <input id="key_string" value="input key here" name="key_string" />

<br>
<button onclick="save_options()">Save</button>
<br>
<div id="status"></div>
</body>

Easy cheesy, right? On page load it runs a function to restore the options with values previously stored, there’s a form with 3 fields and some defaults, a <div> that displays confirmation on save, and on form submit the function save_options() is called.

Here’s are the two functions, with comments!:

<script type="text/javascript">

// Saves options to localStorage.
function save_options() {
  var email_address = document.getElementById("email_address").value;
  localStorage["email_address"] = document.getElementById("email_address").value;

  var from_address = document.getElementById("from_address").value;
  localStorage["from_address"] = from_address;

  var key_string = document.getElementById("key_string").value;
  localStorage["key_string"] = key_string;

  // Update status to let user know options were saved - briefly :)

  var status = document.getElementById("status");
  status.innerHTML = "Options Saved: <br>To Email: " + email_address + "<br>From Email: " + from_address;
  setTimeout(function() {
    status.innerHTML = "";
  }, 750);
}

// autofills form fields with previous entered information if it exists
window.onload = function() {
    //first check to see if there are already email addresses stored, exit if not (will display defaults then)
  if(!localStorage["email_address"] && !localStorage["from_address"]){
    return;
  }
  document.getElementById("email_address").value = localStorage["email_address"];
  document.getElementById("from_address").value = localStorage["from_address"];
  document.getElementById("key_string").value = localStorage["key_string"];
}

</script>

popup.html: the default_popup in manifest.js is exactly that, a popup window that appears when the icon is clicked. I had added the popup at Jesse’s suggestion so that he knows that he for sure clicked the icon and will be adding the service response in the future to verify that it indeed went through. I originally had all of my functionality in a background page, but for some reason I couldn’t get it to work with my popup*, so I just threw all of the code in popup.html. I’ll revisit this when I’m ready for some frustration.

On the popup page load I call the function that does all of the work and pass it information from the selected tab:

window.onload = function()
{
	// grab the selected tab title and url and send to my email function
	chrome.tabs.getSelected(null, function(tab){
		send_email(tab.title, tab.url);
	});
}

The main functionality of my little extension is all in send_email. Here is all the information that you need for using cross-origin xmlhttprequest within a chrome extension. I pretty much copied and pasted from it, even included the malicious script warning in the comments :) My function takes the title and url and sends it to a webservice – the main thing to note here is that you will need to include the domain in your permissions in manifest.json. Here it is:

// uses my own dumb webservice, returns true or false
 function send_email(title, url){
    var jens_url = "http://domainnameforemailwebservice.com";
    var xhr = new XMLHttpRequest();
    var fullstring = "";

    // need to encode the following still on this end
    // would like to alter this to use gmail if it's open
    // until then it's just for jesse and I, I guess

    var emailaddress = localStorage["email_address"];
    var fromaddress = localStorage["from_address"];
    var key_string = localStorage["key_string"];

    var fullstring= jens_url + "?id=" + key_string + "&email_address=" + mailaddress + "&page_title=" + title + "&page_link=" + url + "&from_address=" + fromaddress;
    console.log(fullstring);

    //send and receive
    xhr.open("GET", fullstring, true);
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
        // WARNING! Might be injecting a malicious script! This should not be complete yet
        console.log(xhr.responseText);
      }
    }
    xhr.send();
    return xhr.responseText;
  }

And there you go, that’s what I have so far, and it’s working! All code that I’ve discussed is available publicly on github. Next up in Part 2 I’ll cover installation, testing and distribution.

That’s it for now!
Jen

* The one thing that wasn’t easy and I haven’t really figured out is how to use a background.js file and popup together. Originally, I wasn’t using a popup so had a listener programmed into a background script, along with all of my other functions. I preferred this separation of logic and display, but once I added a popup into manifest.json, the listener no longer worked. I hope to revisit this in the future. If anyone has suggestions, please let me know! (I will admit that not a lot of time was spent trying to resolve this though.)

** It would be nice to use the user’s gmail account instead of a hosted web service. I need to do more research to see how easy and safe this is though. Any discussion on integrating gmail functionality into a custom extension is welcome – please comment. I’ve seen examples that open up the gmail tab, but I really want everything to happen in the background.

*** I am aware of a few bugs and will fix them before Part 2.

**** At some point I should really have this usable for someone besides myself and jesse

Click here to view and leave comments!

« Previous PageNext Page »