Commit cfb3a9d1 authored by Shane A. Stillwell's avatar Shane A. Stillwell 🎯
Browse files

fix spelling mistakes identified by Triplecheck

parent 981251e7
......@@ -28,7 +28,7 @@ For the technical needs I have a small [Granite Gear Ripstop Stuffsack](http://w
* [Etymotic HF5 Earphones](http://www.etymotic.com/consumer/earphones/hf5.html) (great for noise free listening)
* Simple lens cleaner (I wear glasses)
* MacBook Power cord in a bag (having cords in their own containers/bags really helps reduce tangle)
* MacBook Power Extension rolled up with velcro ties
* MacBook Power Extension rolled up with Velcro ties
* iPhone wall charger
* iPhone Earphones in an old makeup remover case
* Granite Gear Stuff Sack
......@@ -50,13 +50,13 @@ The **Girl Scout** cup is sort of a running joke. My wife picked it up at a gara
## Survival & Emergency
While out of doors in this wonderful world, you will run into situations. It may be as simple as a bandaid, or more life threatening involving emergency medical care and survial. In such cases there are a few items that can make all the difference.
While out of doors in this wonderful world, you will run into situations. It may be as simple as a bandaid, or more life threatening involving emergency medical care and survival. In such cases there are a few items that can make all the difference.
![Survival Items](images/IMG_0913.JPG)
* Paracord rope
* Para cord rope
* Batteries
* Altoid Mini Container
* Altoids Mini Container
* Super glue
* Cotton ball
* Dental floss
......@@ -64,7 +64,7 @@ While out of doors in this wonderful world, you will run into situations. It may
* Sewing needles
* Mini compass (I was lost in the woods once, no fun)
* Safety pin
* Bandaids & Alligator clips
* Banda ids & Alligator clips
* [Petzl eLite headlamp](http://amzn.com/B008AUBOTS)
* Real compass (yeah, being lost is no fun)
* Lighters (forget the matches)
......
......@@ -44,7 +44,7 @@ aws cloudfront create-invalidation \
```
## What Does It Do?
In a nutshell. This script will bump the current version of the project, build your static site, upload to AWS S3 bucket, then tell Cloudfront to invalidate all the files in the specific Cloudfront distribution.
This script will bump the current version of the project, build your static site, upload to AWS S3 bucket, then tell Cloudfront to invalidate all the files in the specific Cloudfront distribution.
## What You'll Need
To run this you'll need a few things in place
......@@ -71,7 +71,7 @@ then
exit
fi
```
Here we check if the tag hash is different than the current HEAD hash. Basically we don't want to create another commit if nothing new has been commited. You need to actually change code and make a new commit before this script will continue past this part.
Here we check if the tag hash is different than the current HEAD hash. Basically we don't want to create another commit if nothing new has been committed. You need to actually change code and make a new commit before this script will continue past this part.
```
npm version patch;
......@@ -98,8 +98,8 @@ aws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/*";
```
After we've done uploading our files to S3, we tell Cloudfront to invalidate all our files. Since this is a wildcard, we only get dinged for one cache invalidation from Cloudfront rather than the hundreds or thousands of files that are on our site (that could get expensive, since Cloudfront starts charging for [invalidations past 1000/month](https://aws.amazon.com/cloudfront/pricing/))
After we've done uploading our files to S3, we tell Cloudfront to invalidate all our files. Since this is a wild card, we only get dinged for one cache invalidation from Cloudfront rather than the hundreds or thousands of files that are on our site (that could get expensive, since Cloudfront starts charging for [invalidations past 1000/month](https://aws.amazon.com/cloudfront/pricing/))
## Summary
This script makes it really easy for me to just fire and forget and it has a little built in safecheck so I'm not just bumping up the version with no new code to show for it. I've gotten in the habit to create a `publish.sh` for many of my projects since I'm not always sure how each are deployed if I only deploy on occasion. Happy Shipping.
This script makes it really easy for me to just fire and forget and it has a little built in safe check so I'm not just bumping up the version with no new code to show for it. I've gotten in the habit to create a `publish.sh` for many of my projects since I'm not always sure how each are deployed if I only deploy on occasion. Happy Shipping.
......@@ -25,7 +25,7 @@ function in Mysql.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
So my query looks like this
/* Show Gift Cert nubmers */
/* Show Gift Cert numbers */
(
SELECT GROUP_CONCAT(cert_id) FROM ugiftcert_history uh
WHERE so.entity_id = uh.order_id
......
......@@ -14,7 +14,7 @@ As a hip, cutting edge developer, you're using [Hugo](https://gohugo.io/) to gen
Being cool has its complications though. How and where should you deploy your Hugo app. Should you push it locally using rsync or some other fancy means? Whatever.
This simple post is going to show you how to deploy your Hugo app using Gitlab's Continous Integration feature. Something I've fallen in love with as I've understood how to set up builds and push out my code to production. I'll be using **Cloudfront/S3** to host my Hugo site. You can checkout the following links to get more familiar with how it works.
This simple post is going to show you how to deploy your Hugo app using Gitlab's Continuous Integration feature. Something I've fallen in love with as I've understood how to set up builds and push out my code to production. I'll be using **Cloudfront/S3** to host my Hugo site. You can checkout the following links to get more familiar with how it works.
* [A Handy Publish Script for Static Sites](/2016/08/21/a-handy-publish-script-for-static-sites-using-cloudfront/)
* [Using Free AWS SSL with Cloudfront/S3/Route53](/2016/02/14/using-free-ssl-and-cloudfront-for-an-angular-react-site/)
......@@ -24,7 +24,7 @@ This simple post is going to show you how to deploy your Hugo app using Gitlab's
1. First you need to [set up an account with Gitlab](https://gitlab.com/users/sign_in) if you have not already.
1. Then you need to [create a project](https://gitlab.com/projects/new).
1. Next you'll need to add Gitlab as a remote to your git files (where you currently have your cool Hugo app).
1. Last bit is to set up some Variables for your app. To deploy to S3 and fire off a Cloudwatch invalidation request, Gitlab is going to need your `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. You'll store these in the Gitlab variables (hint on the project page, click the gear drop down and select Variables).
1. Last bit is to set up some Variables for your app. To deploy to S3 and fire off a Cloudwatch invalidation request, Gitlab is going to need your `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. You'll store these in the Gitlab variables (hint on the project page, click the gear dropdown and select Variables).
![Variables](images/Screen Shot 2017-01-12 at 4.33.21 PM.png)
## The Gitlab CI file .gitlab-ci.yml
......
......@@ -8,7 +8,7 @@ tags:
This is no where in the documentation that I could find on Doctrine's site. I wanted to do search with a criteria of OR.
For example, in psuedo code
For example, in pseudo code
Find all Events where (first_name like 'Jim') OR (last_name like 'Jim') OR (title like 'Jim)
......
......@@ -8,19 +8,19 @@ tags:
## The Battle Field
Spam is like a flood of water. The dams do what they can, but let's face it, there is a force that penetrates our best efforts. The constant barrage of email to 'Enlarge this', 'Buy now', 'Meet sexy singles in your area' is eternal. Some how getting into your inbox makes the spammers money. I've yet to hear someone enjoy the spam they get, so I really scratch my head on their business model, but they keep coming, so we'll keep fighting.
Spam is like a flood of water. The dams do what they can, but let's face it, there is a force that penetrates our best efforts. The constant barrage of email to 'Enlarge this', 'Buy now', 'Meet sexy singles in your area' is eternal. Some how getting into your inbox makes the spammers money. I've yet to hear someone enjoy the spam they get, so I really scratch my head on their business model, but they keep coming, so we'll keep fighting.
## What to do
How do you fight it? First, I'll say that the web mail providers do a pretty good job of keeping spam at bay. They should, they have multiple millions of dollars to attack the problem. Google, Yahoo, and Hotmail (MSN) have pretty good filters. I have an account at all three and from best to worst is Google, Yahoo, MSN respectively.
How do you fight it? First, I'll say that the web mail providers do a pretty good job of keeping spam at bay. They should, they have multiple millions of dollars to attack the problem. Google, Yahoo, and Hotmail (MSN) have pretty good filters. I have an account at all three and from best to worst is Google, Yahoo, MSN respectively.
But what about the little guy (me). I'm the IT guy for a small local company and we need email too. I'm also a fan of Linux for its power and flexibility. So I've put together some free tools to help me fight this war and I keep added to the arsenal whenever a new weapon of choice is made avaiable. The great thing about these tools, they are free and quite advanced.
What about the little guy (me). I'm the IT guy for a small local company and we need email too. I'm also a fan of Linux for its power and flexibility. So I've put together some free tools to help me fight this war and I keep added to the arsenal whenever a new weapon of choice is made available. The great thing about these tools, they are free and quite advanced.
The power of open source is this: _Someone who works for passion will produce more and better than someone who works for pay_. Try as they might, the big software companies pay the best programmers to do their bidding, but they are competing with people who have a passion and are willing to work in their spare time.
## A Little History
When I first took up my current position, everyone (about 30 people) was milling through about 100-500 spam messages a day. It was awful and needless to say, inefficient. So I set up a [Postfix](http://www.postfix.org/) SMTP server with a [Cyrus IMAP](http://cyrusimap.web.cmu.edu/imapd/) server. I proceeded to install [Spamassassin](http://spamassassin.apache.org/) (SA) and use a cron script to have SA learn Ham and Spam every night.
When I first took up my current position, everyone (about 30 people) was milling through about 100-500 spam messages a day. It was awful and needless to say, inefficient. So I set up a [Postfix](http://www.postfix.org/) SMTP server with a [Cyrus IMAP](http://cyrusimap.web.cmu.edu/imapd/) server. I proceeded to install [Spamassassin](http://spamassassin.apache.org/) (SA) and use a cron script to have SA learn Ham and Spam every night.
Now all the associates had to do was drag spam into their Junk folder and SA would find and learn from them on a nightly basis.
......@@ -28,42 +28,40 @@ Easy enough, but the spammers are desperate. Soon they started including a bunch
## The Troops Rally
First of all, Bill Gates a few years back predicted that the spam problem would be solved in two years. Well that time has come and gone and most would agree, it's still a problem. So a guy named Meng Wong came up with the idea of publishing authorized senders for a domain in the DNS records, so an SMTP server could check this when it receives mail. This is called [Sender Policy Framework](http://www.openspf.org/) (SPF). It's quite effective in beating the spammers, who try to get in using what is called a "[Joe Job](http://en.wikipedia.org/wiki/Joe_job) ." Essentially, they can't send you email from your own domain. This works good, but is only effective if domains publish this info, and now we are maybe at 20% who have published this info. SPF does break one thing, forwarding. With SPF enforced, an SMTP cannot auto forward an email, but that's not such a big deal.
First, Bill Gates a few years back predicted that the spam problem would be solved in two years. Well that time has come and gone and most would agree, it's still a problem. So a guy named Meng Wong came up with the idea of publishing authorized senders for a domain in the DNS records, so an SMTP server could check this when it receives mail. This is called [Sender Policy Framework](http://www.openspf.org/) (SPF). It's quite effective in beating the spammers, who try to get in using what is called a [Joe Job](http://en.wikipedia.org/wiki/Joe_job) . Essentially, they can't send you email from your own domain. This works good, but is only effective if domains publish this info, and now we are maybe at 20% who have published this info. SPF does break one thing, forwarding. With SPF enforced, an SMTP cannot auto forward an email, but that's not such a big deal.
Unfortunately Microsoft decided to rename SPF to Sender ID, then they claimed that they championed this great new idea (they originally fought it, but that is common Microsoft practices).
## A Hero Arrives
_&quot;<span class="body">An invasion of armies can be resisted, but not an idea whose time has come.&quot; -Victor Hugo</span>_
>An invasion of armies can be resisted, but not an idea whose time has come. -Victor Hugo
Not really a technological breakthrough, but an idea. Spammers don&#39;t play by the rules, so if we force incoming spam to play by the rules, then spammers will get rejected. Spammers try to send an email once and if it gets delay or temporarily rejected, they just drop it and move on. It would be costly/inefficient for them to keep trying to deliver an email to you. The idea is [Grey-listing](http://greylisting.org/) . Simple. Keep track of the IP, To:, and From: addresses of each email in simple DB files. If this is the first time we&#39;ve seen this triplet, then reject the email with a temporary fail message (450).
Not really a technological breakthrough, but an idea. Spammers don't play by the rules, so if we force incoming spam to play by the rules, then spammers will get rejected. Spammers try to send an email once and if it gets delay or temporarily rejected, they just drop it and move on. It would be costly/inefficient for them to keep trying to deliver an email to you. The idea is [Grey-listing](http://greylisting.org/) . Simple. Keep track of the IP, To:, and From: addresses of each email in simple DB files. If this is the first time we've seen this triplet, then reject the email with a temporary fail message (450).
If this is a true SMTP server, it will try again at a later time (usually with in 5-15 minutes later). Grey-listing will keep rejecting the email for a certain period of time (usually 5 minutes) then it will let it through and the next email from that person will get right in with no delay.
This was pure gold. In the shop I work at, we cut spam by 90%, not really the spam that was in our inbox because SA was already doing a great job, but our Junk folders were about 90% smaller than before grey-listing.
The drawbacks. An initial delay in email delivery. There are also some popular domains that don&#39;t play correctly and those are let through with no delay. Some critics have stated they didn&#39;t want to create the extra bandwidth of having an SMTP server try back. Poppycock and Boulder-dash! When it connects, it only uses a few small packets to handshake before the whole message gets delivered. I&#39;m rejecting the email during the handshake before the message is delivered and not having to deal with the bandwidth that the spammer is using to deliver his message.
The drawbacks. An initial delay in email delivery. There are also some popular domains that don't play correctly and those are let through with no delay. Some critics have stated they didn't want to create the extra bandwidth of having an SMTP server try back. Poppycock and Boulder-dash! When it connects, it only uses a few small packets to handshake before the whole message gets delivered. I'm rejecting the email during the handshake before the message is delivered and not having to deal with the bandwidth that the spammer is using to deliver his message.
## For Your Eyes Only
Now, the new trick that is being pulled is image spam. The email has an image that has what the spammer wants you to know. Most are pharmacy or stock spams. Then they have text that is included to throw off the scanners like SA. This get their message around the scanners, because the scanners cannot read the image.
They&#39;ve stuck at us, now we open fire on them. The solution. [FuzzyOCR](http://wiki.apache.org/spamassassin/FuzzyOcrPlugin) plugin for SA. That&#39;s right. By the power of OCR technology, we can scan that image in the email for words and then run them against the SA scanner.
They've stuck at us, now we open fire on them. The solution. [FuzzyOCR](http://wiki.apache.org/spamassassin/FuzzyOcrPlugin) plugin for SA. That's right. By the power of OCR technology, we can scan that image in the email for words and then run them against the SA scanner.
Awesome!
In short when the email comes in it gets checked as follows
<div>
1. Postfix Headers are checked for way out of dates.
2. SPF checks to make sure the sending SMTP has the right to send via SMTP
3. Postgrey does the grey-listing
1. Rejects it with a 450 status if haven&#39;t seen this sender before
2. Accepts if sender has been seen before4. Spamassassin runs 1000&#39;s of tests on this email
1. If it&#39;s spam, status the email as such5. If there is an embedded image, FuzzyOCR will extract the words and run them against a list of bad words, this adds to SA threshold.
6. The email is delivered to Cyrus IMAP </div>
1. Postfix Headers are checked for way out of dates.
2. SPF checks to make sure the sending SMTP has the right to send via SMTP
3. Postgrey does the grey-listing
1. Rejects it with a 450 status if haven't seen this sender before
2. Accepts if sender has been seen before.
1. Spamassassin runs 1000s of tests on this email
1. If it's spam, status the email as such
5. If there is an embedded image, FuzzyOCR will extract the words and run them against a list of bad words, this adds to SA threshold.
6. The email is delivered to Cyrus IMAP </div>
No more spam.
......
......@@ -6,7 +6,7 @@ tags:
- Server Admin
---
Today I was faced with the challenge of finding all the JPG files in a a directory (and subdirecties of that) and copying them to another directory (striping out the subdirectory folder name).
Today I was faced with the challenge of finding all the JPG files in a directory (and subdirectories of that) and copying them to another directory (striping out the subdirectory folder name).
`
find /path/to/directory/ -iname "*.jpg" -exec cp '{}' /path/to/dest/dir/ \;
......
......@@ -16,7 +16,7 @@ Ignore the entire Magento <pre>/media</pre> folder.
media/**/*
`
The root repository .gitignore file will act as a global but can be overridden in subdirecties by creating a <pre>.gitignore</pre>in those directories.
The root repository .gitignore file will act as a global but can be overridden in subdirectories by creating a <pre>.gitignore</pre>in those directories.
### A Gotcha!
......
......@@ -4,10 +4,10 @@ date: "2013-11-23T11:19:38-05:00"
tags:
---
Instant messangers are so vital to communcation on the web these days, both in and out of an organization. Let's take a look at some of the popoular ones out there with their pros and cons. As we compare them, we'll consider cost, features, portability, and easy of use.
Instant messengers are so vital to communication on the web these days, both in and out of an organization. Let's take a look at some of the popular ones out there with their pros and cons. As we compare them, we'll consider cost, features, portability, and easy of use.
## Google Hangouts
Gtalk has been sort of reborn as Hangouts. This web based solution has even just recently had another update that makes it very appealling for group video chats. With hangouts you can contact anyone that has a Google account. Hangouts also supports third party pluggins that help do things like record a video chat session or have your name appear below your video like a news caster does on TV. Screen sharing in Hangouts works great while on a video call.
Gtalk has been sort of reborn as Hangouts. This web based solution has even just recently had another update that makes it appealing for group video chats. With hangouts you can contact anyone that has a Google account. Hangouts also supports third party plugins that help do things like record a video chat session or have your name appear below your video like a news caster does on TV. Screen sharing in Hangouts works great while on a video call.
### Pros
* Ubiquity of the Google network (many people have at least one Google Account)
......@@ -34,7 +34,7 @@ HipChat and Campfire have a lot in common, but HipChat goes well beyond Campfire
### Pros
### Cons
* It's easy to miss undread messages as it does not track these like other instant messaging service.
* It's easy to miss unread messages as it does not track these like other instant messaging service.
## Skype
......
......@@ -21,11 +21,11 @@ MongoDB is a *Document Store*, not to be confused with a database as you are pro
* Data that does not change much
* Data with different nested structure you don't really care about consistent fields
For example. Let's say you have a device and it logs a large number of things about itself every second. Say, a phone that logs its latitude, longitude, battery charge, network information, and more. Later you'll want to query or search this information, but it doesn't need to be updated since you are recording a log. MongoDB would be great for this. Since it can handle huge amounts of data and it really doesn't have to be consitent.
For example. Let's say you have a device and it logs a large number of things about itself every second. Say, a phone that logs its latitude, longitude, battery charge, network information, and more. Later you'll want to query or search this information, but it doesn't need to be updated since you are recording a log. MongoDB would be great for this. Since it can handle huge amounts of data and it really doesn't have to be consistent.
## What MongoDB doesn't do very well
## What MongoDB doesn't do well
The appeal to me initially was being able to keep the schema of my data in the app and have the app worry about field names. MongoDB doesn't care if you feed it different types of data with each insert into a collection. It will happily create the corrisponding field in a related data format. It might not be the type of data you want, but life goes on.
The appeal to me initially was being able to keep the schema of my data in the app and have the app worry about field names. MongoDB doesn't care if you feed it different types of data with each insert into a collection. It will happily create the corresponding field in a related data format. It might not be the type of data you want, but life goes on.
### Missing or misspelled fields
......@@ -58,13 +58,13 @@ function getAmount(amount) {
```
### Inconsistancy in your data
### Inconsistency in your data
For some weird reason, a few of the passwords in the database were being stored as plain text instead of a hash. This was very disconcerting. I'll write more later on why you should not be doing password hashing in the app (hint: let the database do it). In other cases, since I didn't do a lot of data validation on some fields, I noticed that people were using the app in very strange ways. Like storing weird meta values in the a person's email record. I guess they were just being creative in how they stored data.
For some weird reason, a few of the passwords in the database were being stored as plain text instead of a hash. This was very disconcerting. I'll write more later on why you should not be doing password hashing in the app (hint: let the database do it). In other cases, since I didn't do a lot of data validation on some fields, I noticed that people were using the app in very strange ways. Like storing weird meta values in a person's email record. I guess they were just being creative in how they stored data.
## Conclusion
Building a web app with users, data, settings, etc? Use Postgres as your database. If you need to store massive amounts of log or complex JSON object data, then use MongoDB. As an added bonux, Postgres has so many built in features, it can actually do many of the things you were doing in the app. Such as updating timestamps, computing user password hashes, and much more.
Building a web app with users, data, settings, etc? Use Postgres as your database. If you need to store massive amounts of log or complex JSON object data, then use MongoDB. As an added bonus, Postgres has so many built in features, it can actually do many of the things you were doing in the app. Such as updating timestamps, computing user password hashes, and much more.
## But What About Migrations of Schema
Since I use Node.js mostly, I use the wonderful [Knex](http://knexjs.org) module that you can write migrations in this manner
......
......@@ -101,7 +101,7 @@ export default Reflux.createStore({
// This is magic that matches up the Actions to the listening methods below
listeners: Actions,
init() {
// Need to provide the initial value to compenents
// Need to provide the initial value to components
return person;
},
......
......@@ -6,7 +6,7 @@ tags:
- Programming
---
Search seems so simple on the surface, but inside it's a very complex thing (just ask Microsoft why they still haven't beaten Google at this game). Magento offeres some search options for products, but it's search is not 'awesome', but just OK.
Search seems so simple on the surface, but inside it's a complex thing (just ask Microsoft why they still haven't beaten Google at this game). Magento offerers some search options for products, but it's search is not 'awesome', but just OK.
Here are some options I've found that return a small set of products that are most accurate.
......@@ -15,11 +15,11 @@ System > Config > Catalog > Catalog Search
- This will catch plurals pretty good as well as slight spelling variants
2\. Disable quicksearch for 'Descriptions'
- This is imnporting in cutting down the cruft in search results.
- This is importing in cutting down the cruft in search results.
Wish List for Magento Search.
* Suggested Products. When someone searches for 'screwdriver' I want to suggest a certain specific product at the top of the search results.
* Better Synonim support
* Better Synonym support
* Spelling suggestions
* Category Search. If someone searches for 'boots' I want to display catagories whose names match that search, e.g. 'Womens boots' 'Mens boots'.
* Category Search. If someone searches for 'boots' I want to display categories whose names match that search, e.g. 'Women's boots' 'Men's boots'.
......@@ -33,9 +33,9 @@ Integration testing was not easy either, since I was using `Zend_Test_PHPUnit_Co
### Unit testing and Integration testing in Node.js and ExpressJS
Thanks to [TJ Holowaychuk](https://github.com/visionmedia), unit testing with [MochaJS](http://visionmedia.github.com/mocha/) is pretty simple. I take that back, getting your head around it is a little of chore, but once you understand the difference between MochaJS (framework) and [ChaiJS](http://chaijs.com/) the actual tests, from there on out, it's dead simple to unit test business logic.
Thanks to [TJ Holowaychuk](https://github.com/visionmedia), unit testing with [MochaJS](https://mochajs.org/) is pretty simple. I take that back, getting your head around it is a little of chore, but once you understand the difference between MochaJS (framework) and [ChaiJS](http://chaijs.com/) the actual tests, from there on out, it's dead simple to unit test business logic.
Integration Testing is awesome. Get this, [MochaJS](http://visionmedia.github.com/mocha/) employs [SuperTest](https://github.com/visionmedia/supertest) which uses [SuperAgent](https://github.com/visionmedia/superagent) all of these written by [TJ](https://github.com/visionmedia). It actually fires up a Node.js server on a random port to run the test and then shutsdown. Once you have it set up, it's really easy to write loads of API tests. Check out my dead simple [Makefile](https://gist.github.com/4057439)... you just need to type `make test` and it will run your tests (you can even have them run automagically when a file changes). Mind = Blown.
Integration Testing is awesome. Get this, [MochaJS](https://mochajs.org/) employs [SuperTest](https://github.com/visionmedia/supertest) which uses [SuperAgent](https://github.com/visionmedia/superagent) all of these written by [TJ](https://github.com/visionmedia). It actually fires up a Node.js server on a random port to run the test and then shutsdown. Once you have it set up, it's really easy to write loads of API tests. Check out my dead simple [Makefile](https://gist.github.com/4057439)... you just need to type `make test` and it will run your tests (you can even have them run automagically when a file changes). Mind = Blown.
## 3 PHP does not lend itself to scaling
......@@ -51,7 +51,7 @@ The [12 Factor App](http://12factor.net) lays out really good advice to web apps
1. II Dependency
PHP installs vary so much depending on which modules are install. I have never installed modules locally to satisfy the dependancy. They are ususally installed by PEAR in some common place on the server.
PHP installs vary so much depending on which modules are install. I have never installed modules locally to satisfy the dependency. They are usually installed by PEAR in some common place on the server.
**Node.js** stores all needed modules locally in the app under the `node_modules` folder. And NPM is the bomb (does that still mean cool?)
......@@ -69,9 +69,9 @@ The [12 Factor App](http://12factor.net) lays out really good advice to web apps
## 5\. Package Management or PEAR versus NPM
This is not even a fair fight. **PEAR** is _old and busted_, **NPM** is the _new hotness_. I cringe when I have to try to use PEAR to install stuff. First you have to make sure you have a `channel` installed in PEAR to get the packages that channel provides. Dependancy hell is another reason to loath PEAR.
This is not even a fair fight. **PEAR** is _old and busted_, **NPM** is the _new hotness_. I cringe when I have to try to use PEAR to install stuff. First you have to make sure you have a `channel` installed in PEAR to get the packages that channel provides. Dependency hell is another reason to loath PEAR.
NPM on the other hand is so easy to use. It's a central repo that anyone can upload modules to. All modules are stored in the local directory of that app so the app is entirely self contained. NPM also resolves dependancy like a boss.
NPM on the other hand is so easy to use. It's a central repo that anyone can upload modules to. All modules are stored in the local directory of that app so the app is entirely self contained. NPM also resolves dependency like a boss.
npm install express
......@@ -79,7 +79,7 @@ Done!!!
## The Bottom Line
Can you write complex, cool, fast, and awesome apps in PHP? Sure you can. Can you unit test, integration test, use environment variables, and satify local dependancies. Sure, but I've personally fallen prey to bad habits, forsaking unit testing, and more evils because it's convoluted to get it done in PHP.
Can you write complex, cool, fast, and awesome apps in PHP? Sure you can. Can you unit test, integration test, use environment variables, and satisfy local dependencies. Sure, but I've personally fallen prey to bad habits, forsaking unit testing, and more evils because it's convoluted to get it done in PHP.
It's been much easier for me to do all these things in Node.js and with **significantly less code**. I find that my code in JavaScript is MUCH more modular (code has a clean separation) which makes it much easier to unit test, use mocks and stubs.
......
......@@ -7,13 +7,13 @@ tags:
- Programming
---
[Tweetianium](https://github.com/appcelerator-titans/tweetanium) builds it's own namespace that it operates under rather than calling code that looks like the following to open up a new window.
[Tweetianium](https://github.com/appcelerator-titans/tweetanium) builds its own namespace that it operates under rather than calling code that looks like the following to open up a new window.
<pre lang="JavaScript">Ti.UI.createWindow({url:'somefile.js', importantdata: mydata });</pre>
This essentially uses different files to open new windows, it's managable to point, but I had trouble with not having some sort of global variables I could call on.
This essentially uses different files to open new windows, it's manageable to point, but I had trouble with not having some sort of global variables I could call on.
## In walks [Tweetanium](https://github.com/appcelerator-titans/tweetanium) and [Struct](https://github.com/krawaller/struct)
These keep the entirety of the code in basically a namespaced object. I have to admit, it took me 2-3 times looking over the code to really get it. Let me try to help.
These keep the entirety of the code in basically a name spaced object. I have to admit, it took me 2-3 times looking over the code to really get it. Let me try to help.
## app.js
......@@ -48,4 +48,4 @@ Some further files to investigate would be the _/tweetanium/ui/styles.js_ and th
## Resources:
* [https://github.com/appcelerator-titans/tweetanium](https://github.com/appcelerator-titans/tweetanium)
* [http://blog.krawaller.se/titanium-application-structure-learning-from ](http://blog.krawaller.se/titanium-application-structure-learning-from )
[https://blog.krawaller.se/posts/titanium-application-structure-learning-from-tweetanium/](https://blog.krawaller.se/posts/titanium-application-structure-learning-from-tweetanium/)
......@@ -12,7 +12,7 @@ Here are a few things to watch out.
## Getting PHP v5.2
Some of my apps are not ready to make the jump to PHP 5.3 just yet, so I needed to get a hold of PHP 5.2\. In the past I just install the [Zend Server CE](http://files.zend.com/help/Zend-Server-Community-Edition/rpm_installation.htm) it would have all the PHP bells and whistles I could ever need. Not anymore, now it's time to fend for myself.
Some of my apps are not ready to make the jump to PHP 5.3 just yet, so I needed to get a hold of PHP 5.2\. In the past I just install the [Zend Server CE]() it would have all the PHP bells and whistles I could ever need. Not anymore, now it's time to fend for myself.
**Webtatic Repo**
http://www.webtatic.com/blog/2009/06/php-530-on-centos-5/
......@@ -44,7 +44,7 @@ Here is the `/etc/init.d/php_cgi` init script.
#!/bin/sh
#
# php-cgi - php-fastcgi swaping via spawn-fcgi
# php-cgi - php-fastcgi swapping via spawn-fcgi
#
# chkconfig: - 85 15
# description: Run php-cgi as app server
......
......@@ -10,7 +10,7 @@ tags:
#### Summary
Create the illusion of mutliple backed up copies, but in reality only the changes are different thereby saving space on the HDD. Create a cron job to run the following script once a day. The script will keep 4 days of backups, edit the numbers to your liking. Utilizing some built in rsync features it will only store 1 copy of the file on disk unless it has changed.
Create the illusion of multiple backed up copies, but in reality only the changes are different thereby saving space on the HDD. Create a cron job to run the following script once a day. The script will keep 4 days of backups, edit the numbers to your liking. Utilizing some built in rsync features it will only store 1 copy of the file on disk unless it has changed.
#### The script
......
......@@ -8,7 +8,7 @@ tags:
Most everyone familiar with the Internet knows that Google is king of search. Even Yahoo and MSN know this, but haven&#39;t figured out how to match Google. Here is a hint for them. Google is king because of the shear amount of crawling that Googlebots perform.
For example, I just launched a website this week dedicated to to the Boundary Waters Canoe Area (BWCA), a national forest in north east Minnesota that is accessible only by canoe. It allows maps, forums, photos, and other information for those that are planning a trip in the BWCA.
For example, I just launched a website this week dedicated to the Boundary Waters Canoe Area (BWCA), a national forest in north east Minnesota that is accessible only by canoe. It allows maps, forums, photos, and other information for those that are planning a trip in the BWCA.
[http://www.wildpaddle.com](http://www.wildpaddle.com)
......
......@@ -115,7 +115,7 @@ function async validateResetCode (id, code = '', ctx) {
const timestamp = Buffer.from(timeHash, 'base64').toString('ascii')
// If more then 24 hours, then fail
// If more than 24 hours, then fail
const diff = differenceInHours(new Date(timestamp), new Date())
if (Math.abs(diff) > HOURS_DIFF) return false
......
......@@ -26,6 +26,6 @@ The work around for me has been to declare the socket in my application.ini file
resources.db.params.unix_socket = "/usr/local/zend/mysql/tmp/mysql.sock"
`
The problem this introduces, haveing a different application.ini on the server and on then on my local devel machine.
The problem this introduces, having a different application.ini on the server and on then on my local devel machine.
Ugggg.
> Ugggg.
......@@ -48,7 +48,7 @@ These are functions your database can easily handle without breaking a sweat
* Transforms: lowercase / uppercase values on insert ✅
* Atomic Updates: automatically update a timestamp e.g. `updated_at`
* Constraints: For example, if you only want to allow three addresses for a person ✅
* Defaults: Values, create them in the database and allow them to be overriden by your app ✅
* Defaults: Values, create them in the database and allow them to be overridden by your app ✅
**OK, that was a rabbit trail, back to the main subject ENUMs**
......@@ -58,7 +58,7 @@ Let's look at a couple of notes about ENUM types. First, we'll start with this E
CREATE TYPE phone_type as ENUM ('MOBILE', 'WORK', 'HOME')
```
1. You can add to an ENUM type, but not remove. Add another enum value with `ALTER TYPE item_status ADD VALUE IF NOT EXISTS 'OTHER'`. Just know that `OTHER` is now permenantly in that type. It cann't be easily removed.
1. You can add to an ENUM type, but not remove. Add another enum value with `ALTER TYPE item_status ADD VALUE IF NOT EXISTS 'OTHER'`. Just know that `OTHER` is now permanently in that type. It cann't be easily removed.
1. Altering an ENUM type must be done outside of a transaction. Nuff said.
......@@ -99,7 +99,7 @@ This is part of learning what you really want from your database. We had a many
END;
$$ language 'plpgsql';
```
You'll notice that the table trigger will check if another record exists and automatically set the `is_default` value. Pretty slick. The only problem we saw was another race condition (see a pattern). When the client would call the same endpoint with different values. Each insert ran in it's own transaction and therefor the `is_default` was set to true.
You'll notice that the table trigger will check if another record exists and automatically set the `is_default` value. Pretty slick. The only problem we saw was another race condition (see a pattern). When the client would call the same endpoint with different values. Each insert ran in its own transaction and therefor the `is_default` was set to true.
3. Stepping back and looking at the problem, we really didn't care about an `is_default`, we mostly cared about about detecting the first insert. This can be done with a timestamp. So instead we decided to use a `created_at` field with a default value of `now()`. The only drawback now is we have to derive the `is_default` value by looking at other records and determining if this is the oldest timestamp.
......@@ -111,7 +111,7 @@ This is part of learning what you really want from your database. We had a many
## UNION ALL
We found `UNION ALL` to be a powerful way to combine multiple tables together that had similar types of content into a single view. For argument sake, we didn't go the route of complete normalization because of some difficultly setting up the data. So we would create a view that looked like this (a poor example, but simple none the less).
We found `UNION ALL` to be a powerful way to combine multiple tables together that had similar types of content into a single view. For argument sake, we didn't go the route of complete normalization because of some difficultly setting up the data. So we would create a view that looked like this (a poor example, but simple nonetheless).
```
CREATE VIEW people (
......@@ -138,7 +138,7 @@ This pattern works well as you are discovering your data requirements, but shoul
## Proper handling of IDs and field names
I'm going to breifly touch on `ID`s, but this subject deserves it's own blog post (look for it soon).
I'm going to briefly touch on `ID`s, but this subject deserves its own blog post (look for it soon).
1. Most concrete table types should have an `id` field. It's just easier to lookup, select, join, and delete.
1. NEVER use auto-increment
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment