Categories
Troubleshooting Tutorials

Ruby/Homebrew breaking with OS X 10.10 Yosemite Upgrade

Warning: I’m assuming if you have homebrew installed then you are familiar with the command line. If you aren’t familiar, don’t attempt this or ask someone that is.

Apple updated Ruby from 1.8 to 2.0 in Yosemite, so homebrew might not work and you’ll see an error like this:

/usr/local/bin/brew: /usr/local/Library/brew.rb: /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby: bad interpreter: No such file or directory

If you haven’t upgraded to Yosemite yet, run brew update first, and I think that will patch the Yosemite/2.0 issue.

If you have already updated, you’ll need to cheat a symlink to trick home-brew into thinking you are using 1.8 still. Run these commands:

$ cd /System/Library/Frameworks/Ruby.framework/Versions
$ sudo ln -s Current 1.8
$ brew update

Once that’s done, you should remove your symlink:

$ sudo rm 1.8
Categories
Tutorials Workflow

Batch Upgrading WordPress installs on server

PSA: You shouldn’t just willy nilly upgrade your WordPress installs. It’s best to test your upgrade in a staging environment.

Every time a WordPress update comes out, I cringe having to update all the sites on my VPS server. I finally hunkered down today and got a shell script written to upgrade all WordPress installs on a server.

This solution will upgrade on one server, so If you have WordPress installs sprawled across multiple servers, you might want to look into a service like ManageWP.

The key is wp-cli

wp-cli is a command line tool that helps streamline WordPress tasks like upgrading, installing and configuring.

Installing wp-cli

Note: Right now, I haven’t successfully installed wp-cli globally, so for now, you will have to install wp-cli for each user on your server. Add a comment to this post if you have successfully done a global install.

Update: wp-cli changed their installation and you can now do a global installation.

Follow the wp-cli installation guide to install globally.

 

Creating the shell script

We’ll create a script that will upgrade wordpress, the database, all plugins, and all themes. You can edit this accordingly in the script below.

Create the file

$ vim push_all_wordpress_sites.sh

Paste the following into your new file:

#!/bin/bash

paths=(
  /home/USERNAME/path/to/wordpress
  /home/USERNAME/path/to/anothor/wordpress
)

for PATH_STRING in "${paths[@]}"
do
  :

  # regex to extract username from path
  re="\/home\/([^/]+)\/"
  if [[ $PATH_STRING =~ $re ]]; then

    # change to correct directory
    cd ${PATH_STRING}

    echo "Backing up" ${PATH_STRING} "Database..."
    /usr/bin/sudo -H -u ${BASH_REMATCH[1]} zsh -c '~/.wp-cli/bin/wp db export'

    # prompt user of upgrade
    echo "Upgrading: " ${PATH_STRING}

    # do wp-cli magic
    /usr/bin/sudo -H -u ${BASH_REMATCH[1]} bash -c '/usr/local/bin/wp core update'
    /usr/bin/sudo -H -u ${BASH_REMATCH[1]} bash -c '/usr/local/bin/wp core update-db'
    /usr/bin/sudo -H -u ${BASH_REMATCH[1]} bash -c '/usr/local/bin/wp plugin update --all'
    /usr/bin/sudo -H -u ${BASH_REMATCH[1]} bash -c '/usr/local/bin/wp theme update --all'

  fi

done

Note: This script assumes that your paths are full paths including the username folder.

As you’ll see in the “paths” variable in the top, you’ll want to change those placeholders to real paths on your server where your WordPress installs are located.

Executing the script

From here you just need to change the permissions of your new file:

$ chmod 755 push_all_wordpress_sites.sh

Then, you can run it anytime you want to upgrade all of your WordPress installs:

$ ./push_all_wordpress_sites.sh
Categories
Tutorials Workflow

Making SSH logins super-quick

SSH access is pretty essential these days in web development. Especially if you have root access to a server, or using tools like Grunt, Git or Sass. But signing into them can be very time consuming.

I just recently put together a straightforward workflow (OSX and Linux) for logging into a server via SSH.

