This gist will collects all issues we solved with Rails 5.2 and Webpacker
# Last few parameters(--skip-* part) is only my habbit not actully required
$ rails new <project_name> --webpack=stimulus --database=postgresql --skip-coffee --skip-test
$ cd <project_name>
$ rails db:create
$ rails g migration enable_hstore_extension
# db/migrate/<TIMESTAMP>_enable_hstore_extension.rb
class EnableHstoreExtension < ActiveRecord::Migration[5.2]
def change
enable_extension 'hstore'
end
end
$ rails g migration enable_uuid_extension
# db/migrate/<TIMESTAMP>_enable_uuid_extension.rb
class EnableUuidExtension < ActiveRecord::Migration[5.2]
def change
enable_extension 'uuid-ossp'
enable_extension 'pgcrypto'
end
end
# lib/templates/active_record/model/model.rb
<% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %>
# scope macros
# Concerns macros
# Constants
# Attributes related macros
<% if attributes.any?(&:password_digest?) -%>
has_secure_password
<% end -%>
# association macros
<% attributes.select(&:reference?).each do |attribute| -%>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
<% end -%>
# validation macros
# callbacks
# other
private
# callback methods
end
<% end -%>
If you are using some front end framework you may like to integrate stylesheet into components with webpack or you just like to integrate stylesheets with webapck like me. This is a way that we integrate that into webpacker.
NOTE: This is only the convention of our team you can avoid this step and keep stylesheet in assets/.
$ mkdir app/javascript/stylesheets
$ touch app/javascript/stylesheets/application.scss
$ touch app/javascript/stylesheets/_variables.scss
$ touch app/javascript/stylesheets/_base.scss
After create files please write down styles as follow:
app/javascript/stylesheets/application.scss
@import 'variables';
@import 'base';
app/javascript/stylesheets/_variables.scss
$colors: (
major: #00D252,
minor: #2F3B59
);
app/javascript/stylesheets/_base.scss
h1 {
color: map-get($colors, major);
}
On the top of app/javascript/packs/application.js
import 'stylesheets/application'
If you are not use --webpack=stimulus
for create project or install stimulus
in existed project.
$ yarn add stimulus
$ mkdir app/javascript/controllers
# To provide a example for testing stimulus
$ touch app/javascript/controllers/clipboard_controller.js
app/javascript/s/packs/application.js
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
import 'stylesheets/application'
import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"
const application = Application.start()
// The path you may like to change to under `pack` that path will be `./controllers`
// but convention will be in `/app/javascript/controllers`
const context = require.context("controllers", true, /\.js$/)
application.load(definitionsFromContext(context))
Example of testing stimulus
:
app/javascript/controllers/clipboard_controller.js
import { Controller } from 'stimulus'
export default class extends Controller {
static targets = ['source']
initialize() {
console.log('clipboard initialize')
}
connect() {
console.log('clipboard connect')
if (document.queryCommandSupported('copy')) {
this.element.classList.add('clipboard--supported')
}
}
copy(e) {
e.preventDefault()
this.sourceTarget.select()
document.execCommand('copy')
}
}
$ rails g controller pages example
Add app/views/pages/example.html.erb
<h1>Hello, World</h1>
<hr>
<div data-controller="clipboard members dashboard">
PIN
<input type="text" data-target="clipboard.source" value="1234" readonly>
<button data-action="clipboard#copy" class="clipboard-button">
Copy to Clipboard
</button>
</div>
Open app/views/layout/application.html.erb then add pack tags
to <head>
<%= stylesheet_pack_tag 'application' %>
<%= javascript_pack_tag 'application' %>
config/routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'pages#example'
end
Then you can test
$ rails s
Navigate to localhost:3000
should see as follow
Until here you should complete Rails 5.2 using webpacker with stimulus and stylesheets.
For common practical stiuation you may want to use bootstrap v4.x.
# https://getbootstrap.com/docs/4.1/getting-started/webpack/
$ yarn add jquery popper.js bootstrap
In app/javascript/stylesheets/application.scss add bootstrap
@import '~bootstrap/scss/bootstrap';
@import 'variables';
@import 'base';
app/javascript/packs/application.js
import 'bootstrap'
Add configuration to config/webpack/environment.js. If you do not setup this step, the abilities related to Popper.js
such as tooltip
will not working.
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
/**
* Automatically load modules instead of having to import or require them everywhere.
* Support by webpack. To get more information:
*
* https://webpack.js.org/plugins/provide-plugin/
* http://j.mp/2JzG1Dm
*/
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
})
)
module.exports = environment
Sometimes you may like to use jQuery in views you should expose jQuery to global
# https://webpack.js.org/loaders/expose-loader/
$ yarn add expose-loader -D
# NOTICE: For some production environment you may ignore `-D`
Add configuration to config/webpack/environment.js
/**
* To use jQuery in views
*/
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: '$'
}]
})
$ mkdir -p lib/templates/active_record/model
$ touch lib/templates/active_record/model/model.rb
lib/templates/active_record/model/model.rb
<% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %>
# scope macros
# Concerns macros
# Constants
# Attributes related macros
<% if attributes.any?(&:password_digest?) -%>
has_secure_password
<% end -%>
# association macros
<% attributes.select(&:reference?).each do |attribute| -%>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
<% end -%>
# validation macros
# callbacks
# other
private
# callback methods
end
<% end -%>
First of all, thanks and @pjforde1978 is right. I haven't use Rails 6 in my products yet so I don't exactly know.