My First Literary Rejection

Yay! I got my first rejection, from Bards and Sages Publishing, for “Once There Were Men.” I have not had time to write much in terms of short stories, so this was my first submission. I got much appreciated feedback. Very excited!

They gave me a scorecard:
Category Score
Character Development 
Dialogue
Grammar/Punctuation 4
Narrative Voice 3
Originality 2
Plot 2
Point-of-View
World-Building
Final Score 2.750

It’s probably a pretty bad score, but now I know more of what they are looking for. Bards and Sages left a comment on The Wolf Dreams Books Facebook page: “It is always nice when someone takes a rejection in stride. If you are interested, we provide a breakdown of what those scores actually mean on the website.”

I also received Reviewer Notes: “To me, this reads less as a story and more as a brief lecture on the overall morality of the human species, or, in the author’s apparent view, the lack of it. The species is presented as callous and selfish in the extreme, but without any detail or nuance to the presentation. I actually have a difficult time classifying this as fiction rather than opinion as there’s little in the piece designed to make me feel rather than tell me how horrible my species is.”

After “Tishta the Crystal Orb” is out, I’m planning to focus on developing my short story skills. 2018 will be a year of discovering places to submit and how to write the stories they want to read.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Advertisements
Posted in AmWriting, AmWritingFantasy, Books, Environment, Fantasy, Horror, Life, Novel, Reading, Science, Writing | Tagged , , , , , , , | 1 Comment

The Wrong Donations – Some Tough Words on Disaster Relief

This is a heartfelt reminder to think before you donate goods. It applies to any donation you might make to any charity–local, national or international. The work it takes to sort through donations of unusable clothing and other items sometimes is not worth the effort. In general, underwear and socks are always in high demand–but donate NEW ONES. Any other clothing donations should be clean and gently used (or, better yet, new or like-new).

My Best Laid Plans

I need to make a statement. I want to say it as kindly and gently as possible, but this message really needs to get out there. It’s important. Please hear me with as much grace as you can, because I mean it with all love and gentleness.

My children and I spent hours yesterday sorting the donations that are pouring in. That picture is the mountain we were faced with, and it was still coming. We’re not the only ones. Hundreds (thousands?) of volunteers all across our state are doing the same exact thing. Why? Because your hearts are in theright place.That’s why.

I want to make that abundantly clear. It is beautifully apparent that you are thinking about us and that you want to help us figure this thing out. You are doing anything you can, and that has brought such profound joy to our hearts. I personally…

View original post 1,093 more words

Posted in Uncategorized | Leave a comment

My JS Journey: Creating an npm Package

In this blog post, I will show how to create an npm package that can be used from other modules. The example is a wrapper around node fs.

Setting up

Start as you would for any ES6 project by creating the following. The steps are covered in previous blog postings: My JavaScript Journey: Basic ES6 CLI Skeleton and Mocha as a JavaScript Test Framework.

mkdir file-handler
cd file-handler
git init
npm init -y
mkdir src
cd src
create index.js
create _index.js
cd ..
mkdir test
cd test
create test.js
cd ..
npm install babel-core --save-dev
npm install babel-preset-env --save-dev
npm install babel-register --save-dev
npm install babel-cli --save-dev
npm install mocha --save-dev
create .gitignore
create .babelrc
cd src
update package.json to add scripts, etc.

Test fs.readFile

Add tests to test/test.js that call your wrapper method

import assert from 'assert';
import FileHandler from '../src/index';

describe('FileHandler', function() {
  const testFilesPath = 'test/data/';
  const fileName = 'hello.txt';
  let fileHandler = new FileHandler();
  describe('getData', function() {
    it('should return error when invalid path', function(done) {
      const path = "blah";
      const expected = "ENOENT: no such file or directory, open '" + path + "'";
      fileHandler.getData(path)
      .catch(function (e) {
        assert.equal(expected, e.message);
        done();
      })
      .catch(function(err) {
        done(err);
      });
    });

    it('should return file contents', function(done) {
      const expected = "hello";
      fileHandler.getData(`${testFilesPath}${fileName}`)
      .then(function(data) {
        assert.equal(encodeURI(data), expected);
        done();
      })
      .catch(function(err) {
        done(err);
      });
    });
  });
});

