Categories
Wordpress

Changing the backorder message in Woocommerce

A client walks into a bar and asks me “can I change the backorder message in woocommerce?”

I reply: “Of course! 😀”

Setup

The code in this tutorial pre-setup with wordpress & woocommerce installed. I am using a an empty child theme of storefront.

Download this repository: for a quick start bare-bones storefront child theme with minimal configuration.

prettier & prettier-php

I use prettier & prettier-php to automatically make my code prettier and its installed in the theme linked above. (Remember to run: npm install)

Adding the filter

In wordpress, a “adding a filter” is essentially adding function to an array of functions which will be performed at a specific spot of the code.

Add_filter()

Learn more about add_filter() at the official wordpress documentation.

Parameters

add_filter() takes four parameters, a name, a function to perform, a priority and its expected number of parameters.

  1. Name – The name of the action where the functions will execute
  2. Function – The name of the function we are adding to the pipeline
  3. Priority – The order in which the functions run (ASC)
  4. Number of parameters – How many parameters your function is expecting
<?php

add_filter(
  "woocommerce_get_availability_text",
  "gregbastianelli_change_backorder_message",
  10,
  2
);

So above: we are calling the ‘woocommerce_get_availability_text' action, we are adding our ‘gregbastianelli_change_backorder_message‘ function to the pipeline, setting a priority of 10 and expecting 2 parameters.

Change backorder message globally

If we visit the source code for woocommerce_get_availability_text you can see it returns two parameters in the apply_filters function.

Expected Parameters

  • $availability is the text message returned when a product shows its on backorder.
  • $this is the product in question.

Now that we know which data is being passed to us – we can setup our function.

Step-by-step

Setup up the function – write documentation and do stuff.

function gregbastianelli_change_backorder_message($text, $product)
{
  /**
   * Allows developer to change backorder message site-wide
   * @param string $text
   * @param WC_Product $product
   */

   // do stuff

}

First we want to set a backorder message.

  $backorder_message = "Will ship in January 2021";

Next we want to set a condition so our backorder message only shows on products on backorder.

...
 
 if ($product->managing_stock() && 
      $product->is_on_backorder(1)) {
    return $backorder_message;
  }

  return $text;
}

We also include a return under our condition so the work done by the previous functions in the pipeline is passed on if our condition is not met.

The end results (tl;dr)

In a hurry? Here are the end results.

How to change backorder message store wide

<?php

add_filter(
  "woocommerce_get_availability_text",
  "gregbastianelli_change_backorder_message",
  10,
  2
);

function gregbastianelli_change_backorder_message($text, $product)
{
  /**
   * Allows developer to change backorder message site-wide
   * @param string $text
   * @param WC_Product $product
   */

  $backorder_message = "Will ship in January 2021";

  if ($product->managing_stock() && 
      $product->is_on_backorder(1)) {
    return $backorder_message;
  }

  return $text;
}

How to change the backorder message for a specific product

If you want to have different messages for different products, include a check for a specific id as well.

...

  $backorder_message = "Will ship in January 2021";
  $target_id = 272; // include ID

  if (
    $target_id === $product->get_id() && // check for ID
    $product->managing_stock() &&
    $product->is_on_backorder(1)
  ) {
    return $backorder_message;
  }

  return $text;
}

You did it!

Look at you. Changing your very own backorder message in woocommerce like a DEV PRO!

Categories
Gatsby Wordpress

Using a Highlight.js with GatsbyJS & WordPress

GatsbyJS is awesome because it allows developers to quickly design, develop and deploy projects. Gatsby sites are automatically optimized for speed and allows us to focus on building something great.

Why use a Code Syntax Highlighter?

If your personal website is littered with pre and code tags – you might want to consider using a code syntax highlighter.

Syntax highlighters are abundant, easy to use, improve readability and really up your dev game.

With syntax highlighting

Without syntax highlighting

I think the images speak for themselves.

Highlight.js

Highlight.js homepage has a interactive demo for syntax highlighting

