Ignored By Dinosaurs 🦕

generaldevelopment

When I first started getting into this, I read a lot on PHP and remember clearly having my eyes go crossed when I came across code like this —

<?php
// Example code: Creating Drupal 7 nodes by POSTing from cURL in PHP:

$site = "127.0.0.1/d7";
$user = "someusername";
$pass = "theusersassword";
$crl = curl_init();
curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($crl, CURLOPT_USERAGENT, 'PHP script');
curl_setopt($crl, CURLOPT_COOKIEJAR, "/tmp/cookie.txt");
curl_setopt($crl, CURLOPT_COOKIEFILE, '/tmp/cookie.txt');

/// etc, etc, etc
// taken from http://blog.ampli.fi/creating-drupal-7-nodes-with-php-via-the-restws-api/

So, in a nutshell, Curl is a very popular Linux/Unix command line program for doing things across the internet – downloading things, uploading things, pinging remote servers with requests, etc. Curl has a wealth of options that you can set with command line flags (-I to only get response headers, -D to post form data, -X to specify a HTTP method, etc).

PHP has a built in function for working with Curl, thereby making it easy to programmatically make HTTP calls to other servers. Of course, to really be able to use Curl in a way that's analogous to it's usage on the command line, you need a way to set those flags. curl_init() sets all that up for you, and all you really need to do after that is set whatever flags you need in calls to curl_setopt().

See the docs here – https://php.net/manual/en/function.curl-init.php.

#php #generaldevelopment

I've got this decoupled CMS brewing in my head, and wanted to jot down what I think would be a kind of cool method for generating URLs and URL redirects and making sure everything stays in sync without having to maintain a giant table of redirects (ala Drupal).

The basic scheme would look like this — site.com/{item_type}/{item_id}/{item_slug}. The type parameter could probably be optional, but it's there for now. An example URL could be ignoredbydinoaurs.com/posts/123/the-totally-awesome-seo-juice.

Of course, in whatever framework you're working in, those url segments are going to be broken down into tokens passed into whatever controller function is running the query. So your query would/could look like this in the controller


def show
	@post = Post.find(params[:id])
	if @post.slug != params[:slug]
	redirect_to "/#{@post.type}/#{post.id}/#{@post.slug}", :status => :moved_permanently
	end
end

This has the advantage of never going out of sync with a redirect table, and never opening up the possibility of having an alias and a redirect create a loop. This happens often in Drupal, so with this scheme, you're only looking up based on an item's ID, which should never change. If somehow a URL has made it out in the the wild that is not the preferred URL, nothing breaks, it just gracefully performs a redirect to the proper URL.

The only significant portion of the URL is the ID, everything else is decoration or SEO juice.


Somewhat off topic, but if you had a use cases where you were running multiple sites out of this CMS, and you had editors that frequently shared content, or wrote up each other's content for a sister site, then the primary key of of the article can stay consistent across different publications.

“How would different editors utilize each other's content in that case? Like, how would different pubs have the same article with a different summary on this instance from that instance?”

PostgreSQL schemas, that's how. I'll write that up, probably sometime in 2017.


2016, Django update

This wasn't exactly hard to do, but I was surprised to find that nobody really wrote up how to simply issue a redirect like this in a Django view (controller to the rest of the world). Assuming that get() or get_queryset() was the answer, but I was wrong. This was the help piece of info that I needed. Did I mention how much I love Django's docs?

This is the method that drives this very page.


class DetailView(generic.DetailView):
	model = Post
	
	def dispatch(self, request, *args, **kwargs):
	object = get_object_or_404(Post, pk=self.kwargs['pk'])
	if object.slug != self.kwargs['slug']:
	return redirect(object, permanent=True)
	# else, delegate up
	return super(DetailView, self).dispatch(request, *args, **kwargs)

#generaldevelopment #rails #django

Nginx configs

So I recently had a couple of seemingly disparate tasks come across my desk. We recently launched a HMTL mobile app, an Angular front end to our Drupal sites. We decided to completely decouple the mobile app from the Drupal codebase after a fairly long exploratory period trying out different approaches.

When launch day finally came, we set up the mobile app at app.$$BRAND.com, with our main sites at www.$$BRAND.com. Acquia has this cool feature in their Varnish layer that will filter user-agent strings for ones that match a set of “mobile” user agents that they have defined in a central file. So flipping folks on iPhones over to the mobile site was a piece of cake. What I forgot was that the same logic wouldn't be triggered for the reverse — flipping desktop users to the desktop version of the site from app.$BRAND.com. (Our mobile app is hosted on our own, not with Acquia).