Add a wrapper method to src/index.js

Since the only thing you will be exporting is the FileHandler class, the code goes directly into /src/index.js. This is what will be imported by the module that uses it.

import fs from 'fs';

class FileHandler {
  getData(path, type = 'utf8') {
    return new Promise((resolve, reject) => {
      fs.readFile(path, type, (err, data) => {
        if (err) { reject(err); }
        resolve(data);
      })
    });
  }
}

export default FileHandler;

Run the test

Add a script to run the tests to package.json:

"test": "mocha --compilers js:babel-core/register test/test.js"

Run:
npm test

One test should pass and one should fail.

  FileHandler
    getData
      ✓ should return error when invalid path
      1) should return file contents

  1 passing (268ms)
  1 failing

  1) FileHandler getData should return file contents:
     Error: ENOENT: no such file or directory, open 'test/data/hello.txt'
      at Error (native)

To make the tests run automatically with each change, add the following scripts to package.json:

"start": "npm run dev",
"dev": "npm test -- -w",

To ensure you build after each change, add the following script to package.json ("pre" is a prefix that will run the script before either build or test):

"pretest": "npm run build",

And, to prevent the test file(s) from being included in the distribution, add the babel-cli flag --ignore to the build script in package.json:

"build": "babel ./src -d ./dist --ignore test.js",

Now, run:

npm start

You will see the scripts chained together. In the end, Mocha will be running, waiting for the next change to be saved. To quit, ctrl-c.


> file-handler@1.0.0 start /Users/<your source>/file-handler
> npm run dev

> file-handler@1.0.0 dev /Users/<your source>/file-handler
> npm test -- -w

> file-handler@1.0.0 pretest /Users/<your source>/file-handler
> npm run build

> file-handler@1.0.0 prebuild /Users/<your source>/file-handler
> npm run clean

> file-handler@1.0.0 clean /Users/<your source>/file-handler
> rm -rf dist

> file-handler@1.0.0 build /Users/<your source>/file-handler
> babel ./src -d ./dist --ignore test.js

src/_index.js -> dist/_index.js
src/index.js -> dist/index.js

> file-handler@1.0.0 test /Users/<your source>/file-handler
> mocha --compilers js:babel-core/register test/test.js "-w"

  FileHandler
    getData
      ✓ should return error when invalid path
      1) should return file contents

  1 passing (268ms)
  1 failing

  1) FileHandler getData should return file contents:
     Error: ENOENT: no such file or directory, open 'test/data/hello.txt'
      at Error (native)

Add test/hello.txt File

cd test
mkdir data
create hello.txt

You will need to tickle src/index.js and save it to trigger the tests to run again (or ctrl-c and start again). The test will still fail since there is no content in test/data/hello.txt.

  FileHandler
    getData
      ✓ should return error when invalid path
      1) should return file contents

  1 passing (39ms)
  1 failing

  1) FileHandler getData should return file contents:

      AssertionError: '' == 'hello'
      + expected - actual

      +hello

      at test/test.js:26:16

Add ‘hello’ to test/data/hello.txt. Tickle index.js and save it to run the tests again. All happy and green now.

  FileHandler
    getData
      ✓ should return error when invalid path
      ✓ should return file contents

  2 passing (8ms)

Checkin

This is a good spot to checkin.

Currently, my package.json looks like this:

{
  "name": "file-handler",
  "version": "1.0.0",
  "description": "Library creation demonstration",
  "main": "index.js",
  "scripts": {
    "clean": "rm -rf dist",
    "prebuild": "npm run clean",
    "build": "babel ./src -d ./dist --ignore test.js",
    "start": "npm run dev",
    "dev": "npm test -- -w",
    "pretest": "npm run build",
    "test": "mocha --compilers js:babel-core/register test/test.js"
  },
  "keywords": [
    "node",
    "fs",
    "testing",
    "mocha",
    "javascript",
    "es6"
  ],
  "author": "Ramona Ridgewell",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.24.1",
    "babel-core": "^6.25.0",
    "babel-preset-env": "^1.5.2",
    "babel-register": "^6.24.1",
    "mocha": "^3.4.2"
  }
}