As mentioned above – there are plenty of options out there when it comes to code syntax highlighters.

We are going to choose highlight.js because it is well-known, easy to use and comes with lots of theme styles.

Setup

First, download highlight,js from npm.

$ npm i highlight.js

Next create a helper file at /src/utils/helper.js.

$ touch src/utils/helper.js

Import the library

// /src/utils/helper.js

import hljs from "highlight.js"

Pick a code theme

Highlight.js has lots of themes available – you can find them all by visiting the official repository, the homepage or running ls in the module’s styles folder.

I chose ‘atom-one-dark’.

// /src/utils/helper.js

import hljs from "highlight.js"
import "highlight.js/styles/atom-one-dark.css"

Configuration

Unless you have some built in meta data or class names which signify the language in your code blocks – you will probably want to use the auto-detect feature.

Trouble is, highlight.js has over 180 languages and detection can be tricky.

I overcame this by narrowing the search to just the languages I know I use in these blocks

// /src/utils/helper.js

...

hljs.configure({
  languages: ["php", "javascript", "json", "bash", "scss"],
})

You can see all the possible options by running hljs.listLanguages() in the console.

Building our code highlighter

Finally we are going to create our highlightCode() function which simple finds all code tags nested within a pre tag and “highlight it”.

// /src/utils/helper.js

...

const highlightCode = () => {
  const codes = document.querySelectorAll("pre > code")
  for (let key in codes) {
    if (typeof codes[key] === "object") {
      hljs.highlightBlock(codes[key])
    }
  }
}

Essentially we are looping through the elements, double checking it is an object then replacing the node with a new element created by the highlighter.

Wrapping up

Finally export the helper – the final result should be:

// /src/utils/helper.js

import hljs from "highlight.js"
import "highlight.js/styles/atom-one-dark.css"

hljs.configure({
  languages: ["php", "javascript", "json", "bash", "scss"],
})

const highlightCode = () => {
  const codes = document.querySelectorAll("pre > code")
  for (let key in codes) {
    if (typeof codes[key] === "object") {
      hljs.highlightBlock(codes[key])
    }
  }
}

export default { highlightCode }

Using our helper function

The new helper we wrote is great but how do we use it? See this was the tricky bit for me.

GatsbyJS + WordPress work together by querying your WordPress database for the appropriate data.

A post’s content is passed as a large string of HTML and the only way to use that HTML in react is to use dangerouslySetInnerHTML.

dangerouslySetInnerHTML

dangerouslySetInnerHTML is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack.

https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

As per the offical react documentation this property name is purposefully scary to remind you its dangerous to set the innerHTML unless your careful.

Luckily our content was written in the WordPress CMS and has already been sanitized for our viewing pleasure.

Highlighting the code blocks

Finally we are going to use the helper we created.

I’m going to assume you have a running Gatsby site with a template setup to display your single posts. If not – the GatsbyJS + WordPress documentation is wonderful and got me started quickly.

Your post will look something like this – where we are creating a content div and passing our posts content via the dangerouslySetInnerHTML property.

// /src/templates/blog-post.js

Import React, { useEffect } from 'react'

export default function BlogPost({ data }) {
  const post = data.allWpPost.nodes[0]

return (
    <Layout>
      <div id="single">
        <h1 className="title section-header">{post.title}</h1>
        <div
          id="content"
          dangerouslySetInnerHTML={{
            __html: post.content,
          }}
        />
      </div>
    </Layout>
  )
}

Most important to understand is we are passing the HTML of our post directly to div#content.

UseEffect

UseEffect is a react lifecycle method – essentially a spot/time in the code where we can run our own functions. Because we are forced to use dangerouslySetInnerHTML – we cannot access or modify the post’s content before hand.

We can however use UseEffect to run our code highlighter after the component is loaded into the DOM and the content created.

Add import your helper and run the highlightCode function in the useEffect block.

// /src/templates/blog-post.js

Import React, { useEffect } from 'react'