Using an SSH Config file

The SSH Config file saves your usernames, hosts and ports into a single config file.

  1. If the config file isn’t there, create it by running these commands:
    $ mkdir ~/.ssh # this directory may already exist
    $ vim ~/.ssh/config
  2. Now you can edit this file and add the following code for each server you want to connect to:
    Host ryan
        HostName ryantvenge.com
        Port 22 #The default port for SSH.
        User user_name
  3. Now, you can simply type ssh ryan to connect to the server.

Creating SSH Keys

But it is still asking for your password. So let’s get rid of that step too by creating an SSH key. SSH keys are a great tool to secure access to servers. It gives you the ability to use super-secure passwords because you don’t have to remember them. But they are kind of a pain to setup.

Run the following comands:

$ ssh-keygen -f ~/.ssh/ryan -C "ryan"
$ ssh ryan 'mkdir ~/.ssh && touch ~/.ssh/authorized_keys #these files may already exist, so you may get an error. Don't worry
$ cat ~/.ssh/ryan.pub | ssh ryan 'cat >> .ssh/authorized_keys'
  1. The first command creates the key. For simplicity’s sake, I named the key the same name as our SSH config shortcut name, “ryan”. When asked for a passphrase, simply hit return twice.
  2. The second command is creating a spot on the server to hold your ssh key.
  3. The last command copies your public key up to the server.

And Bob’s your uncle, you are all done! No more typing passwords in when pushing and pulling Git repos. No more forgetting IP addresses of servers. And best of all, you can now make your passwords sooper secure 50 character random strings, because you won’t need to type time in manually on a regular basis.

Update: If you are using git, you’ll need to update your remote path with the shortcut name, otherwise it won’t use your ssh key:

url = ssh://SHORTCUT_NAME/path/to/git/repo
Categories
Tutorials

Busting client-side js/css in WordPress

When was the last time you made a change to a site and the Project Manager or client says something to the affect of “I don’t see the change.” Then you have to tell show them how to clear their cache so the css of js change you made gets updated, not to mention that every other returning user to that site will have the same issue.

I had always meant to fix this issue, but I knew I’d have to add a random query string to each css or js file, and let’s be honest, I’m not going to do that every time.

After poking around on the WordPress Codex, there is a way to completely automate this process so you never have to think about it again.

Enqueue scripts and styles through WordPress

This is something you should be doing anyway, so WordPress knows that these files exist. The Codex have some pretty good docs on css and js enqueuing, but here’s what the syntax looks like that you put in your functions.php:

wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
wp_enqueue_style( $handle, $src, $deps, $ver, $media );

As you can see, the css and js enqueue functions are just a little different. The important parameter in here is $ver which stands for “version”.

So what WordPress wants you to do is add a string to that parameter (a date would be appropriate) and when you commit a change to that js/css file, you go in and change that string. When I brought this up to my coworker Matt Meyer, he let me know that there is a way in php to the get last modified date of a file. Perfect! Now we can completely automate this. Here is was your enqueuing code should now look like:

wp_enqueue_style( 'style', get_template_directory_uri() . '/style.css', array( 'fonts' ), filemtime( get_stylesheet_directory() . '/style.css' ) );
wp_enqueue_script( 'main_js', get_template_directory_uri() . '/js/main.min.js', array('jquery'), filemtime( get_stylesheet_directory() . '/js/main.min.js' ), true );