Using the Library

We need a different app to import file-handler. How do we do that? First, to get the ES5 transpiled version of the code, change the "main" property in package.json to point to ./dist/index.js.

  "main": "./dist/index.js",

The final bit is to set which files are required by the end-user, which is the ./dist/ folder. Add this to package.json:

"files": [
  "dist"
]

Create node.js Package Module

The first step in publishing an npm module is to create the package. Navigate to the root where the package.json is. Run:

npm pack

This creates file-handler-1.0.0.tgz in the same directory. It gets the "name" field from package.json and appends the "version" from the same file, to create the file name. You can see the contents by running:

tar -tf file-handler-1.0.0.tgz

which returns:

package/package.json
package/README.md
package/dist/_index.js
package/dist/index.js

Test the Module

Create Test Module

To set up a new module, you can use this package.json or however you wish to set it up.

{
  "name": "testFileLib",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "clean": "rm -rf dist",
    "prebuild": "npm run clean",
    "build": "babel ./src -d ./dist --ignore test.js",
    "start": "npm run dev",
    "dev": "npm test -- -w",
    "pretest": "npm run build",
    "test": "mocha --compilers js:babel-core/register test/test.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.24.1",
    "babel-core": "^6.25.0",
    "babel-preset-env": "^1.5.2",
    "babel-register": "^6.24.1",
    "mocha": "^3.4.2"
  }
}

Add the usual src/index.js, src/_index.js, .babelrc, .gitignore. index.js doesn’t need to do anything at this point.

const main = () => {
  console.log("hello");
};

main();

Install Your Package

Here’s the most exciting part. Navigate to the root of your test project and run:

npm install ../file-handler/file-handler-1.0.0.tgz

The path assumes your library and test project are in the same parent directory —adjust appropriately. The output looks like this:

testFileLib@1.0.0 /Users/<your source>/testFileLib
└── file-handler@1.0.0

npm WARN testFileLib@1.0.0 No repository field.

If you check ./node_modules/, you will find a file-handler directory with the built /dist/, and the package.json and README.md.

Write Some Tests

I literally copied the tests from file-handler and changed line 2 to:

import FileHandler from 'file-handler';

Running npm test should just work as expected.

Read File When Running Test App

To use file-handler in index.js, change it to the following:

import FileHandler from 'file-handler';

const main = () => {
  const fileHandler = new FileHandler();
  const fileName = "test/data/hello.txt"
  fileHandler.getData(fileName)
  .then((data) => {
      console.log(data);
  })
  .catch((err) => {
    console.log("error reading file", err);
  });
};

main();

If you run:

npm test

it will clean, build and run your tests. Then, run:

node src/_index

It should say hello or whatever you put in your file.

Add file-handler to npm

At this point, even though the library only supports one method, I am going to show how to make your new library available on npm.

Add User

Assuming you have never done this before, run the following:

npm adduser

It will prompt you for Username, Password, Email. Username must be unique, so you might need to try a couple of times to find an unused one. The error begins with this:

npm WARN adduser Incorrect username or password
npm WARN adduser You can reset your account by visiting:
npm WARN adduser
npm WARN adduser     https://npmjs.org/forgot
npm WARN adduser

You can verify you are not already using the email by going to the link https://npmjs.org/forgot and trying to have a reset email sent. When you give it all valid responses, it will respond with:

Logged in as on https://registry.npmjs.org/.

Confirm you were added by going to:

https://www.npmjs.com/~<your username>

If you already have an npm user, you can login using:

npm login

Publish the Module

Now, it’s time to publish. As long as you’re in the root of the project (with the package.json), you don’t need to specify the folder to point to that file. Include the tarball and, unless you’re a paying member, don’t forget to make the package public (it defaults to private).

npm publish file-handler-1.0.0.tgz --access public

If your project name is already taken on npm, which this example assumes, you will receive an obtuse error message that includes:

npm ERR! you do not have permission to publish "file-handler". Are you logged in as the correct user? : file-handler

