New Way to Develop React App With Create React App (No Build Configuration)

New Way to Develop React App with Create React App (No Build Configuration)

Setting up Gulp, Webpack, Browserify, Babel, JSX, ES6, ES6 modules, hot reloading, … etc. manually - forget about it and no more fuss with it.

Inspired by the cohesive developer experience provided by Ember.js Facebook wanted to provide an easy way to develop React apps, they created create-react-app with the targets zero configuration.

Installation
You may need NPM installed and you can use NVM to easily switch Node versions between different projects.

The Node installation is only required for Create React App itself.

To install create-react-app module, run:

1
npm install -g create-react-app

Creating an App
To create a new app, run:

1
create-react-app geekhmer

It will create a directory called geekhmer inside the current folder. And inside that directory, it will generate the initial project structure and install the transitive dependencies:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
geekhmer/
  README.md
  node_modules/
  package.json
  .gitignore
  public/
    favicon.ico
    index.html
  src/
    App.css
    App.js
    App.test.js
    index.css
    index.js
    logo.svg

No configuration or complicated folder structures, just the files you need to build your app.

Run the App
Runs the app in development mode:

1
npm start

Open http://localhost:3000 to view it in the browser.

Run the Test
Runs the test watcher in an interactive mode:

1
npm test

Read more about testing.

Builds the App for Production
Builds the app for production to the build folder. It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes. By default, it also includes a service worker so that your app loads from local cache on future visits.

1
npm run build

Your app is ready to be deployed. So far so good, That’s it!!! See ya!!! :)

Installation and Configuration Nginx as Reverse Proxy for Apache on Ubuntu Server

Installation and Configuration Nginx as Reverse Proxy for Apache on Ubuntu Server

In this article, I will show you how to install and configure Nginx as a caching reverse proxy for an Apache web server on Ubuntu, Nginx is used as the front-end and Apache as the back-end.

Nginx will run on port 80 to respond to requests from user/browser, the request will be forwarded to the Apache server that is running on port 7070.

Apache

Install Apache & PHP
Log into your ubuntu server with SSH and switch to root user by running:

1
sudo su

Then install apache with the apt-get command:

1
apt-get install apache2

Once apache is installed, we must install PHP as apache module for this tutorial:

1
apt-get install php5 php5-mysql libapache2-mod-php5

Configure Apache and PHP
By default, apache listens on port 80. We have to configure apache to run on port 7070 for our proxy setup as port 80 will be used by nginx later.

If you want to change the port for apache web server, you must edit the apache configuration file /etc/apache2/ports.conf, and then proceed with the virtual host configuration in the /etc/apache2/sites-available/ directory.

First change the Apache port to 7070 by editing the file ports.conf with the vim editor:

1
vim /etc/apache2/ports.conf

And then change port 80 to 7070:

ports.conf
1
Listen 7070

And then save and exit.

And now go to the virtualhost directory and edit the file 000-default.conf:

1
vim /etc/apache2/sites-available/000-default.conf

And then make sure your configuration is same as below:

000-default.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<VirtualHost *:7070>
  ServerName www.reverse.com
  ServerAlias reverse.com

  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html/geekhmer-dev

  <Directory "/var/www/html/geekhmer-dev">
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/geekhmer-dev_error.log
  CustomLog ${APACHE_LOG_DIR}/geekhmer-dev_access.log combined
</VirtualHost>

And then save and exit.

Next test the configuration and restart apache:

1
2
3
apachectl configtest

systemctl restart apache2

Then we verify that the apache and php is working by creating a new file with the name info.php in the directory /var/www/html/.

1
echo "<?php phpinfo(); ?>" > /var/www/html/info.php

Visit your site www.reverse.com:7070/info.php.

Nginx

Install Nginx
Let install Nginx with the following apt-get command:

1
apt-get install nginx

Configure Nginx
Once Nginx is installed, configure Nginx to act as reverse proxy for the apache web server that running on port 7070.

Go to the nginx configuration directory and edit the file nginx.conf:

1
vim /etc/nginx/nginx.conf

And then enable Gzip compression for Nginx by uncomment the gzip lines below:

nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/    javascript;