Notice that I’m using the get_stylesheet_uri() function when setting $handle param, but in the $ver param, I’m using get_stylesheet_directory(). The difference is that get_stylesheet_directory() function outputs a browser-friendly path (like http://ryantvenge.com/wp-content/themes/tvengedesign_30/), and get_stylesheet_directory() outputs the full server path (like /home/serveruser/public_html/wp-content/themes/tvengedesign_30/) so php can find the file and read the “last modified” date.

This was the tipping point for me to enqueue everything. I knew it was something I should be doing, but was just too lazy. Now that clients’ cache is automatically busted, I’m sold.

Edit: If you aren’t aware how enqueuing scripts work in the functions.php file, you want to put your enqueues in this function and add the action:

<?php
function my_scripts_method() {
    // use wp_enqueue_script() and wp_enqueue_style() here
}
add_action( 'wp_enqueue_scripts', 'my_scripts_method' );
?>

Thanks to Gordon for pointing this out in the comments. 🙂

Edit 2: Thanks Morgan for pointing out that like a noob, I mixed up get_stylesheet_directory() and get_stylesheet_uri(). I did fix this throughout the article.

Categories
Tutorials

Expanding underline navigation with css

I was working on a client site last week, and had mocked up a regular ol’ text navigation with a border-bottom on it. I was gonna just put a border on it and call it a day, but I wanted to do something more with a sort of animation.

I decided to make the line expand from the center, as expanding from the left seemed to give the text an unbalanced feel. For the life of me, I can’t figure out where I got the inspiration for this idea. I must have seen this affect before somewhere.

html and scss without the fanciness

The markup…

<nav class="nav-secondary">
	<ul>
		<li><a href="^_^">Home</a></li>
		<li><a href="^_^">Who We Are</a></li>
		<li><a href="^_^">Blog</a></li>
	</ul>
</nav>

with some base styling:

$red: #ef4035;
$grey: #b0a7a7;
.nav-secondary {
	ul {
		width: 100%;
	}
	li {
		text-align: center;
		display: inline-block;
		float: left;
		padding: 0 6%;
		white-space: nowrap;
	}
	a {
		color: darken($grey, 10%);
		text-decoration: none;
		padding-bottom: 6px;
		display: block;
	}
}

Why use psuedo elements?

Obviously, we can’t just put a border on the bottom of the anchor and anmiate width, because our anchor text wouldn’t be visible until hover. I decided to use a pseudo element for the “border” so we can have a width: 0; before hover. I also split the line into two elements, :before and :after, which breaks the “border” into two segments that we can animate separately.

$red: #ef4035;
$grey: #b0a7a7;
.nav-secondary {
	ul {
		width: 100%;
	}
	li {
		text-align: center;
		display: inline-block;
		float: left;
		padding: 0 6%;
		white-space: nowrap;
	}
	a {
		color: darken($grey, 10%);
		text-decoration: none;
		padding-bottom: 6px;
		display: block;
		&:after {
			clear: both;
			display: block;
			content: "";
			position: relative;
			left: 50%;
			height: 3px;
			background: $red;
			border-radius: 6px;
		}
	}
}

From there, we set the initial width: 0, the :hover and :focus to width: 50% (because there are 2 “borders”), and add a transition to animate the width.

$red: #ef4035;
$grey: #b0a7a7;
.nav-secondary {
	ul {
		width: 100%;
	}
	li {
		text-align: center;
		display: inline-block;
		float: left;
		padding: 0 6%;
		white-space: nowrap;
	}
	a {
		color: darken($grey, 10%);
		text-decoration: none;
		padding-bottom: 6px;
		display: block;
		&:after {
			clear: both;
			display: block;
			content: "";
			position: relative;
			width: 0;
			left: 50%;
			height: 3px;
			background: $red;
			@include transition(width .2s, left .2s);
			border-radius: 6px;
		}
		&:hover, &:focus {
			&:after {
				width: 100%;
				left: 0;
			}
		}
	}
}

Final working nav

Check out this Pen!

Browser support

It turns out that animating generated content is not supported in all browsers. Chris Coyier has a post about it, but the long and short of it is that it’s not supported in IE9 (is supported in 10), not supported in current Opera or current Safari. This didn’t bug me too much because it degrades really well, and support isn’t that far off.

A note about performance

After I had put this on CodePen, vsync found a more straightforward approach to the solution by using text-align: center and only one pseudo element. I just happen to be looking at it on my 2008 MacBook Pro, and the framerate was a little jerky. I took a look in Chrome Dev Tools, and it was for sure reprinting quite a bit. I’m not trying to dis on vsync‘s code. It was just dumb luck that I came up with a more efficient solution. But I just wanted to note it.