Alexius-Huang / Wunderschon

Wonderful, gorgeous rabbit online shopping mart
MIT License
5 stars 0 forks source link

Wunderschön

MIT Licence Build Status Code Climate

Ruby on Rails Ruby

forthebadge forthebadge

Wunderschön Rabbit

About

Wunderschön means very gorgeous and wonderful in German. This project is a kind of online shopping website which is filled with sketches of rabbits and its products.

Wunderschön is built with Ruby version 2.4.1 and Rails 5.1.

Requirement

Installation & Setup

Clone It!

$ git clone git@github.com:Maxwell-Alexius/Wunderschon.git

Go into the project folder:

$ cd Wunderschon

Bundle it:

$ bundle install

Create and migrate database:

$ bundle exec rails db:create 
$ bundle exec rails db:migrate

If yarn haven't installed in your OS, see installation of yarn. After yarn installed, run this command to install JS packages via yarn:

$ yarn init

You can choose to open Rails server and open webpacker (JS develop server) separately, that requires you to open additional two terminal and run two commands separately:

# Rails server
$ bundle exec rails server
# Webpacker JS develop server
$ ./bin/webpack-dev-server

Or you can integrate both server into a terminal via one command:

$ foreman start

It will automatically start both Rails server and JS webpacker develop server in the same terminal.

Develop Notes

Gems Info

Excluded the Rails default gems, the info of the included Ruby gems are listed below (in an alphabetical order):

JS Asset Pipeline with Webpacker & Yarn

Using Rails 5.1+ provided new feature: Loving Javascript integrate with Yarn JS dependencies management. You can think of Yarn as the JS version of the bundler.

Setting Up Webpacker

  1. Add gem webpacker to the Gemfile and execute bundle install
  gem 'webpacker'
$ bundle install
  1. Remember to check and update your NodeJS version! (>= 6.4.0)
$ node -v
  1. After install the gem, webpacker provide several rake tasks. To check it, run bin/rails webpacker you should get the following output:
$ bin/rails webpacker
Available webpacker tasks are:
webpacker:install                Installs and setup webpack with yarn
webpacker:compile                Compiles webpack bundles based on environment
webpacker:check_node             Verifies if Node.js is installed
webpacker:check_yarn             Verifies if yarn is installed
webpacker:check_webpack_binstubs Verifies that bin/webpack & bin/webpack-dev-server are present
webpacker:verify_install         Verifies if webpacker is installed
webpacker:yarn_install           Support for older Rails versions. Install all JavaScript dependencies as specified via Yarn
webpacker:install:react          Installs and setup example React component
webpacker:install:vue            Installs and setup example Vue component
webpacker:install:angular        Installs and setup example Angular component
webpacker:install:elm            Installs and setup example Elm component
  1. Choose an installation command, e.g. if you want to install with React, run
$ bundle exec rake webpacker:install:react
  1. After webpacker installed, you can put your ES6 JS files in the app/javascript directory. This is where the webpacker compiles your JS file.

  2. Run the command below to compile the JS files. The compiled files will be placed in public/packs directory.

$ bundle exec webpacker:compile
  1. webpacker gem provide helper method javascript_pack_tag for loading JS files in your views. For instance, to load the compiled application.js in application.html.erb, in your view:
<html>
  <head>
    <!-- ... Other Stylesheet or Meta Tags ... -->

    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <!-- Load compiled application.js -->
    <%= javascript_pack_tag    'application' %>
  </head>
  ...

Develop with foreman

foreman can help us manage to execute rails server with webpacker watch mode at the same time. Install the gem first, but not to include in your project Gemfile!

$ gem install foreman

Create the Procfile in the app root directory and add the content:

web: bundle exec rails server
webpacker: ./bin/webpack-dev-server

Running the command will start the rails server and start the webpacker watch mode:

$ foreman start

For more information, see foreman gem GitHub

Using Yarn

It is very easy to use Yarn, similar to node package manager, initialize Yarn first:

$ yarn init

Use the command to install any node package:

$ yarn add [package-name]

For example, adding jquery via yarn is simple:

$ yarn add jquery

Webpack prefers the original, unmodified source code of a library, rather than the packaged “dist” code. In Rails config/webpack/shared.js, add the alias key in the resolve object with an object which aliases the "jquery" with the directory of the jQuery file:

// ... Omitted
module.exports = {
  // ... Omitted

  resolve: {
    alias: {
      jquery: 'jquery/src/jquery'
    },
    // ... Omitted
  }
}

In order to make jQuery available to other modules, we can use the webpack.ProvidePlugin makes a module available as a variable in every other module required by webpack. Therefore, in the same file, add the statement in the plugins part of the export module object:

// ... Omitted
module.exports = {
  // ... Omitted

  plugins: [
    // Omitted
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      jquery: 'jquery'
    })
  ],

  // ... Omitted
}

Lastly, we can then require jQuery in the pack. Import jQuery into app/javascript/packs/application.js and make it available globally using the window object:

import jQuery from 'jquery'
window.jQuery = jQuery

For more information, you can read:

Node Packages Info

Using ReactJS in Rails with Webpacker

Installation

Make sure you have webpacker already installed, if not, run:

$ bin/rails webpacker:install

Then just run the webpacker built-in command and it'll serve you well:

$ bin/rails webpacker:install:react

It will automatically configure the package.json, .babelrc and install dependencies including the babel-preset-react which enables you to use JSX syntax during development.

[Deprecated]

Additionally, you should also install prop-types package using Yarn:

$ yarn add prop-types

Because React.PropTypes is deprecated as of React version 15.5, so if you want to use type checking (and it is highly recommended), you should also install the prop-types library instead.

[Update] When install react with webpacker, it also helps you install the prop-types library which you don't need to install it by yourself.

Using react-rails with webpacker

Note: Please make sure you have setup webpacker with react.

Add react-rails into your Gemfile and run bundle install. After installation, run:

$ rails generate react:install

Which generates:

Please visit react-rails repository for more information. This README only covers the step to setup ReactJS environment.

In the application/javascript/packs/application.js, you can see that react-rails automatically add several lines which enables you to controller React components rendering:

// Support component names relative to this directory:
var componentRequireContext = require.context('/components', true)
var ReactRailsUJS = require('react_ujs')
ReactRailsUJS.useContext(componentRequireContext)

Add the statement ReactRailsUJS.mountComponents in the document ready event, which enables to use the simple React component helper:

$(document).ready(function() {
  ReactRailsUJS.mountComponents()
})

So when we want to render the component file, say hello.jsx, we can use the react_component helper to render it:

<%= react_component 'hello' %>

We can also pass in default props with a Ruby hash which is very helpful:

<%= react_component 'hello', greetings: 'hello', name: 'Maxwell-Alexius' %>

Hello World Example

After installation, you can manage and develop React component in app/javascript/packs/components/ directory. To create a component, for example, the hello-world program, create a new file called hello-world.jsx and below is the example code:

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

/* Declare Your Component */
class HelloWorld extends React.Component {
  constructor(props) {
    super(props)
    /* You can initialize your states here */
    // this.states = { ... }
  }

  static defaultProps = {
    appName: 'Hello World!'
  }; // <----- Do not forget the semicolon!

  /* You can declare life-cycle methods in this component declaration block */
  // componentWillMount() { ... }
  // componentDidMount() { ... }
  // shouldComponentReceiveProps() { ... }
  // ... other life-cycle methods

  render() {
    return (
      <div className="hello-world">
        {this.props.appName}
      </div>
    )
  }
}

/* Checking Props' Types */
HelloWorld.propTypes = {
  appName: PropTypes.string.isRequired
}

/* Render Your Component */
// You should have <div id="app"></div> in your HTML file
ReactDOM.render(
  <HelloWorld />,
  document.getElementById('app') 
)

Nested Components

For example, to nest another component in our HelloWorld component, let's create another directory which is called components/hello_world/ and include another component file inner-component.jsx. It should use the export default to export our component as a module:

import React from 'react'
import PropTypes from 'prop-types'

class InnerComponent extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div className="inner-component">
        Hello, This is the InnerComponent!
      </div>
    )
  }
}

export default InnerComponent

And then include the module to our root component file. Using JSX syntax to use the component in the render method:

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
import InnerComponent from './hello_world/inner-component'

class HelloWorld extends React.Component {
  /* ... Omitted ... */
  render() {
    return (
      <div className="hello-world">
        <InnerComponent />
      </div>
    )
  }
}

Using props to Transfer Date From Parent to Child Component

(Drafting...)

Using key to Render List-alike Component Structure

(Drafting...)

Using state to Update and Mutate the State of the Data

(Drafting...)

Event Handling

(Drafting...)

Using refs to Reference Child Component from Parent

(Drafting...)

Wunderschön Shopping Cart Design

Using React.js to construct the shopping cart component UI interface. Its structure is presented below:

- shopping-cart (Root Component)
  - message
  - icon
  - wrapper
    - header
    - body
      - caption
      - *item
        - quantity-field
    - footer

Hint: * means list-like components

(Drafting...)

Axios - HTTP Client from Browsers & NodeJS

Installation

(Drafting...)

Basic Usage

(Drafting...)

RxJS - Reactive Programming using Observable

Installation

(Drafting...)

Basic Usage

(Drafting...)