The most important is:
- gzip on : to turn gzip compression.
- gzip_types : is list of MIME-types which you want to turn the compression.
- gzip_proxied any : is enable compression for proxied request.

Under gzip settings, add these proxy cache settings:

nginx.conf
1
2
3
4
##
# Proxy Cache Settings
##
proxy_cache_path /var/cache levels=1:2 keys_zone=reverse_cache:60m inactive=90m max_size=1000m;

The important is:
- The directory for the proxy cache is /var/cache.
- levels : is a directive that tells Nginx how the cache is saved in file system.
- key_zone : is just a name of the cache zone, you can choose it freely, but don’t add special chars or whitespace in the name. I will use the name “reverse_cache” here.

And then save and exit.

And then we will configure proxy params in /etc/nginx/proxy_params file for using in virtualhost later.

1
vim /etc/nginx/proxy_params

Paste the configuration below:

proxy_params
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;

##
# Cache configuration
##
proxy_cache reverse_cache;
proxy_cache_valid 3s;
proxy_no_cache $cookie_PHPSESSID;
proxy_cache_bypass $cookie_PHPSESSID;
proxy_cache_key "$scheme$host$request_uri";
add_header X-Cache $upstream_cache_status;

And then save and exit.

Now we will configure a virtualhost in the directory /etc/nginx/sites-available. And I will create a new virtualhost configuration file named reverse.conf. Just got to the directory and create new file with vim:

1
vim /etc/nginx/sites-available/reverse.conf

Paste the configuration below:

reverse.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
server {
  listen 80;

  # Site Directory same in the apache virtualhost configuration
  root /var/www/html/geekhmer_dev;
  index index.php index.html index.htm;

  # Domain
  server_name www.reverse.com reverse.com;

  location / {
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_pass http://127.0.0.1:7070;
    include /etc/nginx/proxy_params;
  }

  location ~* \.php$ {
    proxy_pass http://127.0.0.1:7070;
    include /etc/nginx/proxy_params;
  }

  # Enable Cache the file 30 days
  location ~* .(jpg|png|gif|jpeg|css|mp3|wav|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx|css|js)$ {
    proxy_cache_valid 200 120m;
    # expires max;
    expires 30d;
    proxy_cache reverse_cache;
    access_log off;
  }

  # Disable Cache for the file type html, json
  location ~* .(?:manifest|appcache|html?|xml|json)$ {
    expires -1;
  }

  location ~ /\.ht {
    deny all;
  }
}

And then save and exit.

And then activate the new virtualhost configuration:

1
ln -s /etc/nginx/sites-available/reverse.conf /etc/nginx/sites-enabled/

And then we will test the nginx configuration and restart nginx:

1
2
3
nginx -t

systemctl restart nginx

Nginx is configured as reverse proxy now. You can test it with curl:

1
2
3
curl -I www.reverse.com

curl -I www.reverse.com/info.php

Configure Logging

I will configure apache to log the real ip of the visitor instead of the local IP.

Let go to install the apache module libapache2-mod-rpaf and edit the module configuration file:

1
2
3
apt-get install libapache2-mod-rpaf

vim /etc/apache2/mods-available/rpaf.conf

Add the server IP to the line 10. My server IP is: 192.168.1.117.

rpaf.conf
1
RPAFproxy_ips 127.0.0.1 192.168.1.117 ::1

And then save and exit.

And then restart apache:

1
systemctl restart apache2

Test rpaf by viewing the apache access log with the tail command:

1
tail -f /var/log/apache2/geekhmer-dev_access.log

Nginx is installed as reverse proxy in front of the Apache web server. If a visitor requests a php file, the request will be passed to apache on port 7070, and you can see the real IP visitor on the apache log file.

Conclusion

Nginx is fast and popular web server with low memory usage that can act as web server and reverse proxy for HTTP and HTTPS protocol. Nginx reverse proxy for apache is a setup that uses Nginx as front-end, and apache as back-end. Nginx handles the incoming request from the browser and passes it to the apache back-end. In this article, we have setup a configuration for nginx as http cache that caches PHP file requests and images.

Simple Sales Framework for “Sell Me This Pen”

Sell me this pen

