Now that I develop a lot of projects in Ruby on Rails, they require specialist hosting. The standard shared hosting accounts that host so many websites including those powered by WordPress just don’t provide enough server resources to run a modern and complex web application.
But what if I want to also run a WordPress powered blog as a section of the same domain? This sounds complicated.
It is actually possible to run different subdomains (something.example.com) on different servers.
How?
Create a new A record in the DNS for the domain in question. You can usually do this through your registrar.
You’ll need 2 things in order to do this:
Creating an A record is then fairly straight forward.
Where it says HOST, type the name of the subdomain. So for example if you’re trying to create blog.example.com, the host would just be “blog”.
Where it says points to, or IP, type the IP address of the server where you’re going to host the subdomain.
Now, you can head over to your hosting account and Add Domain or Addon Domain as is standard practise in CPanel.
For domain to add, type the full name: blog.example.com.
If your domain registrar is GoDaddy, everything should work within about 30 seconds. But for other registrars it can take up to 24 hours.
It’s common in UX design to have web page elements react in some way to user interaction. For example, have a link change colour when the user mouses over it.
This can be achieved using Javascript in the DOM, but equally, it can be done with CSS.
So assume this is the following link code. An a tag inside a nav div.
<div id="nav">
<a href="">link</a>
</div><!-- // nav -->
To style this normally, the CSS would be as follows:
#nav a {color: black;}
And to style the link, when a user hovers over it, we would do:
#nav a:hover {color: blue}
If you’re viewing this website on your mobile device, you may have already used the slide-out menu to navigate around the site. If you haven’t, you can click the yellow square on the top right of the screen to have a look at it without leaving this page.
A slide-out menu is a space-efficient way of creating a navigation menu on a smaller screen device where screen space is at a premium.
In this post I’m going to explain how to implement this type of menu on your website or web-app.
In essence, this menu is a div that is not displayed by default, and is given a width value only when the javascript function to do so is called on it.
So, the “slide-out” is actually an illusion. When the page is loaded, by default, the menu div has a width of 0px, and so does not display on the page.
Then, we call a Javascript function on it which gives it a width value of whatever we want, say 250px.
There are three parts to this implementation.
<div id="mySidenav" class="sidenav">
<a href="javascript:void(0)" class="closebtn" onclick="closeNav()">×</a>
<a href="https://www.adampatel.co.uk/" rel="nofollow">Home</a>
<a href="https://www.adampatel.co.uk/about/">About</a>
<a href="https://www.adampatel.co.uk/portfolio/">Portfolio</a>
<a href="https://www.adampatel.co.uk/cv/">CV</a>
<a href="https://www.adampatel.co.uk/blog/tutorials/">Coding Tutorials</a>
<a href="https://www.adampatel.co.uk/blog/">Blog</a>
</div><!-- // sidenav -->
We have a div called mySidenav which contains a few standard hyperlinks, followed by the closing of the div.
Lines 2 and 3 are also an a tag but they trigger the javascript function that closes the menu.
The CSS we put in the stylesheet will be the values of various CSS properties by default, ie. when the page first loads.
/* The side navigation menu */
.sidenav {
height: 100%; /* 100% Full-height */
width: 0; /* 0 width - change this with JavaScript */
position: fixed; /* Stay in place */
z-index: 1; /* Stay on top */
top: 0; /* Stay at the top */
left: 0;
background-color: #111; /* Black*/
overflow-x: hidden; /* Disable horizontal scroll */
padding-top: 60px; /* Place content 60px from the top */
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
}
/* The navigation menu links */
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
/* When you mouse over the navigation links, change their color */
.sidenav a:hover {
color: #f1f1f1;
}
/* Position and style the close button (top right corner) */
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
You’ll notice on line 4, the default width of the div is 0%, so it doesn’t display by default.
Place this code in the head of your HTML.
<script>
/* Set the width of the side navigation to 250px */
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
}
/* Set the width of the side navigation to 0 */
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
</script>
There are two Javascript functions in this code.
openNav() which selects the mySidenav div and applies a width of 250px to it, thus making the menu slide out when this function is called.
closeNav() does the opposite. It reapplies a width of 0 when the function is called.
But how do we call the function? Well you’ve already seen in the HTML in part 1 that we called one of those functions within the menu. Calling the other is much the same, except we call it from an element that is visible on the page by default, in the case of my website, the menu button.
<div id="call_menu"><span align="center" onclick="openNav()">MENU</span></div>
It’s the onclick=”openNav()” bit that calls the Javascript function and activates the slide-out menu.
And that’s it!
You can of course apply your own colour schemes and fonts by making changes to the CSS.
this is a test ruby project to see if and how it appears in the portfolio category.
example
Yesterday evening, I left my laptop unattended with a stylesheet I’d been playing with open on the screen. This stylesheet is several months old and contains more than 500 lines of code. When I got back to the desk, I must have just saved, closed and moved on with my evening. The problem? Did I mention I have cats?
This morning, when I loaded the page, I realised it was slightly uglier than I remembered. Furthermore, there seemed to be changes in lots of places that just looked less refined than they had before. It irritated me. And my only conclusion is that one of the cats walked over the keyboard. I have seen this happen many times so I know it’s possible.
I have checked over the code by eye and cannot find any of the usual hallmarks of cat footprints in the code. Things like
//////////////////////////////////////////////////........,l,,,,,kkkkkkkk
So what now?
Fixing something like this is difficult by sight. Especially when we consider that some of the divs in play, themselves contain multiple other divs.
This is when I thought about a CSS testing framework. My time at Makers recently has taught me about things like Rspec and Jasmine for Ruby and Javascript. Maybe there’s one for CSS?
A google search uncovered BackstopJS, which I think does exactly this – makes sure CSS requirements remain satisfied when your pesky cat walks across the keyboard and can tell you where in the file the problems are when they don’t.
I may write more about this as I figure out how to use it.
###
A Gemfile is a file we create which is used for describing gem dependencies for Ruby programs. A gem is a collection of Ruby code that we can extract into a “collection” which we can call later. It lets you specify which gems you want to use, and which versions of these gems to use.
Simple example of a gemfile:
source 'https://rubygems.org'
gem 'nokogiri'
gem 'rails', '3.0.0.beta3'
gem 'rack', '>=1.0'
gem 'thin', '~>1.1'
Place the Gemfile
in the root of the directory containing the associated code. For instance, in a Rails application, place the Gemfile
in the same directory as the Rakefile
.
Gems are installed using a program called Bundler.
The Gemfile.lock
file is where Bundler records the exact versions that were installed. This way, when the same library/project is loaded on another machine, running bundle install
will look at the Gemfile.lock
and install the exact same versions, rather than just using the Gemfile
and installing the most recent versions.
Bundler provides a consistent environment for Rubyprojects by tracking and installing the exact gems and versions that are needed. Bundler is an exit from dependency hell, and ensures that the gems you need are present in development, staging, and production. Starting work on a project is as simple as bundle install .
Running different versions on different machines could lead to broken tests, etc. Never directly edit the lock file.
Exmple of Gemfile.lock:
GEM
remote: https://rubygems.org/
specs:
actioncable (5.2.1)
actionpack (= 5.2.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.1)
actionpack (= 5.2.1)
actionview (= 5.2.1)
activejob (= 5.2.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.1)
actionview (= 5.2.1)
activesupport (= 5.2.1)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.1)
activesupport (= 5.2.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.2.1)
activesupport (= 5.2.1)
globalid (>= 0.3.6)
activemodel (5.2.1)
activesupport (= 5.2.1)
activerecord (5.2.1)
activemodel (= 5.2.1)
activesupport (= 5.2.1)
arel (>= 9.0)
activestorage (5.2.1)
actionpack (= 5.2.1)
activerecord (= 5.2.1)
marcel (~> 0.3.1)
PLATFORMS
ruby
DEPENDENCIES
bootsnap (>= 1.1.0)
byebug
capybara (>= 2.15)
chromedriver-helper
coffee-rails (~> 4.2)
jbuilder (~> 2.5)
listen (>= 3.0.5, < 3.2)
puma (~> 3.11)
rails (~> 5.2.1)
rspec-rails
RUBY VERSION
ruby 2.5.1p57
BUNDLED WITH
1.16.3
References
References:
Most of this post is lifted directly from Gemfile & Gemfile.lock in Ruby by David Pargal, because I found it to be a very good and comprehensive article for beginners. Why copy it? Simply because the Internet is a dynamic place and for the benefit of my learning, I’d hate for the original source to disappear from the Internet, which, of course, I have no control over.
Other bits –
https://bundler.io/man/gemfile.5.html
RSpec is a framework used in test-driven development (TDD) for writing feature and unit tests to evaluate whether a computer program is fit for purpose.
Test-Driven Development works in a red-green loop:
The test always fails the first time because when we write the test, we haven’t attempted to pass it yet.
RSpec can be installed by navigating to the root project folder and typing:
$ gem install rspec
Unit tests test individual parts of the logic of a program. When you write a unit test, it should be as small and simple as possible. A feature test tests the program as a user. e.g. using the interface a user would use to see if the feature works.
By convention, tests written with RSpec are called “specs” (short for “specifications”) and are stored in the project’s spec
directory at root/spec/.
With RSpec, we are always describing the behaviour of classes, modules and their methods. The describe
block is always used at the top to put specs in a context. It can accept either a class name, in which case the class needs to exist, or any string you’d like.
describe ClassName do
end
This is perhaps the simplest RSpec test. This test will simply test for the existence of ClassName.
If we run the test now, it will fail because we haven’t written any code yet. This is in fact what we expect, so it’s not a bad thing.
We will get a uninitialized constant error because we have asked the test to check for the existence of a constant called ClassName, but as we have no production code yet, this constant cannot possibly exist – because nothing exists yet.
All we have to do to get this test to pass is to initialise the constant by calling it in the production code (stored by convention in the lib folder):
class ClassName
end
Before we run the test again, we need to alert Rspec of the existence of the file in which we’ve called the constant.
At the top of the spec file (above the test), add the line:
require 'filename'
Note: the file extension (.rb) and the relative file path (root/lib/) are assumed by Rspec.
The test should now pass.
Let’s look at a slightly more complex example…
describe StringCalculator do
describe ".add" do
context "given an empty string" do
it "returns zero" do
expect(StringCalculator.add("")).to eq(0)
end
end
end
end
Notes about this example:
describe
block to describe the add
class method. By convention, class methods are prefixed with a dot (".add")
, and instance methods with a dash ("#add")
.context
block to describe the context under which the add
method is expected to return zero. context
is technically the same as describe
, but is used in different places, to aid reading of the code.it
block to describe a specific example, which is RSpec’s way to say “test case”. Generally, every example should be descriptive, and together with the context should form an understandable sentence. This one reads as “add class method: given an empty string, it returns zero“.expect(...).to
and the negative variant expect(...).not_to
are used to define expected outcomes. The Ruby expression they are given (in our case, StringCalculator.add(""))
is combined with a matcher to fully define an expectation on a piece of code. The matcher we are using here is eq
, a basic equality matcher. RSpec comes with many more built-in matchers.describe ClassName do
describe "methodname" do
expect(Classname.methodname($args)).to eq(result)
end
end
Rspec tests can also be written using one-liner syntax. There is surprisingly little literature about this online.
I need to figure this out.
to complete
So, since Week 1 of Makers, my feelings towards the command line are changing. In week 1, I likened it to a printer – often doesn’t do what you want or expect of it, but never actually tells you in plain English what’s wrong with it, either giving you a cryptic message or more often preferring to remain completely silent.
Now, I’d say, you just have to know how to use it. It’s like one of those old cars that the piston-head owner is completely in love with, while most normal people think it is primitive and temperamental.
I can completely see why PCs never really took off until Microsoft and IBM found a solution to the problems of the direct operating system. I just feel like it could do with giving more feedback. I want to know when I’m on the right track without having to constantly ask.
The rule seems to be that if it doesn’t issue you with an error message, then the computer is happy. But that doesn’t mean I will necessarily be happy? It’s like speaking to somebody in a foreign country: I know I said something in their language but I swear the train station is the other way!?
But while all that is true, for a lot of things, it’s extremely nifty.
For everything the mouse did for graphical interfaces, ultimately making computing accessible to the masses, it still introduced the irritation of having to point a cursor into a text area, for example, and then moving your hand to the keyboard to type in it.
If you master the command line, a lot of that goes away. The only catch is that you do need a good command of shell script so that you can tell it exactly what you want it to do, and accuracy is vitally important.
I guess what I’m trying to say is that I’ve grown used to the command line under certain circumstances – maybe even developed an admiration for it. And that’s probably a good thing, because from what I’ve learned so far, as a software engineer, I’ll be spending a lot of time with it whether it annoys me or not.
^C
Every new project should be connected to a remote git repository for a number of reasons including protection from loss and version control.
Create project folder on local computer from command line
$ cd ~/Projects
$ mkdir nameit
$ cd nameit
Make git
$ git init
Create repo on Github
Click new repo
Get address of Git
Get SSH address (with colon after github.com)
Create remote
$ git remote add origin git@github.com:makersacademy/gitname.git
In summary…
echo "some text" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:makersacademy/gitname.git
git push -u origin master
Copyright 2021. All Rights Reserved. Adam Patel