I already had a big list of regexes to test mobile user agent strings with (thanks Acquia!), so the trick was to recreate that in Nginx, the webserver for our mobile app.

Not wanting to do a bunch of evil if {} statements in the Nginx configs, I cast about for a more elegant solution, eventually stumbling upon map.

The Nginx map module

http://nginx.org/en/docs/http/ngxhttpmap_module.html.

So basically what this does is to test any arbitrary Nginx variable for some condition, and spit out a custom variable that you can user in your config. An example —-

map $http_user_agent $device_redirect {
  default "desktop";
  ~(?i)ip(hone|od) "mobile";
  ~(?i)android.\*(mobile|mini) "mobile";
  ~Mobile.+Firefox "mobile";
  ~^HTC "mobile";
  ~Fennec "mobile";
  ~IEMobile "mobile";
  ~BB10 "mobile";
  ~SymbianOS.\*AppleWebKit "mobile";
  ~Opera\sMobi "mobile";
}

This takes a look at the incoming user agent string (fun fact — grab any request header with $http_NAME_OF_HEADER) and compares it against a set of regexes. If one of them is a match, then the $device_redirect variable gets set to “mobile”, otherwise, it's set to the default of “desktop”. This gets used later in the config —

if ($device_redirect = "desktop") {
  return 301 $scheme://$desktop_host$request_uri;
}

In other words, if the user agent doesn't match one of those regexes, redirect the user to the desktop site. Pretty neat!

As a side note, does anyone else think it's weird that the comparison syntax in that if statement only uses one '='? But yeah, that's the right way.

Later that day, on a different Angular app

So that mobile app and this one that I'm about to talk about kinda conform to the Drupal concept of “multisite”. That is, a single codebase that serves a variety of different sites. I figured out a pretty simple hack for this one that maybe I'll share in another blogpost if I get around to it, but basically it involves setting a siteVar in the bootstrapping phase of the Angular app based off of the window.location.hostname. I have a Config Angular service that stores the mapping of hostname to siteVar. It's easy and it works.

The way we serve different stylesheets to different brands is by setting up a sites/$BRAND/ folder that houses site specific styles, etc. When Angular bootstraps, it uses the siteVar variable to fill in $BRAND, and the site specific stuff is loaded. It's easy and it works. Except in Firefox.

Firefox doesn't like this setup, and particularly on the favicon, it proved to be a real PITA.

The default Yeoman favicon would always show up in Firefox, nothing else, since we had that favicon path set dynamically by Angular after the app loaded. it just wasn't responding to any of the usual hacks, and it turns out FF has a long and storied history with the favicon.

Having just found the perfect hammer for the previous problem, I thought I'd see if it could solve this one.

Map all the things...

So for this one, I have an Nginx map companion to the one that I have in Angular.

map $http_host $sitevar {
  default "";
  ~rdmag "rd";
  ~alnmag "aln";
  ~bioscience "bt";
  ~cedmagazine "ced";
  # etc...
}

This maps the incoming host variable on the request to a $sitevar variable, used like this...

location /favicon.ico {
  try_files /sites/$sitevar/favicon.ico $uri;
}

So the browsers that respect the dynamic favicon path continue to work, and if FF never cooperates, Nginx catches that request and fixes the problem before anybody knows...

#devops #generaldevelopment #angular

I've finally been getting around to using Redis for caching on this blog and other Rails projects I've got laying around, and I've finally gotten around to Homebrewing PHP 5.5 to use for my local set up at work. Jose's default PHP 5.5 brew doesn't install the new Opcache, so look around and make sure you install that version because it screams.

I guess you could fairly say that caching has been on my mind a lot lately as I also finally got around to installing and using Memcached here in development with our company's Drupal sites. That's also a separate Jose homebrew install, so look around for that, too. Anyway, after fiddling around with all the Drupal configs that I had commented out previously that dealt with Memcached, I got it up and running. Make that hauling ass. It's a lot of fun.

So of course, the next step is to install some outdated script that gives me some visibility into the cache statistics. Here's where I get to the point.


Out of the box, the Homebrew installation of Memcached gives you 64M, which is also what you get if you install it from Aptitude on Ubuntu. I've finally done enough Ubuntu to get that most config files are stashed somewhere in /etc (/etc/memcached.conf), but where do these files live on the Mac?