I personally never thought anyone would say, “Sell me this pen” in a sales interview. I was wrong. It will happen to you. And you should know exactly what to say back.

I will give you the right sales framework to respond perfectly every time. One day it will happen to you and I want you prepare the script as below:

Here we go:

Interviewer: Do me a favor, sell me this pen. (reaches across to hand me the pen)

Me: (I slowly roll the pen between my index and thumb fingers.) When was the last time you used a pen?

Interviewer: This morning.

Me: Do you remember what kind of pen that was?

Interviewer: No.

Me: Do you remember why you were using it to write?

Interviewer: Yes. Signing a few new customer contracts.

Me: Well I’d say that’s the best use for a pen.

Would not you say signing those new customer contracts is an important event for the business? Then you shouldn’t treate like this. What I mean is, here you are signing new customer contracts, an important and memorable event with a very unmemorable pen.

This is the pen for more important events. This is the tool you use to get deals done. Think of it as a symbol for taking your company to the next level. Because when you begin using the right tool, you are in a more productive state of mind, and you begin to sign more new customer contracts.

Actually. You know? Just this week I shipped ten new boxes of these pens to many office in Phnom Penh.

Unfortunately, this is my last pen today. So, I suggest you get this one. Try it out. If you are not happy with it, I will personally come back next week to pick it up. And it won’t cost you a dime. What do you say?

Interviewer: Yes.

See how simple that was. The Interviewer/Customer loved it. Why?

Here’s the Simple Sales Framework for “Sell me this pen”
1. Gather info - Find out how they last used a pen
2. Respond to info - Emphasize the importance of the activity they last used a pen
3. Delivery info - Sell something bigger than a pen, like a state of mind
4. Closing - Ask for the buy

So far so good, remember it’s not about actually selling a pen. It’s about showing how well you can sell a product. Take 15 minutes today to practice the script above. I promise you will benefit. Share this with person in sales. It could save their career lolzzZ. See ya!

Why Is Website Maintenance Important?

Why Is Website Maintenance Important?

I saw it many times a company has a website delivered, with no changes, no additions, no fresh content and most important of all is no security updates. The website stays as it was delivered, sometimes for many years.

You truly ask yourself: “If I like the design and the website just works, why would I need to be maintained?”. Please go through with me and read on to learn why maintenance is very important:

SECURITY
Probably the most important thing is: keep your site safe! Website software (Content Management Systems, plug-ins and other add-ons to the website’s functionality) are constantly updated. Partly to improve how it works or to add something new and handy, but often also to patch security holes.

Hackers are constantly looking for outdated websites or software (and known security holes). If you don’t keep up with the latest version of the software, your website could be at risk.

ATTRACTIVENESS
A website that is regularly updated with fresh content (blog posts, news articles, promotions, new products, etc.) attracts more visitors. And isn’t that what you want to achieve with your website: attracting visitors? Visitors get a bad impression if there is old data on your website.

Regularly create the new content, text, or images that relate to your business to attract both new and returning visits.

GOOGLE RANKING
Google loves websites that are regularly updated. Keeping your products and services up-to-date shows search engines that your site is fresh. A site with copyright on the bottom and the “Latest News” article years out of date will not be as attractive to Google in terms of quality or usefulness. When new content is added on a regular basis, Google values this and takes that into account with the overall ranking of your website.

Google itself provides a useful tool called “Webmaster Tools” which essentially checks the ‘health’ of your website.

YOUR CORPORATE IMAGE
Your website is an interface into your business and it can have a big impact on how visitors value your products or services. Your website should be kept relevant by regularly refreshing content. Also regularly check that contact forms work, addresses and phone numbers are updated and products, services and price lists are current and correct. This means visitors find what they are looking for quickly and easily, and are more likely to become customers.

Can you do maintenance yourself?
Of course you can. The websites with Content Management Systems (like WordPress) that make it very easy to add or update content yourself. However, ask yourself: will you really do that? Will you really dedicate time every week or month to update your website’s content? And maintain those regular updates year after year? Or do you rather concentrate on your business instead of maintaining your website?

Additionally there is one thing that’s not easy for non-technical people to do software updates. An update to your website’s software can easily break your website. Because (part of) a software is not compatible with another application.