To overcome the error without simply choosing a different package name, create and install a scoped package, which I discuss below. I think this is a better way to go since all of your packages will be bundled under your npm user name in the file hierarchy.
If you wish, you can search to try to find a unique name using:

npm search

To add scope, prefix your package.json "name" with @ followed by your npm user name. The @ is important and will be included in the import paths.

{
  "name": "@<your npm user name>/file-handler"
}

Create a new tarball. It will include the prefix.

npm pack

generates the file

<your npm user name>-file-handler-1.0.0.tgz

When you install the new tarball in your test project, you will find this folder structure in ./node_modules/:

/@<your npm user name>/file-handler/

Of course, you will then need to change your test project code paths to reflect the change. Don’t forget the @.

import FileHandler from '@<your npm user name>/file-handler';

Run your tests. They should just pass.

This time, publishing should work:

npm publish <your npm user name>-file-handler-1.0.0.tgz --access public

A successful publish will result in something like this:

+ @<your npm user name>/file-handler@1.0.0

Once you publish a package with a given name and version, it can never be used again. You will need to change the version in package.json.

Now, go back to your test project’s ./node_modules/ and delete

./@<your npm user name>/file-handler/

Then, to install your package from npm, run:

npm install @<your npm user name>/file-handler --save-dev

It should succeed. The output looks like this:

testFileLib@1.0.0 /Users/<your>/<src>/testFileLib
└── @<your npm user name>/file-handler@1.0.0

npm WARN testFileLib@1.0.0 No repository field.

If you check your package.json, you should find this line added to the devDependencies:

"@<your npm user name>/file-handler": "^1.0.0",

Run your tests. All should be well in the universe.

In Conclusion

Wow. This took a lot of research. In my next blog post, I will cover making updates to the npm package. The file-handler code is in my GitHub file-handler repository.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, #npm, AmWriting, Coding, GitHub, JavaScript, Programming, Science, STEM | Tagged , , , , , , , , , , , , , , | 1 Comment

Mocha as a JavaScript Test Framework

The last few projects I discussed were to get you started coding in ES6 JavaScript. I intentionally kept the functionality very limited. In this article, I will show how to set up a test framework using my ES6 CLI Promises repository, promises. There are many different frameworks to choose from. A simple one to set up is Mocha.

Setting up

First, clone promises (the instructions for cloning are included in the article that goes with this repository, My JS Journey: Promises).

Next, install the node dependencies.

npm install

Then, build and run it to ensure everything is set up correctly.

npm run build
npm start

It should say,
hello world

Install Mocha

Install Mocha.

npm install mocha --save-dev

This should have added mocha to the devDependencies in package.json. Now is a good time to change the name.

{
  "name": "MochaExample",
  "version": "1.0.0",
  "description": "Simple Mocha example",
  "main": "index.js",
  "scripts": {
    "build": "babel src -d dist",
    "start": "node dist/index",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.24.0",
    "babel-core": "^6.24.0",
    "babel-preset-env": "^1.3.2",
    "babel-register": "^6.24.0",
    "mocha": "^3.3.0"
  }
}

Might as well check in the code.

Convert src/hello.js to Implement a class

To facilitate exporting, I find it easiest to use classes. Modify src/hello.js as follows.

class Hello {
  static getWorld() {
    return new Promise((resolve) => {
      setTimeout(() => resolve(' world'), 500);
    });
  }

  static hello() {
    return new Promise((resolve) => {
      this.getWorld().then(result => {
        resolve('hello' + result);
      });
    });
  }
}
export default Hello;

Notice that the functions changed from const to static. Also, now that they are part of the object, to reference them within the object, it is necessary to prefix them with this., e.g. this.getWorld(), as in line 10.
Modify src/index.js to accommodate the new class.

import Hello from './hello';

const sayHello = (message) => {
  console.log(message);
};

const main = () => {
    var args = process.argv;
    if (args[2] && args[2] === '--v' ) {
        console.log('Es6CliSkeleton - version 1.0.0');
    } else {
        Hello.hello().then(res => sayHello(res));
    }
};

main();