This is the only downside to Homebrew, that most of the brewers (and God bless y'all, not complaining) pick some arbitrarily weird places to stash stuff, and crazy commands to access the executables. mysql.server start? What distro does that come from? It just doesn't make a lot of sense, but I guess that's what keeps your mind sharp.

Anyway, I wanted to feed Memcached some more memory, and I couldn't find the config file for the life of me. Maybe you're here for the same reason. I dug pretty deep into Google before I found the answer. It's in ~/Library/LaunchAgents/homebrew.mxcl.memcached.plist.

Out of the box it looks like this —

xml version="1.0" encoding="UTF-8"?

Label
homebrew.mxcl.memcached
KeepAlive

ProgramArguments

/usr/local/opt/memcached/bin/memcached
-l
localhost

RunAtLoad

WorkingDirectory
/usr/local


So instead of pointing at a config file, you just pass all the config in the startup command. To bump it up, you need to pass in -m 128, or however much you want to feed it, like this.

xml version="1.0" encoding="UTF-8"?



Label
homebrew.mxcl.memcached
KeepAlive

ProgramArguments

/usr/local/opt/memcached/bin/memcached
-l
localhost
-m
256

RunAtLoad

WorkingDirectory
/usr/local


#devops #generaldevelopment

This is a little collection of books that I've found helpful over the past few years, ranging from design to development to business to fiction.

Ruby/Rails

* The Well-Grounded Rubyist: David A. Black: Books”) – Great second programming book. * Agile Web Development with Rails: Sam Ruby, Dave Thomas, David Heinemeier Hansson: Books”) * Metaprogramming Ruby: Paolo Perrotta: Books”) * Learn to Program (9781934356364): Chris Pine: Books”) – Great first programming book. * Design Patterns in Ruby: Russ Olsen: Books”)

Drupal

* Using Drupal: Angela Byron, Addison Berry, Nathan Haug, Jeff Eaton, James Walker, Jeff Robbins: Books”) – Great first Drupal book. * Drupal 6 Search Engine Optimization: Benjamin Finklea: Books”) – Great general SEO book with heavy Drupal focus. * Pro Drupal Development: John K. VanDyk: Books”)

General Front End Development / Design / Usability

* CSS: the Missing Manual: David Sawyer McFarland: Books”) * Jquery Cookbook (9780596159771): Cody Lindley: Books”) * Don't Make Me Think!: Steve Krug: Books”) * Web Design for ROI: Lance Loveday, Sandra Niehaus: Books”) * The Design of Everyday Things: Donald A. Norman: Books”)

General Back End Development / Databases

* Learning SQL: Alan Beaulieu: Books”) * Beginning Database Design: Clare Churcher: Books”)

iPhone / Cocoa

* Cocoa Programming for OS X Programming for Mac® OS X (3rd Edition) (9780321503619): Aaron Pablo Hillegass: Books”) * iPhone SDK Development (9781934356258): Bill Dudney, Christopher Adamson: Books”)

General Business / Startup Culture

* Founders At Work (9781430210788): Jessica Livingston: Books”) * Tribes: Seth Godin: Books”) * Linchpin: Seth Godin: Books”) * Blink: Malcolm Gladwell: Books”)

#generaldevelopment

May I suggest you download this book — Learn Python the Hard Way? It's got instructions in the very first bit about getting a decent, free text editor installed. TextEdit that comes with the Mac leaves quite a bit to be desired, and though I haven't personally checked out GEdit, I'm sure it's a step up. Of course if you think you might want to get serious about this, or if you get serious about this down the line, may I suggest dropping $60 on TextMate? I know it's kind of a lot of money, but if you get into this stuff, it's worth it.

May I also suggest that you go through the first few exercises? It's fun to make your computer do things, however rudimentary, and doing them in the babystep fashion that this has you do eases you into programming geekery like the command line. It trains your fingers, it trains your eyes. It's like that part in Rocky 4 where he goes to Siberia to toughen up against Drago.

Back soon. Cheers.

#generaldevelopment

Does anybody here want to build something? My buddy Jimmy of This Blog fame laid an idea on me the other night. He's a teacher, and a fairly progressive, observant one at that. I believe him when he says that there's nothing out there like this kinda simple, cool idea that he had. I think it must exist somewhere but it's not being properly promoted if it does. So, I thought maybe it'd be a cool idea to try and teach him a little something about web development, and teach myself a lot in the process. There's no way that this idea of his is currently within my grasp since a big part of the concept is an iOS app, but I don't think the overall idea is really that far outside the realm of possibility. It's going to need a web backend to it, anyway. So let's see. Where to start?