So far so good, let technical people do website maintenance for your business to professionals.

Online Payment Gateway in Cambodia

Online Payment Gateway in Cambodia

The amount of shops in Cambodia wanna sell product and service online is growing. But you truly don’t know which Online Payment Gateway you consider to choose for implement and do integration right?

The good news is here, take it easy I will do a presentaion for you, let go through with me:

PayPal
PayPal is by far the easiest method to receive online payments made by credit card or via PayPal itself. However, the company has no relations with any bank in Cambodia.

So it’s not possible right? Well, the only possibility is to have a bank account in another country linked to your PayPal account.

Cathay United Bank
Cathay United Bank (formerly SBC Bank) in Cambodia offers an online payment gateway, which is rather easy to implement.

Of course, you need an account with the bank and Cathay United charges a percentage fee for this service. It only can handle credit cards of MasterCard, JCB and VISA, which is a bit limited.

ACLEDA Bank
As a well respected bank, ACLEDA is a bit late to the party, only announcing recently their E-Commerce Payment Gateway.

ACLEDA uses the same MasterCard Internet Gateway Service (MiGS) as Cathay United Bank, so this is just as easy to set up on your website.

WING
WING is primarily a phone-to-phone payment service and very popular among Cambodians. They can send and receive money nationwide, the company has a large network of agents and also offers a solution for online payments. The only thing you have to do is open a free business account. Once that’s done you’ll get instructions on how to implement it on your website to receive online payments in your Wing account. This service is only available for customers within Cambodia.

PayGo
PayGo is a service provided by ABA Bank. To use the service, customers first have to sign up using a mobile phone number. This only works for Cambodian phone numbers, so not suitable for international customers. Although it is convenient for customers in Cambodia, we have some doubts about the security of this system. Only using a phone number as a check seems not very secure.

My suggestion for you is that:

Due PayPal not yet entered in Cambodian market, the services offered by Cathay United Bank and ACLEDA Bank seem the most robust, secure and comparatively easy to implement.

And if you only or primarily target customers within Cambodia, WING and PayGo can be an alternative.

So far so good, That’s it!!! See ya!!! :)

Generating Income on the Internet Using Social Media

Generating Income on the Internet Using Social Media

Once it comes to generating income on the Internet using social media, there are a few principles which you need to understand.

1. INTRODUCE YOURSELF
The first thing you need to know is how to introduce yourself, whether video or article platform.

People are busy, you need to think of how you can introduce yourself in under 15 seconds. Get to the right point.

Take sometime to come up with a way to do it, and remember the words you used because you’ll need to do it the same way every time you introduce yourself on the same platform.

As well, keep in mind that among the people who log into your scope, some might not have heard of you before, so you need to not just introduce yourself quickly, but you need to be able to capture and hold their attention/interest.

Within that 15 seconds of your introduction, you need to be able to make people understand who you are and what you do.

2. HAVE A PRODUCT TO PROMOTE
The second thing that you will need to have is a product to promote.

There are two ways for you to do this:
- Promote your own product for 100% of the profit
- Promote someone else’s product for a commission

You decide – you could sell a product on Amazon, Alibabaor or sell a product yourself on your own website or mobile platform.

You must have a product!

3. HAVE A CALL TO ACTION
The third thing you need is a call to action – What is “A call to action”? It mean that you must tell people what to do next.

If you don’t have a call to action, then no action will be taken.

At the end of the scope tell people that:

“If you like what you have just known, head over or go through to my website.”

Or you could tell them: “If you liked this scope, please follow me on twitter, facebook page… and join me for the next one.”

Every time you present, you must always have a call to action.

So these are the three things that you want to have to really master and get thousands of people to your social media. So far so good, That’s it!!! See ya!!! :)

Copy to Clipboard Without Flash With Clipboard.js

Copy to Clipboard without Flash with Clipboard.js

Well, in this article I gonna show you how to easily implement the ability to copy data to the clipboard. In order to implement it I will clipboard.js javascript library, let get started with me:

Installation

The first thing I need to do is include the clipboard.js library file in head tag of the application:

1
<script src="https://cdn.jsdelivr.net/clipboard.js/1.5.12/clipboard.min.js"></script>