...

 useEffect(() => {
    helper.highlightCode()
  })

  return (
...

Your code blocks should now look like a text editor – improving the readability and aesthetic of your blog posts.

Categories
Gatsby Wordpress

Gatsby + WordPress Menu API

GatsbyJS and WordPress work beautifully together – you get to keep using the familiar WordPress backend while running react in the front.

Getting Gatsby to work with the WordPress menu API was fun so I thought I’d share how I did it.

Prerequisites

This post is geared toward developers with intermediate React and WordPress experience.

Follow this Gatsby + WordPress tutorial to quickly get started if you don’t already have a Gatsby application running.

Overview

Our objective is to get our Gatsby site to play nice with the WordPress menu API.

To achieve this, we must:

  • Build our query in the graphQL IDE
  • Build our Menu react component
  • Implement logic for dealing with nested navigation items

At the end of this – we will have a navigation menu that works seamlessly with the WordPress backend.

Setup

Gatsby uses graphQL for querying data from an API, so download and install the WPGraphQL & WPGatsby plugins on your existing wordpress site.

Next add the following to your gatsby-config.js file located at the root of your gatsby site.

/gatsby-config.js


{
  plugins: [
    {
      resolve: `gatsby-source-wordpress-experimental`,
      options: {
        url: `http://gerrg.com/graphql`,
      },
    },
  ],
}

Finally run gatsby develop and “experience the magic”.

Any issues – checkout the quick start instructions here.

gatsby develop

After running gatsby develop we can visit our site at http://localhost:8000 and visit our graphQL IDE at http://localhost:8000/___graphql.

The graphQL IDE

My favorite thing about graphQL (besides the simple syntax) is the IDE – this allows your to quickly build queries, explore the schema and experiment.

Using the graphQL IDE to quickly form a query for all posts from my wordpress site.

Getting WPMenu Items

The WPGraphql plugin we installed on our existing wordpress site allows our to query the WP_Menu API – this is what allows our gatsby site to work with Menus created in the WordPress admin section at: Appearance > Menus.

The WordPress admin section for building menus.

Copy the following query into your IDE to ensure you can get your menu items properly:

query MyQuery {
  wpMenu {
    id
    menuItems {
      nodes {
        parentId
        label
        path
        childItems {
          nodes {
            path
            label
          }
        }
      }
    }
  }
}

Running the query should return an object with a list of menu items – including parentID, path, label and children (if any).

The results of your menu item query should look similar to this image

Assuming you’ve got the proper data returned, now we are set to build a Menu component and feed it our queried data.

Creating our Menu in React

Now that we have a query, we are going to want to bring that data into our Gatsby application.

First, create a basic Header component at src/components/header.js.

// src/components/header.js

import React from "react"

const Header = () => {
  // query data here

  return (
    <header className="header">
        <h1>Gatsby + WordPress Menu's<h1>
    </header>
  )
}

export default Header

Since header is not a “template” we must use useStaticQuery to contact the WordPress Menu API. Since we already created the query in the IDE – this will be easy.

First import graphql and useStaticQuery from gatsby

import React from "react"
import { graphql, useStaticQuery } from "gatsby"

const Header = () => {
...

Next setup the query function at the first line in the Header component.

...
const Header = ({ siteTitle }) => {
  const data = useStaticQuery(
    graphql`
      {
       // our query will go here
      }
      
    `
  )
...

Finally copy the query we built in the IDE at http://localhost:8000/___graphql into the query statement – the final result should look like this:

...
const Header = ({ siteTitle }) => {
  const data = useStaticQuery(
    graphql`
      {
        wpMenu {
          id
          menuItems {
            nodes {
              parentId
              label
              path
              childItems {
                nodes {
                  path
                  label
                }
              }
            }
          }
        }
      }
    `
  )

return (
...

Re-run gatsby develop and console.log(data) to test the query.

Houston, we have a problem.

You might have noticed that there is an issue with our query. Currently we are getting all the menu items in the menu – regardless if they are nested or not.

To fix the issue – we will want to filter out the children by checking if a menu item has a parentID.

Currently our query is returning duplicate menu items – “WordPress” is child of Tutorials as well as its own menu item below.

Filter out the children

We dont want nested menu items passed to the Menu component becuase it will result in duplicates and not reflect how the menu was build in the admin section (the entire point of this post).

Luckily modern Javascript makes it quite easy to filter an array with filter.

Add this line after the query:

...

  // filter only parents
  const menu = data.wpMenu.menuItems.nodes
    ? data.wpMenu.menuItems.nodes.filter(menuItem => menuItem.parentId === null)
    : null

   return(
...

Now we are checking to see if there are any menu items, if yes filter out the top-level menu items – ELSE – return null.

Console.log(menu) and you should only see the top-level menu items.

Console.log(menu) returns a filtered array of top-level menu items.

Finally – we can pass our data to a menu component which will take care of all the list-item logic.

Quickly create a Menu component at src/components/menu.js

// src/components/menu.js

import React from "react"

const Menu = ({menu}) => <p>im gonna be a menu one day</p>

export default Menu

Import your menu and pass it your filtered array of menu items.

import { graphql, useStaticQuery } from "gatsby"
import React from "react"
import Menu from "./menu"

const Header = ({ siteTitle }) => {
...

return (
    <header className="header">
        <h1>Gatsby + WordPress Menu's<h1>
        <Menu menu={menu} />
    </header>
  )

}

Finally we are ready to create a Menu component which will handle all the logic of displaying menu items.

Building the Menu component

The menu component will be responsible for listing our menu items – it will loop each menu item and check if it has any children.

If there are no children menu items – we will display the current menu item as a standard link.

If there ARE children – we will display it as a dropdown menu item which will show the children on hover.

Setup the menu – loop the items

First we will setup the menu, loop through each item in the menu and check if it has any children.

// src/components/menu.js

import React from "react"

const Menu = ({menu}) => (
  <ul className="menu">
  // this is where we will do the loop
  </ul>
)

export default Menu

Next we will loop through each item in the menu and check if it has children

...
const Menu = ({menu}) => (
  <ul className="menu">
    {menu.map(menuItem => {
      const children = menuItem.childItems.nodes.length
        ? menuItem.childItems.nodes
        : null

      return children ? (
        <DropdownMenuItem parent={menuItem} children={children} />
      ) : (
        <MenuItem menuItem={menuItem} />
      )
    })}
  </ul>
)
...

Above we are looping the menu and checking if it has children – if the item has children we display a dropdown menu ELSE display a normal menu.

MenuItem

First we will define the menu item because its simple – add the following below the Menu component.

...
const MenuItem = ({ menuItem }) => (
  <li className="menu-item">
    <a href={menuItem.path}>{menuItem.label}</a>
  </li>
)

The menu item is passed a menuItem in its props – it simple returns a list item with a link and label.

DropdownMenuItem

The DropdownMenuItem is a bit more interesting – it uses a bit of state logic to decide whether or not to show its children.

const DropdownMenuItem = ({ parent, children }) => {
  const [show, setShow] = useState(false)

  return (
    <li
      className={`dropdown menu-item`}
      onMouseEnter={() => setShow(true)}
      onMouseLeave={() => setShow(false)}
    >
      {parent.label}
      <div style={{ display: show ? "block" : "none" }}>
        <div className="flex-square">
          {children.map(child => (
            <Link to={child.path}>{child.label}</Link>
          ))}
        </div>
      </div>
    </li>
  )
}

Lets try to understand this component bit-by-bit.

const DropdownMenuItem = ({ parent, children }) => {

The DropdownMenuItem is passed the current menu item as well as its children via props.

const [show, setShow] = useState(false)

The component also uses useState – which simply returns a variable set to false and a function for setting that variable.

return (
    <li
      className={`dropdown menu-item`}
      onMouseEnter={() => setShow(true)}
      onMouseLeave={() => setShow(false)}
    >

Next we create a <li> element, give it the ‘dropdown’ and ‘menu-item’ classes and setup some events.

Essentially when we hover the <li> show is set to true – when we are not hovering show is set to false.

...            
      {parent.label}
      <div style={{ display: show ? "block" : "none" }}>
        {children.map(child => (
          <Link to={child.path}>{child.label}</Link>
        ))}
      </div>
    </li>
  )
}

export default Menu

At {parent.label} we are adding the text of the parent menu item.

<div style={{ display: show ? "block" : "none" }}>

Then we conditionally edit the wrapper’s display property to ‘block’ if show is true ELSE none

...         
        {children.map(child => (
          <Link to={child.path}>{child.label}</Link>
        ))}
...

Finally loop the children nodes and create a link to each of them.

You did it!

Good job – we setup our Gatsby site to query our existing WordPress site for the menu.

Hopefully this gives you an idea how you can deploy new Gatsby applications while keeping the robust and familiar WordPress admin section.

Categories
Wordpress

Using wc_get_template from a plugin

wc_get_template is great for breaking up a complex plugin into simpler parts.

By default wc_get_template is designed to search in /wp-content/plugins/woocommerce or /wp-content/themes/yourtheme/woocommerce for a template – not in your plugin folder.

Editing wc_get_template with a filter

Luckily we can use a filter to edit the behavior of wc_get_template to search in our plugin if its searching for a specific file path (e.g ‘templates/yourtemplate.php).

** A filter is essentially an array of functions the application will run through before returning a result.

First, add our own function to the filter.

// modify wc_get_template to search in plugin directory
add_filter('wc_get_template', 'gerrg_get_template', 10, 2);

Next we define the function which will modify the behavior of wc_get_template to search in our plugin folder. The function takes 5 parameters but we only need the first two:

  • $located – the results of searching in the woocommerce folder (default behavior)
  • $template_name – this is what we will use to set a condition in our gerrg_get_template function,

Lets write some code

The goal of this function will be to get wc_get_template to search in our plugin directory instead of in the default woocommerce folder path.

function gerrg_get_template($located, $template_name)
{
    // if we are searching for a specific file
    if ('path/to/my/template.php' === $template_name)
    {
      // return the path to that file
      return plugin_dir_path(__FILE__) . $template_name;
    }

    // otherwise work as normal
    return $located;
  }

The function is not too complicated – essentially we added a simple conditon to the wc_get_template function.

If wc_get_template is passed a SPECIFIC path (e.g. ‘path/to/my/template.php’) the function will return your plugin’s directory path to the file.

If the condition is not met, revert back to normal function (look in WC folder and theme’s WC folder).

Wrapping up

The filter modifies the functionality of wc_get_template under very specific circumstances.

...
if ('path/to/my/template.php' === $template_name){
    return plugin_dir_path(__FILE__) . $template_name;
}
...

Categories
Wordpress

How to add Bootstrap columns to WooCommerce Shop Page

If you prefer the Bootstrap Grid System over the default woocommerce column setup then it requires a few lines of code to get going.

This is one of many ways to accomplish our goals.

  • Create our grid-based container
  • Add our column classes to the products in the container
  • Close the container

Open our bootstrap container

First open up a new div with .row to house our products by hooking into woocommerce_product_loop_start.

function gerrg_woocommerce_product_loop_start(){
    /**
     * opens up any category and shop pages as a boostrap row.
     */
    return '<div id="gerrg-archive" class="row">';
}
add_filter('woocommerce_product_loop_start', 'gerrg_woocommerce_product_loop_start', 999);

Add bootstrap .col-* to products

Now we need to add bootstrap colomn classes to woocommerce products by hooking into the woocommerce_post_class filter.

  • .col-6 – 1/2 the row on mobile
  • .col-sm-3 = 1/4 the row on small displays
  • .col-xl-2 = 1/6 the row on large displays
function gerrg_add_bootstrap_cols_to_product( $class ){
    /**
     * adds bootstrap grid classes to all category and shop pages.
     */
    $class[] = 'col-6 col-sm-3 col-xl-2';
    return $class;
}

add_filter('woocommerce_post_class', 'gerrg_add_bootstrap_cols_to_product', 30, 3);

Wrapping things up

Finally we close up our shop row and have a functional bootstrap grid system on all woocommerce shop, category & taxonomy pages.

Just like be began, we adding some html to close our div by hooking into the woocommerce_product_loop_end filter.

function msp_woocommerce_product_loop_end(){
    /**
     * closes up any category and shop pages
     */
    return '</div>';
}
add_filter('woocommerce_product_loop_end', 'msp_woocommerce_product_loop_end', 999);

You did it!

Good job, if you have any questions or concerns or have a better way to succeed than above

Categories
Wordpress

How to add Free Gifts on Woocommerce Programmatically

A client wanted a free pack of blades to be automatically added to when a customer added 20 knives to their cart.

This seemed like good information to share for aspiring “woocommerce store owners / developers”.

If you have any questions, please feel free to reach out.

Planning

So here is what we have to do to get this to work.

  1. Write down the ID’s of the items you wish to target and the reward.
  2. Create a check for the condition (20 of the target in the cart)
  3. Add the reward if not already in the cart
  4. Make the reward free and check bugs.

Find the product ID’s

So first we need to learn which item’s we want to target. An easy way to find the ID is to login to the backend and go to the products tab.

Simple Products

Hover a product in the products tab to display the ID. Use that to target.

For simple products we need only to over the product to see it’s ID.

Variations

Variations as you know are individual products that make up a variable product.

To find the ID of a variation, edit a variable product, go to the variations tab and they will be listed on the left hand side.

Edit a variable product and go to the variations tab to find variation ID’s

So for our example, we are going to keep it simple and just use Pants, Shirts & a Hat.

  • Pants – ID: 553, Type: Variable
  • Hat – ID: 562, Type: Simple

I suggest you write your target & reward ID’s before proceeding, it will make customizing your code to work with your setup much easier, IMO.

Target the product ID’s

Now we will jump into the code.

First add this helper function we will use later to check if a product is in the cart.

function gerrg_get_product_cart_key( $product_id ){
	$product = wc_get_product( $product_id );

	if( ! $product ) return;

	return ( $product->is_type( 'variation' ) ) ? WC()->cart->generate_cart_id( $product->get_parent_id(), $product->get_id() ) : 
												  WC()->cart->generate_cart_id( $product->get_id() );
}

We are hooking into wp because we want this to run on every page load.

add_action( 'wp', 'gerrg_programically_add_to_cart' );

Open up your function and include a check to prevent this from running on the admin side (it causes an error).

function gerrg_programically_add_to_cart(){
	/**
	 * Looks for hard coded ID's in $targets array, check if ID meets product quantity and adds reward if so
	 */
	if( is_admin() ) return;

Next create a targets array, include the ID of all items you wish to target.

For variable products you must use the variation ID’s. I am targeting all sizes of a specific shirt.

These are the variations I am targetting. All sizes of a shirt.
// setup needles
$targets = array( 558, 559, 560, 561 );

Next set the reward, for me I am targeting a hat.

// free gift ID
$reward = 562;

This next bit is just a fancy woocommerce method of checking if something is in the cart.

We will use the helper method you added earlier to generate a cart key to pass to woocommerce to check for the item we are rewarding (otherwise they’d get so many!).

// key for quick searching in cart
$reward_item_key = WC()->cart->find_product_in_cart( gerrg_get_product_cart_key( $reward ) );

Now we will loop through the cart and look at EACH item in the cart.

foreach( WC()->cart->get_cart() as $cart_item ){

We make sure to use the ID given, sometimes working between different product types can cause problems.

// get real ID
$id = ( $cart_item['variation_id'] === 0 ) ? $cart_item['product_id'] : $cart_item['variation_id'];

Now we will loop through each ID in our $targets array.

// loop needles
foreach( $targets as $target ){

Now we are going to add the condition. In this specific circumstance, I need 3 things to be true.

  • The target ID is in the cart
  • That item has a quantity of 3 or more.
  • and finally, the reward is not ALREADY in the cart.
// if needle in haystack, quantity over 20 && reward not in cart
if( $target === $id && $cart_item['quantity'] >= 20 && ! $reward_item_key ){

Add the reward to the cart.

// Add reward
WC()->cart->add_to_cart( $reward );

Close everything up.

Discount the free gift

Now we are going to need to make that free gift free.

We have to hook into woocommerce_cart_calculate_fees to discount the free gift.

// this is where fees are calculated
		add_action('woocommerce_cart_calculate_fees', 'gerrg_discount_free_gift' ) );

Then add the following function

function discount_free_gift( $cart ){
		/**
		 * Look for free gift in cart, discount item if in cart.
		 * @param WC_Cart
		 */
	
		$product = wc_get_product( $this->reward );
	
		if( ! $product ) return;
		
		$reward_item_key = WC()->cart->find_product_in_cart( $this->get_product_cart_key( $this->reward ) );
	
		foreach( WC()->cart->get_cart() as $cart_item ){

			$id = ( $cart_item['variation_id'] === 0 ) ? $cart_item['product_id'] : $cart_item['variation_id'];

			foreach( $this->targets as $target ){

				if( $target === $id && $cart_item['quantity'] >= 20 && $reward_item_key ){

					// Meets all condititions? Add discount (fee).
					$cart->add_fee( 'Free Gift', ( $product->get_price() * -1), true  );
				}
			}
		}
	}

Very similar to the last function we loop the cart and check if the targets are in the cart, the quantity is met AND the reward is in the cart as well.

TL;DR

If you want to skip to the chase, download the plugin.

Categories
Linux

How to setup SSH Keys (TL DR;)

SSH Keys are wonderful and easy to set up. You can SSH keys to quickly log into a remote server (like your website) from the command line WITHOUT a password prompt.

How does it work?

Essentially SSH works by generating two keys (strings) on your machine: a public and a private one. You place the public key on a external server and when you log in the server makes the connection and access is granted.

How do I do it?

Setting up SSH can be done in as little as two steps:

  1. Generate SSH key Pair
  2. Copy public key to remote server (where you want to login)

Generate SSH Key Pair

First generate the SSH key pair with ssh-keygen.

ssh-keygen -t rsa

You will be asked where you want to store the file and whether or not you want a password, I just click ENTER twice.

Copy the public SSH key

Use ssh-copy-id to quickly move the public SSH key to the remote server.

ssh-copy-id user@example.com

You must know the username of server you are trying to access.

Categories
Wordpress

How to Setup WP-CLI on WordPress Server

Setting up WP-CLI is super easy and can be done in just a few steps.

Installation

First download WP-CLI using curl or wget.

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar

Next check if it worked.

php wp-cli.phar --info 

To make things easier, make the wp-cli.phar file an executable.

chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp

sudo: command not found

If you don’t have sudo powers there are a number of things you can do:

Easy Way

You can use the relative path to the wp-cli.phar file.

~/wp-cli.phar

Best Way

A better solution would be to create an alias to run the same command as above with less keystrokes.

Open up your .bashrc file and add this line to the bottom

# User specific aliases and functions
alias wp="~/wp-cli.phar"

Re-source your .bash_profile and run wp --info.

source .bash_profile
wp --info

You did it!

Categories
Ruby on Rails

How to add Bootstrap 4 to your Ruby on Rails Application

Luckily adding Twitter Bootstrap 4 to your ruby on rails application is not too complex.

Here’s the quick and dirty steps to adding bootstrap to your rails application.

Launch your app

Move into your existing application directory or run rails new myapp to create a new application.

Add the bootstrap and jquery gems to your Gemfile.

gem 'bootstrap', '~> 4.4.1'
gem 'jquery-rails'

Run bundle install --verbose (it may take a while).

Restart your server if you have it running. This is an important step for ensuring bootstrap is available in the applications pipeline.

Import styles in application.scss

Rename the default app/assets/stylesheets/application.css to a .scss file.

mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss

Remove all the *= and *= require_tree statements to have access to Bootstrap mixins and variables.

Importing bootstrap at app/assests/stylesheets/application.scss

Add jQuery

Bootstrap 4 relies on jQuery for all the JavaScript heavy lifting.

Earlier we added the ‘jquery-rails gem’ and ran bundle install.

Now all we have to do is add bootstrap dependencies to our app/assests/javascripts/application.js

//= require jquery3
//= require popper
//= require bootstrap
Add bootstrap dependencies to your application.js file.

Check the source code

To test that bootstrap was added to our applications assets pipeline, launch the server and check the source code.

Checking the applications source code for links to bootstrap.

You did it!

What did we do?

  • Added the Bootstrap and Jquery gems to our Gemfile and ran bundle install --verbose.
  • Renamed our application.css to a .scss file and added @import "bootstrap";
  • Added jQuery dependancies to application.js
  • Confirmed what we did by launching the app and checking the source code.
Categories
Ruby on Rails

How to setup Rails App for Heroku

If you want to host your Ruby on Rails application with Heroku- your database must be PostgreSQL.

Unfortantely, it can be difficult to get setup if you’ve never done anything like use the Heroku CLI or manually create databases in psql.

Here are the quick and dirty steps for setting up your rails application for hostign on heroku.

Install Heroku

If you haven’t installed heroku-cli, that is step number one.

Visit the download instructions to figure out how to install heroku.

For me (xubuntu) I used snap.

sudo snap install --classic heroku

Next, you’ll be prompted to setup/login with Heroku.

Create the application

If you are starting from scratch, run the rails new command and specify you want a postgreSQL database (since thats what heroku requires).

rails new myapp –database=postgresql

Move into your new application and run bundle install.

cd myapp
bundle install
...
Bundle complete! 18 Gemfile dependencies, 78 gems now installed.

Test the databases

For my setup, I have to manually create the databases in PostgreSQL.

Run the following commands, using your application’s name instead of myapp.

psql
CREATE DATABASE myapp_development;
CREATE DATABASE myapp_test;
\list;

If psql didn’t work or needs to be setup, I wrote a short post about getting setup with PostgreSQL.

Go back into your application and run rails db:migrate to test your databases were added correctly.

No error message? Good!

Create a welcome page

Rails 5.x no longer includes a default page in a production environment.

So we will have to make one! First create a controller.

rails g controller pages home

Now create a home.html.erb file in the app/views/pages/ directory.

Add some simple HTML to the homepage.

<h1>Rails!</h1>
<a href="http://gerrg.com">GERRG.com Learn to build a Rails Application and Host with Heroku</a>

Finally add the route to the newly create homepage. Open up config/routes.rb and add the following line.

root 'pages#home'

Open up your terminal and launch your server with rails server.

Add it to Github

Now that you’ve got your self a fancy new rails application complete with default page in production environments…

Its time to add it to GitHub before we host the application on Heroku.

Setup repository on GitHub: add, commit and push application.

git add -A
git commit -n 'init commit'
git push

Your push will not work if you haven’t setup your remote origin. In fact, you’ll get an error message about it.

Host on Heroku

Okay so far we have:

  • created our rails application
  • setup our postgreSQL databases
  • built a default page for our production environment
  • and created a repository on github.

Finally, we are going to host our rails application with Heroku and have our site out there on the world wide web.

Run Heroku create to create a repository with Heroku, then push your application from git to Heroku.

heroku create
git push heroku master
This push will take a while and you will see lots of scary messages… just let it finish.

If the command completes, the push was complete and you should be able to visit your application with heroku open.

you did it!