I think we'll build it in Rails since I've learned enough about programming to know that I prefer Ruby as a language to PHP. I think this idea could easily be done in Drupal (a large, flexible content management system that's built in PHP) as well, but for some reason the aesthetic of building the solution you need and no more is really appealing to me. Drupal takes care of a LOT of the stuff that we're going to need to do upfront, things like user authentication (accounts) and interacting with a variety of different protocols – essential if the app phase is ever going to work. Drupal and Rails are both just pieces of software that run databases for you, but the difference is sorta like the difference between buying a really good loaf of bread and baking a really good loaf of bread. It doesn't make you any less of a chef to serve the store bought loaf to your guests, but if you have the time and you know how to bake a good loaf (or if it's just something you want to get good at), you're going to prefer that route.

Step one is getting Rails installed on your computer which, if you bought a Mac is made significantly easier. We'll do that next.

#generaldevelopment

Welcome back to another installment of the newby web developer series. This morning's entry comes once again from our buddy Jimmy, who the two of you reading might know as the highly technically inclined CT robo-teacher. He'll probably be reforming the state of education in your state soon.

What's up fool.

My friend wants me to build him a simple site using wordpress. He already owns the domain name.

My question is, once I build the site using MAMP, and get everything upload to our host, how does the domain name get transferred? Is that something we have to handle or the host handles.

Thanks, Jimmy

Calling me a fool is his way of showing affection. So, the answer is that “it depends”. If your buddy went the “get your domain free with a year's webhosting” route that many larger webhosts encourage you to do, then you don't have to do anything. If your buddy bought the domain on the open market through a registrar such as GoDaddy, you have to dive into the scary, subterranean world of DNS.

DNS stands for Domain Name System. A perhaps less-than-100%-accurate description —

When you buy a domain name, it's sort of like buying a spot in the world's internet phone book. That is to say that the address http://johnnygrubb.com is actually an “abstraction” of the information that a computer needs to complete your browser's request to get my webpage to come up. What my computer needs to know is the IP address of the server where http://johnnygrubb.com lives. The Domain Name System does that for you.

If you need to look up the phone number of Newtown Chinese Restaurant in Newton, you go to the phone book, look for Newtown Chinese Restaurant and move your eye to the right to get the phone number. If you want to go to any website, you enter the address in your browser, which takes the request and hits the nearest DNS server to find the actual IP address of the webhost so the requested page can be grabbed. It's the job of the owner of the domain name to make sure that the “phone number” or IP address is correct.

If you've bought your domain name as part of a package, then you don't need to do anything. The webhost actually owns the domain name and is letting you use it. This has pros and cons obviously, the pros being that they handle all of this DNS stuff for you.

If you've bought the domain name separately, you need to give that name a “phone number” so that DNS knows who to call when you request a page from that site. That's done by getting deep into your Domain Control Panel (or something like depending on the registrar) and and finding the “Nameserver” controls. This is where you give your domain name an address. It's usually in an english readable form, for instance, one of the nameservers for my hosting account is ns1.mediatemple.com. That means that when a request is made for a page on this site, DNS says “don't look at me, go talk to Media Temple's nameservers. They know where to find that page.” Once the request gets to Media Temple, their nameservers say “the page you seek is at 64.207.129.18”, which is the IP address of the actual server on which this site is plopped.

So, to extend the analogy a little further, a DNS lookup is actually more like that movie where the kids are trying to find the super-cool party, only to get to the party they have to drive all over town from one destination to the next before they are finally given the actual address. For real fun, type this is your Terminal —

traceroute http://ignoredbydinosaurs.com This command will show you all of the different “nodes” out there on the web that your request hits before it actually arrives at it's destination, my webhost.

So, the tl;dr is that if he bought the domain name through a webhost as part of a hosting package, you don't need to do anything. If he bought the domain name on it's own, you need to go to the Domain Control Panel or the Domain Manager or whatever it's called where it was registered. In there somewhere is a setting for the nameservers. On the webhost's end, you'll find what their nameservers are (usually something like ns1.awesomewebhost.com and ns2.awesomewebhost.com) and put that information into the proper fields on the registrar end. There's always at least 2 nameservers at every host because like all servers, they can go down and if they both go down your site will be unavailable. It happens.