If you don’t wish to use a CDN, you can download the clipboard in other ways:
- Using npm, by running npm install clipboard --save
- Using bower, by running bower install clipboard --save
- By downloading a zip file from the clipboard.js github page and referencing it in your HTML.

Usage

Copy text from another element: A pretty common use case is to copy content from another element. You can do that by adding a data-clipboard-target attribute in your trigger element. The value you include on this attribute needs to match another’s element selector.

1
2
3
4
5
6
7
<!-- Target -->
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git">

<!-- Trigger -->
<button class="btn" data-clipboard-target="#foo">
    <img src="assets/clippy.svg" alt="Copy to clipboard">
</button>

Cut text from another element: Additionally, you can define a data-clipboard-action attribute to specify if you want to either copy or cut content. If you omit this attribute, copy will be used by default.

1
2
3
4
5
6
7
<!-- Target -->
<textarea id="bar">Mussum ipsum cacilds...</textarea>

<!-- Trigger -->
<button class="btn" data-clipboard-action="cut" data-clipboard-target="#bar">
    Cut to clipboard
</button>

As you may expect, the cut action only works on input or textarea elements.

Copy text from attribute: Truth is, you don’t even need another element to copy its content from. You can just include a data-clipboard-text attribute in your trigger element.

1
2
3
4
<!-- Trigger -->
<button class="btn" data-clipboard-text="Just because you can doesn't mean you should — clipboard.js">
    Copy to clipboard
</button>

Events

There are cases where you’d like to show some user feedback or capture what has been selected after a copy/cut operation.

That’s why we fire custom events such as success and error for you to listen and implement your custom logic.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var clipboard = new Clipboard('.btn');

clipboard.on('success', function(e) {
  console.info('Action:', e.action);
  console.info('Text:', e.text);
  console.info('Trigger:', e.trigger);

  e.clearSelection();
});

clipboard.on('error', function(e) {
  console.error('Action:', e.action);
  console.error('Trigger:', e.trigger);
});

So far so good, That’s it!!! See ya!!! :)

HTTP Status Code and Symbols

HTTP Status Code and Symbols

Thanks to Cody Fauser for this list of HTTP responce codes and their Ruby on Rails or other Framework symbol mappings. Let go through the status code symbol below:

1xx Informational
100 :continue
101 :switching_protocols
102 :processing

2xx Success
200 :ok
201 :created
202 :accepted
203 :non_authoritative_information
204 :no_content
205 :reset_content
206 :partial_content
207 :multi_status
226 :im_used

3xx Redirection
300 :multiple_choices
301 :moved_permanently
302 :found
303 :see_other
304 :not_modified
305 :use_proxy
307 :temporary_redirect

4xx Client Error
400 :bad_request
401 :unauthorized
402 :payment_required
403 :forbidden
404 :not_found
405 :method_not_allowed
406 :not_acceptable
407 :proxy_authentication_required
408 :request_timeout
409 :conflict
410 :gone
411 :length_required
412 :precondition_failed
413 :request_entity_too_large
414 :request_uri_too_long
415 :unsupported_media_type
416 :requested_range_not_satisfiable
417 :expectation_failed
422 :unprocessable_entity
423 :locked
424 :failed_dependency
426 :upgrade_required

5xx Server Error
500 :internal_server_error
501 :not_implemented
502 :bad_gateway
503 :service_unavailable
504 :gateway_timeout
505 :http_version_not_supported
507 :insufficient_storage
510 :not_extended

So far so good, That’s it!!! See ya!!! :)

Why I Do Combining Apache and Nginx Together?

Why I do combining apache and nginx together?

Nginx and apache are powerful and effective servers by nowadays. Apache currently reigns as the number 1 server for websites and since its public release in 2006. And nginx has taken the world by storm and is now the number 2 server for active sites.

The Reason Why I Use Nginx and Apache Together is

Nginx
- nginx serves static files (images, css, html etc.) really fast and efficient and passes php and .htaccess requests to apache for processing.
- nginx needs the help of php-fpm or similar modules for dynamic content.

Apache
- apache is hard on server memory.
- apache serves php and .htaccess (most cms site like wordpress needs it for rewrite) and if you throw in a php opcode cache like zend opcache or xcache it should serve php even faster.