The lines that changed are 1 and 12, both of which reference the new Hello class.

Build and run to ensure everything still works.

Adding Tests

First, create a folder test. Add a file to this folder called hello_test.js.
Add the first test.

import assert from 'assert';
import Hello from '../src/hello';

describe('Hello', function() {
  describe('getWorld', function() {
    it('should return space world', function() {
      Hello.getWorld()
      .then(result => {
        assert.equal(' world', result);
      });
    });
  });
});

Next, in package.json, modify the “scripts” section’s “test” to:

"test": "mocha --compilers js:babel-core/register test/test.js"

Build and run the test.

npm run build
npm run test

You should get output something like this.

> MochaExample@1.0.0 test /Users/your_src/promises
> mocha --compilers js:babel-core/register test/*_test.js
  Hello
    getWorld
      ✓ should return space world
  1 passing (100ms)

With a nice green checkmark.
Check the code in.

A Second Test

We should have a test on the other function, Hello.hello(). It will be very similar the first one. Add this right code after the other test.

  describe('hello', function() {
    it('should return hello world', function() {
      Hello.hello()
      .then(result => {
        assert.equal('hello world', result);
      });
    });
  });

Build and run. The output should look like this.

  Hello
    getWorld
      ✓ should return space world
    hello
      ✓ should return hello world

  2 passing (65ms)

Go ahead and check that in since the next section covers something a little different.

A Broken Promise

Let’s see what happens when the promise is broken. Modify what the promise returns in Hello.getWorld() from

  setTimeout(() => resolve(' world'), 500);

to

  let input = "myErr";
  if (input === "myErr") { reject(new Error(input)); }
  setTimeout(() => resolve(' world'), 500);

Build and run the app.

> MochaExample@1.0.0 start /Users/your_src/Closet/promises
> node dist/index

(node:61097) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): 42

It fails, kind of how you might expect. Run the tests.

  Hello
    getWorld
      ✓ should return space world
(node:61087) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: myErr
    hello
      ✓ should return hello world
(node:61087) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): Error: myErr

  2 passing (111ms)

Interestingly, the tests pass, although they report the unhandled promise rejection. Let’s fix that first. Modify the tests to include a catch, which will also require the use of done in lines 6, 10 and 14, and 19, 23 and 27.

import assert from 'assert';
import Hello from '../src/hello';

describe('Hello', function() {
  describe('getWorld', function() {
    it('should return space world', function(done) {
      Hello.getWorld()
      .then(result => {
        assert.equal(' world', result);
        done();
      })
      .catch(err => {
        console.log(err);
        done(err);
      });
    });
  });
  describe('hello', function() {
    it('should return hello world', function(done) {
      Hello.hello()
      .then(result => {
        assert.equal('hello world', result);
        done();
      })
      .catch(err => {
        console.log(err);
        done(err);
      });
    });
  });
});

Now, the tests fail and let you know why:

  1) Hello getWorld should return space world:
     Error: myErr
      at src/hello.js:5:39
      at Function.getWorld (src/hello.js:3:12)
      at Context.<anonymous> (test/hello_test.js:7:13)

  2) Hello hello should return hello world:
     Error: myErr
      at src/hello.js:5:39
      at Function.getWorld (src/hello.js:3:12)
      at src/hello.js:12:12
      at Function.hello (src/hello.js:11:12)
      at Context.<anonymous> (test/hello_test.js:20:13)

Remove the changes to getWorld(). Check in the code.

In Conclusion

I generally start by writing my tests (Test Driven Development or TDD). I believe it is one of the fundamental practices in good code development. It is important to ensure you have complete test coverage. In this example, you can see I had tests for the “happy path” but had not covered potential failures. It was a bit contrived, but be on the lookout for things that can go wrong. In My JS Journey: Creating an npm Package, I show how to wrap Node fs, which is their file system interface. That blog post includes more about how to use Mocha in a less-contrived project. As that project progresses, it will have a lot of good examples where you need to test for things that might go wrong—a missing file, an empty file, invalid permissions—lots of things to test for. It also has

You can find the code for this project in my github repository, mocha-example.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, AmWriting, Education, GitHub, JavaScript, Programming, Science, Software Development, STEM | Tagged , , , , , , , , , , | 1 Comment

Take Your Daughter to Work Day

What do you think when you hear, “Black Lives Matter?” Do you immediately think, “well, all lives matter?” If so, you’re missing the concept of systemic discrimination. It’s built into our societal norms. It won’t change unless we take steps to make it change. That might mean that someone in the group of discriminators will feel left out or cheated out of an opportunity he thinks he deserves as much as the next person. I’ll tell you this, until Black lives do matter, no lives matter in our country.

The reason I brought up the Black Lives Matter movement is to draw a comparison to another movement from the ’90s, “Take Your Daughter to Work Day.” It was an attempt by women in my industry, computer engineering, to show girls how cool coding could be—and to encourage them to study maths and sciences so that becoming a computer geek was not beyond their reaches.

Over the next couple of years, the movement spread to other disciplines—but it was about daughters. It didn’t take long for parents of boys to complain it was unfair to set aside a special day for girls. Their sons were being left out. They had never witnessed a group of children entering a computer lab—in those days, there would have been just a few machines available—the rush forward, the elbowing to get on the limited resources. Let me! Let me, do it! If they had been there, they would have seen the boys take over all of the machines, with clusters of their peers around them. The girls—at least most of them—would be standing behind the boys, watching, not doing. This was the reason to give girls a special day—to let them engage with the technology on their own terms.

Every year on Take Your Child to Work Day, I am reminded of the way girls continue to be excluded from the sciences, especially Computer Science. Back in the ’80s—the heyday of women in computing—the percentage of young women graduating in the field was around 35%. By 2013, the number had dropped to 18%. We are responsible for this drop. We encourage the practices that preclude girls from a science-rich education. For the men who rule this lucrative, high-paying profession, this leaves little competition from a whole gender—half the population—of people. I wonder if things would be better for women today if we had focused, as a nation, on educating girls in what is now called STEM.

I know, from personal experience, the challenges of being a woman in a man’s field—I  remember only being mentored by one of my male managers, and not very proactively; I was passed over for the coolest and most important projects; I was excluded from being part of “the club”—perhaps not overtly, but just by virtue of the extracurricular activities “the club” pursued, like telling an off-color joke, or going out to drink scotch and smoke cigars, or going on a camping trip to shoot guns and ride dirt bikes. In my day-to-day jobs, I have almost always been the sole woman on my team, in a hierarchy of all-men teams. All of these things, combined, leads to women in computing making only 87% of what their male counterparts are paid. The percentage of women computer engineers, from my direct observation over many years, is around 10%. When high-tech companies state their percentages at closer to twenty, they are including women who work in all capacities, such as program managers, scrum masters, human resources and recruiting—the latter two being predominantly women.

The practice of exclusion of women reaches beyond computer engineering to other high-paying professions. A good example is the Hollywood movie industry. I wrote about this a couple of years ago. It includes the fact that women directed only 6% of the top 250 U.S. grossing films in 2013. The pay gap for women is also well documented. A big deal was made of Anna Boden being selected to direct the new Marvel movie, “Captain Marvel,” although, the co-director is a man, Ryan Fleck. One of the reasons for the hoopla is that Marvel has never had a woman at the helm of one of its movies before. Maybe things are progressing at Marvel—the writers, Nicole Perlman and Meg LeFauvre, are also women, as is the star, Captain Marvel herself, Brie Larson. I hope the company hired these women on the merits of their work and not to save 30% on their wages.

So, on this Take Your Child to Work Day, remember its original intent. Also, when you think about Black Lives Matter, remember, in my field, Black Americans of all genders make up just over 5% of the employees, and Black engineers make up only 1-3%. I can count on one hand the number of Blacks I have worked with, and almost never on my own team. I have nothing against Chinese and Indian immigrants coming to America—some of my best friends are Indians, and we are all, except for Indigenous people, children of immigrants—but, in computing, they are grossly over-represented, especially in the engineering jobs. Maybe we should think about enabling our own children—most importantly women and minorities—to fill these high-paying jobs.

Don’t forget to take your daughter to work today.

Thanks to:
fortune.com
www.aauw.org
time.com/money
www.polygon.com
cra.org

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, Black Lives Matter, Coding, Education, family, Programming, Science, STEM, Uncategorized, Women | Tagged , , , , , , , , , , , , | Leave a comment

An Accessible and Usable GitHub Repository

After adding a few repositories to GitHub, I realized I neglected to discuss README.md. This is a place where you can put notes about your project which will appear on the repository page. For example, here’s the README.md from my newest repository, promises-browser.

See [this article](https://ramonaridgewell.wordpress.com/2017/04/24/my-js-journey-a-promise-in-a-browser/) for a description of how to set up this project.

It shows up at the bottom of the GitHub page, after the list of files. It’s also a good practice to add a description, a link to a webpage, and topics (up near the top).

Screen Shot 2017-04-24 at 12.06.05

I’ve been linking to the articles in my blog for setup instructions, but you could include pertinent notes in the README.md, and they will show up there.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, AmWriting, Coding, Education, GitHub, JavaScript, Science, Women, Writing | Tagged , , , , , , , , , | Leave a comment

My JS Journey: A Promise in a Browser

In this example, I’m going to explain how to fork a GitHub repository—or copy someone else’s—as well as implement a simple promises app. As an added bonus, I threw in using a Class. The code to fork is my JavaScript browser skeleton.

Forking a Repository

In GitHub:

In the upper right, Click the Fork.

In iTerm:

Once you have your local GitHub repository, you can follow the instructions for cloning I outlined in Promises. For more on forking, see this GitHub article.

To install all the node packages, run:

npm install

Then build:

npm run build

To see it run, open index.html. When you click the Get Message button, the Message should dislpay “Hello.”

Screen Shot 2017-04-03 at 09.37.37

Adding A Class

Because I like classes, I implemented one, so you can see how that works with respect to export.

First, implement the class by changing src/hello.js as follows:

class Hello {
  static hello(){
    return 'Hello';
  }
}

export default Hello;

Modify src/index.js to import the class:

import Hello from './hello.js';

var sayHello = function () {
  return Hello.hello();
}

document.getElementById('msgBtn').addEventListener('click', function () {
    var message = sayHello();
    document.getElementById("message").innerHTML = message;
});

Build the project.

npm run build

Load or refresh index.html:
Screen Shot 2017-04-03 at 09.37.37
Checkin the code.

Adding Promises

This example is basically the same as the CLI one I described in Promises. The major difference, of course, is this one is in the browser. Promises let you ensure the order of asynchronous events, such as file reading. In my example, I retrieve the text ” world” after a timeout, and append it to “Hello” from the origin example. It’s contrived, but it shows how a promise works.

Modify src/hello.js as follows:

class Hello {
  static getWorld() {
    return new Promise((resolve) => {
      setTimeout(() => resolve(' world'), 500);
    });
  }

  static hello(){
    return new Promise((resolve) => {
      this.getWorld().then(result => {
        resolve('Hello' + result);
      });
    });
  }
}

export default Hello;

Modify src/index.js to resolve the promise returned from Hello.hello():

import Hello from './hello.js';

const sayHello = (message) => {
document.getElementById("message").innerHTML = message;
};

document.getElementById('msgBtn').addEventListener('click', () => {
Hello.hello()
.then(res => sayHello(res));
});

Build the code and refresh index.html. It should now display “Hello world” instead of simply “Hello.” You might be able to see the half-second lag on getting the message. That’s the timeout.

Screen Shot 2017-04-21 at 12.59.10

Check the code in.

In Conclusion

Promises in ES6 are not difficult, although they can be cumbersome if there are a lot of nested Promises. The new—and, as of yet, not completely supported—ES7 feature, async/await, is meant to simplify nested Promises. I’ll write about that in a future post. You can find the Browser Promise code in my github repository, promises-browser.

Copyright ©2014-17 Ramona Ridgewell. All rights reserved.

Posted in #Education, AmWriting, Coding, Education, JavaScript, Programming, Science, Women, Writing | Tagged , , , , , , , , | 1 Comment