Changing nameserver information is like firing an MX missile. There is no “undo”. There is no recalling the missile. Once you push the button to change the nameservers, that change of address starts filtering out to the rest of the world's DNS servers so that the request can be sent to the proper IP address. This filtering-out process can take anywhere from a few hours to a few days, depending. Once it's done, the whole world will be pointed to the party on your server.

#generaldevelopment

I am having a blast. I found a nice photo gallery Gen Next – has lots of cool features; still working on it.

I do need some help:

1) how do I keep the 'home' page of the WP site clear of posts? I just want to put some html text and links. It seems to always show the latest posts. I need to understand what is going on with that page.

2) How can I order the posts within a category. example: For Lyrics I have category per album with a post for each song. I need to order them in track order, it seems to always put the newest post first. Ordering by permalink would work since I put the track number as the 1st part of the name.

3) Gotta turn off the right nav stuff – not needed.

I tried creating a category called Lyrics and then adding sub-categories for each album. That created the Lyrics page with all songs listed, I wanted just links to the sub-categories; plus it made the menu real ugly with all the albums listed below main menu. I resolved this by making Lyrics a page and putting links to the 'album' categories in the html. It seems to work fine but I am not sure if I could have done this another way.

also: where do I comment out the 'add comments' stuff?

Alright, in order —

  1. Go to Settings –> Reading and set the top option to display a static page as the home page. You'll have a list of options for which static page you want.
  2. As with almost any programming challenge, there are a couple of ways to go about it. I'm not exactly sure how you want them to display in every situation, but I'll take a beginning guess.
    1. The easiest, and in this case probably best way to go is to just make sure you enter the lyrics for the songs in the reverse order than how you want them to appear. If you've already entered some of them in, you can alter the “published date” on the edit screen of each lyric page. I'd just edit that have them line up in the order that you want.
    2. The more stylish option would be to write a function in your theme's functions.php file. To make this work correctly you'd have to make use of the “custom fields” feature. I'm a tiny bit rusty on the exact way to go about this, but basically “custom fields” are extra bits of metadata that you can add to any page or post in WP. For instance, you could create one custom field with a key called “track number” and use the value of that field to define the track number. You'd then figure out the correct function to call with the correct arguments to make it show up in the right order when someone came to the lyrics section of the site.
    3. Doing the same thing from the theme template would also be an option, and probably a little more realistic since you'd be able to have the correct template called by following the naming convention for a given category. This page will tell you how.
    4. Slightly off-topic, but there's also the option of creating a blanket “Lyrics” category, and then creating a post for each album that simply lists the songs in the running order, and then links the song titles to another post that contains the lyrics for that song. This option might give you the most control for the least effort.
  3. So you don't need a right sidebar at all?
  4. Right, yeah I would ditch the sub-categories for the albums, and probably go with option 4 above.
  5. If you look at line 29 on the page.php file and line 39 on the single.php file, you'll see the comment function. I'd just comment it out so it reads -

<?php //comments_template( '', true ); ?>

and your comments will be gone.

#generaldevelopment

So, you've spent the last few months teaching yourself Wordpress. Good job. There are lot of crappy websites out there, most of them built by some site-builder commodity crap-stuffer at GoDaddy or Network Solutions or some other budget host. These are God-awful examples of poor web development practices. They're ugly. They don't render correctly in browsers. Many are all but invisible to search engines, which begs the question – if a website fails to show up in the first couple of pages of Google, does it make a sound?

Wordpress is a wonderful tool to combat these evils. It's easily editable. It's easy to learn. It's east to add features. It's typically built using modern presentation techniques that actually DO show up in search engines. The Thesis theme is a marvel of SEO and will get your page – pretty much no matter what – up on to the first page of Google depending on what you're writing about.

Neither here nor there, because you already have an idea of most of this stuff. You've been tinkering around with MAMP and wordpress on your computer and now you want to know how to get your creation up and visible to the world. This is involves two simple steps, and rather than repeat them, I'll just link to the site where I learned how to do it.

http://weeklywp.com/2009/06/move-wordpress-to-a-new-server/ Questions and requests for clarifications are most welcome. The first big hint is on the front page of the MAMP welcome page. PHPMyAdmin is a database tool for managing your database. That's where you'll export the database that you've been using to develop locally and upload it to your webhost. Follow the instructions in the tutorial. Every webhost I've seen so far has PHPMyAdmin installed somewhere, but where they'v hidden it usually varies. If you are installing this on a server that's owned by, say, the Stamford school system, you might need to talk to an IT admin to get it happening.

#generaldevelopment