nginx + apache with php opcache = performance and server resource efficiency

So far so good, in the next article I will show you the configurations. That’s it!!! See ya!!! :)

Create Content With Multiple Features With CKEditor Gem

Create content with multiple features with CKEditor Gem

Setup & Usage
First, we need to add the CKEditor gem to our Gemfile. Open up your Gemfile and add the line listed below:

Gemfile
1
gem "ckeditor"

Next, open up the terminal and run a bundle install to install the gem:

1
bundle install

Great, now lets create a sample model and accompanying controller that will be used to store our data. Open up and run the command below to create the Magazine model and migrate the database:

1
2
rails g resource Magazine title body:text
rake db:migrate

Now, open your routes file and add the following line to your routes:

routes.rb
1
root to: "magazines#index"

Now, lets add the CKEditor javascript include to our application.js. Modify your application.js file so that it looks like the code listed below:

application.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require ckeditor/init
//= require turbolinks
//= require_tree .

Great, now we need to add some code to the magazines controller. Add the following code to the magazines controller:

magazines_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class MagazinesController < ApplicationController
  def index
    @magazines = Magazine.order("created_at DESC")
  end

  def show
    @magazine = Magazine.find(params[:id])
  end

  def new
    @magazine = Magazine.new
  end

  def create
    @magazine = Magazine.new(magazine_params)
    if @magazine.save
      redirect_to magazines_path, notice: "The magazines has been successfully created."
    else
      render action: "new"
    end
  end

  def edit
    @magazine = Magazine.find(params[:id])
  end

  def update
    @magazine = Magazine.find(params[:id])
    if @magazine.update_attributes(magazine_params)
      redirect_to magazines_path, notice: "The magazine has been successfully updated."
    else
      render action: "edit"
    end
  end

  private
  def magazine_params
    params.require(:magazine).permit(:title, :body)
  end
end

This code enables the ability to read, write, and update the magazines in our example. Now for the views, first lets create the index view:

index.html.erb
1
2
3
4
5
6
7
8
9
<%= link_to "New Magazine", new_magazine_path %>
<% @magazines.each do |magazine| %>
  <h3><%= magazine.title.html_safe %></h3>
  <p><%= magazine.body.html_safe %></p>
  <%= link_to "Edit Magazine", edit_magazine_path(magazine) %>
  <% if magazine != @magazines.last %>
  <hr />
  <% end %>
<% end %>

Now, lets create a partial to store the form. Create a file called app/views/_form.html.erb and add the code listed below:

_form.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<% if @magazine.errors.any? %>
  <ul>
    <%= @magazine.errors.full_messages.each do |message| %>
        <li><%= message %></li>
    <% end %>
  </ul>
<% end %>
<%= form_for @magazine do |f| %>
  <div>
    <%= f.label :title %>
  </div>
  <div>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.label :body %>
  </div>
  <div>
    <%= f.cktext_area :body, rows: 10 %>
  </div>
  <div>
    <%= f.submit %>
  </div>
<% end %>

Now, lets create the new view. Create the app/views/magazines/new.html.erb file and add the code listed below:

new.html.erb
1
2
<h3> New Magazine</h3>
<%= render "form" %>

Now, if you visit the new magazines page on your development server you will see that CKEditor appears.

Next lets create the edit view. Create the app/views/magazines/edit.html.erb file and add the code listed below:

edit.html.erb
1
2
<%= "Editing #{@magazine.title}" %>
<%= render "form" %>

Great, now when you click ‘edit magazine’ on any magazine, it will show the CKEditor for editing.

Images Using Paperclip
In order to integrate images via paperclip, a few more steps are required. Note that you must have ImageMagick installed for this to work. First, lets include the paperclip gem:

Gemfile
1
gem "paperclip"

Next, we need to run a generator provided by ckeditor. This generator will create the necessary models that will be used to store image data. Run the command below:

1
2
rails generate ckeditor:install --orm=active_record --backend=paperclip
rake db:migrate

So far so good, if you restart your rails server and refresh the page, you will be able to click the images button, upload an image, and insert it into your articles.