superglue 0.40.0 → 0.50.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a72d44f915a1102e37b882a5492a0bae8427c68715acf5a59a809fc70cd47aba
4
- data.tar.gz: 00cb36e39bbc5d47001c3c6ad9a588204e5ccf27deabbce41ddae66a1ba83ac5
3
+ metadata.gz: 44a42cb747cff210dd1550dae3f9ddf280e72a2b38ff26b72fa5f2eea2eeadfe
4
+ data.tar.gz: f52f207c4be16d576a51c09f0e821c08d9af68b8150bf52d5b007f59e912d936
5
5
  SHA512:
6
- metadata.gz: dfa4b3fc28f855eca34ff1533050afd0abf800d7106ffdac25ee44e051e530546990138cae9b33b78526264a9235692a0f878011ea46da84baef8a4278f49280
7
- data.tar.gz: a2198132a6bf2d004745ddb1be7b49de05a21571dd55b507c0d8f09928b06771ebcefb25271b9d84ff9f88303e3f359fea9f6c197ff40db907eb3bf65e75620f
6
+ metadata.gz: 57a0e0bbfd2fdcc815af7922f3b97042d016fe6f68be3389a83bcb77a5de2e1e68423a172878482533f25b69464c09d0395a116c4e8179a48ffce1d7a681dcd7
7
+ data.tar.gz: d8f034124031b598ee70394fd4900e4daab38126458db85f25afb96e9074bb07196d1f01e9975e960768676da469772d7be044ca3ce0915de95f2e129fdc78d7
@@ -1,10 +1,10 @@
1
- require 'rails/generators'
2
- require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
1
+ require "rails/generators"
2
+ require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
3
3
 
4
4
  module Rails
5
5
  module Generators
6
6
  class ScaffoldControllerGenerator
7
- source_paths << File.expand_path('../templates', __FILE__)
7
+ source_paths << File.expand_path("../templates", __FILE__)
8
8
 
9
9
  hook_for :superglue, type: :boolean, default: true
10
10
  end
@@ -1,92 +1,98 @@
1
- require 'rails/generators/named_base'
2
- require 'rails/generators/resource_helpers'
1
+ require "rails/generators/named_base"
2
+ require "rails/generators/resource_helpers"
3
3
 
4
4
  module Rails
5
5
  module Generators
6
- class SuperglueGenerator < NamedBase # :nodoc:
6
+ class SuperglueGenerator < NamedBase
7
7
  include Rails::Generators::ResourceHelpers
8
8
 
9
- source_root File.expand_path('../templates', __FILE__)
9
+ source_root File.expand_path("../templates", __FILE__)
10
10
 
11
- argument :attributes, type: :array, default: [], banner: 'field:type field:type'
11
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
12
12
 
13
13
  def create_root_folder
14
- path = File.join('app/views', controller_file_path)
14
+ path = File.join("app/views", controller_file_path)
15
15
  empty_directory path unless File.directory?(path)
16
16
  end
17
17
 
18
18
  def copy_view_files
19
- %w(index show new edit).each do |view|
19
+ %w[index show new edit].each do |view|
20
20
  @action_name = view
21
21
  filename = filename_with_extensions(view)
22
- template filename, File.join('app/views', controller_file_path, filename)
22
+ template filename, File.join("app/views", controller_file_path, filename)
23
23
  end
24
- template '_form.json.props', File.join('app/views', controller_file_path, '_form.json.props')
24
+ template "_form.json.props", File.join("app/views", controller_file_path, "_form.json.props")
25
25
 
26
- %w(index show new edit).each do |view|
26
+ %w[index show new edit].each do |view|
27
27
  @action_name = view
28
28
  filename = filename_with_js_extensions(view)
29
- template 'web/' + filename, File.join('app/views', controller_file_path, filename)
29
+ template "web/" + filename, File.join("app/views", controller_file_path, filename)
30
30
  end
31
31
 
32
- %w(index show new edit).each do |view|
32
+ %w[index show new edit].each do |view|
33
33
  @action_name = view
34
34
  filename = filename_with_html_extensions(view)
35
- template 'web/' + filename, File.join('app/views', controller_file_path, filename)
35
+ template "web/" + filename, File.join("app/views", controller_file_path, filename)
36
36
  end
37
37
 
38
- %w(index show new edit).each do |view|
38
+ %w[index show new edit].each do |view|
39
39
  append_mapping(view)
40
40
  end
41
41
  end
42
42
 
43
-
44
43
  protected
45
- def append_mapping(action)
46
- app_js = 'app/javascript/packs/application.js'
47
44
 
48
- component_name = [plural_table_name, action].map(&:camelcase).join
45
+ def view_path
46
+ "../views"
47
+ end
49
48
 
50
- inject_into_file app_js, after: "from '@thoughtbot/superglue'" do
51
- "\nimport #{component_name} from 'views/#{controller_file_path}/#{action}'"
52
- end
49
+ def app_js_path
50
+ "app/javascript/"
51
+ end
53
52
 
54
- inject_into_file app_js, after: 'identifierToComponentMapping = {' do
55
- "\n '#{[controller_file_path, action].join('/')}': #{component_name},"
56
- end
57
- end
53
+ def append_mapping(action)
54
+ app_js = "#{app_js_path}/page_to_page_mapping.js"
58
55
 
59
- def action_name
60
- @action_name
61
- end
56
+ component_name = [plural_table_name, action].map(&:camelcase).join
62
57
 
63
- def attributes_names
64
- [:id] + super
58
+ prepend_to_file app_js do
59
+ "\nimport #{component_name} from '#{view_path}/#{controller_file_path}/#{action}'"
65
60
  end
66
61
 
67
- def filename_with_extensions(name)
68
- [name, :json, :props] * '.'
62
+ inject_into_file app_js, after: "pageIdentifierToPageComponent = {" do
63
+ "\n '#{[controller_file_path, action].join("/")}': #{component_name},"
69
64
  end
65
+ end
70
66
 
71
- def filename_with_js_extensions(name)
72
- [name, :js] * '.'
73
- end
67
+ attr_reader :action_name
74
68
 
75
- def filename_with_html_extensions(name)
76
- [name, :html, :erb] * '.'
77
- end
69
+ def attributes_names
70
+ [:id] + super
71
+ end
78
72
 
79
- def attributes_list_with_timestamps
80
- attributes_list(attributes_names + %w(created_at updated_at))
81
- end
73
+ def filename_with_extensions(name)
74
+ [name, :json, :props].join(".")
75
+ end
82
76
 
83
- def attributes_list(attributes = attributes_names)
84
- if self.attributes.any? {|attr| attr.name == 'password' && attr.type == :digest}
85
- attributes = attributes.reject {|name| %w(password password_confirmation).include? name}
86
- end
77
+ def filename_with_js_extensions(name)
78
+ [name, :js].join(".")
79
+ end
80
+
81
+ def filename_with_html_extensions(name)
82
+ [name, :html, :erb].join(".")
83
+ end
87
84
 
88
- attributes
85
+ def attributes_list_with_timestamps
86
+ attributes_list(attributes_names + %w[created_at updated_at])
87
+ end
88
+
89
+ def attributes_list(attributes = attributes_names)
90
+ if self.attributes.any? { |attr| attr.name == "password" && attr.type == :digest }
91
+ attributes = attributes.reject { |name| %w[password password_confirmation].include? name }
89
92
  end
93
+
94
+ attributes
95
+ end
90
96
  end
91
97
  end
92
98
  end
@@ -1,13 +1,6 @@
1
- html = form_with(model: @<%= model_resource_name %>, local: true) do |form|
2
- inner = "".html_safe
3
-
1
+ form_props(model: @<%= model_resource_name %>) do |f|
4
2
  <%- attributes.each do |attr| -%>
5
- inner << form.label(:<%= attr.column_name %>)
6
- inner << form.<%= attr.field_type %>(:<%= attr.column_name %>)
3
+ f.<%= attr.field_type %>(:<%= attr.column_name %>)
7
4
  <%- end -%>
8
- inner << form.submit
9
-
10
- inner
5
+ f.submit
11
6
  end
12
-
13
- json.html html
@@ -5,7 +5,9 @@ json.<%= plural_table_name %> do
5
5
  <%- end -%>
6
6
  json.edit_<%=singular_table_name%>_path edit_<%=singular_table_name%>_path(<%=singular_table_name%>)
7
7
  json.<%=singular_table_name%>_path <%=singular_table_name%>_path(<%=singular_table_name%>)
8
- json.delete_<%=singular_table_name%>_path <%=singular_table_name%>_path(<%=singular_table_name%>)
8
+ json.delete_form do
9
+ form_props(model: <%=singular_table_name%>, method: :delete)
10
+ end
9
11
  end
10
12
  end
11
13
 
@@ -1,5 +1,4 @@
1
1
  import React from 'react'
2
- import RailsTag from '@thoughtbot/superglue/components/RailsTag'
3
2
  // import * as actionCreators from 'javascript/packs/action_creators'
4
3
  // import {useDispatch} from 'react-redux'
5
4
 
@@ -23,7 +22,15 @@ export default function <%= plural_table_name.camelize %>Edit ({
23
22
  return (
24
23
  <div>
25
24
  {messagesEl}
26
- <RailsTag {...form} data-sg-visit={true}/>
25
+ <form {...form.props} data-sg-visit={true}>
26
+ {Object.values(form.extras).map((hiddenProps) => (<input {...hiddenProps} key={hiddenProps.id} type="hidden"/>))}
27
+ <%- attributes.each do |attr| -%>
28
+ <input {...form.inputs.<%= attr.column_name %>} type="text"/>
29
+ <label htmlFor={form.inputs.<%= attr.column_name %>.id}><%= attr.column_name %></label>
30
+ <%- end -%>
31
+ <button {...form.inputs.submit} type="submit"> {...form.inputs.submit.text} </button>
32
+ </form>
33
+
27
34
  <a href={<%= singular_table_name.camelize(:lower) %>Path} data-sg-visit={true}>Show</a>
28
35
  <a href={<%= plural_table_name.camelize(:lower) %>Path} data-sg-visit={true}>Back</a>
29
36
  </div>
@@ -10,6 +10,8 @@ export default function <%= plural_table_name.camelize %>Index({
10
10
  <%= plural_table_name.camelize(:lower) %> = [],
11
11
  }) {
12
12
  const <%= singular_table_name.camelize(:lower) %>Items = <%= plural_table_name.camelize(:lower) %>.map((<%= singular_table_name.camelize(:lower) %>, key) => {
13
+ const deleteForm = <%=singular_table_name.camelize(:lower)%>.deleteForm;
14
+
13
15
  return (
14
16
  <tr key={<%= singular_table_name.camelize(:lower) %>.id}>
15
17
  <%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
@@ -17,7 +19,12 @@ export default function <%= plural_table_name.camelize %>Index({
17
19
  <%- end -%>
18
20
  <td><a href={ <%=singular_table_name%>.<%=singular_table_name.camelize(:lower)%>Path } data-sg-visit={true}>Show</a></td>
19
21
  <td><a href={ <%=singular_table_name%>.edit<%=singular_table_name.camelize%>Path } data-sg-visit={true}>Edit</a></td>
20
- <td><a href={ <%=singular_table_name%>.delete<%=singular_table_name.camelize%>Path }data-sg-visit={true} data-sg-method={"DELETE"}>Delete</a></td>
22
+ <td>
23
+ <form {...deleteForm.props} data-sg-visit={true}>
24
+ {Object.values(deleteForm.extras).map((hiddenProps) => (<input {...hiddenProps} key={hiddenProps.id} type="hidden"/>))}
25
+ <button type="submit">Delete</button>
26
+ </form>
27
+ </td>
21
28
  </tr>
22
29
  )
23
30
  })
@@ -1,5 +1,4 @@
1
1
  import React from 'react'
2
- import RailsTag from '@thoughtbot/superglue/components/RailsTag'
3
2
  // import * as actionCreators from 'javascript/packs/action_creators'
4
3
  // import { useDispatch } from 'react-redux'
5
4
 
@@ -22,7 +21,15 @@ export default function <%= plural_table_name.camelize %>New({
22
21
  return (
23
22
  <div>
24
23
  {messagesEl}
25
- <RailsTag {...form} data-sg-visit={true}/>
24
+ <form {...form.props} data-sg-visit={true}>
25
+ {Object.values(form.extras).map((hiddenProps) => (<input {...hiddenProps} key={hiddenProps.id} type="hidden"/>))}
26
+ <%- attributes.each do |attr| -%>
27
+ <input {...form.inputs.<%= attr.column_name %>} type="text"/>
28
+ <label htmlFor={form.inputs.<%= attr.column_name %>.id}><%= attr.column_name %></label>
29
+ <%- end -%>
30
+ <button {...form.inputs.submit} type="submit"> {...form.inputs.submit.text} </button>
31
+ </form>
32
+
26
33
  <a href={<%= plural_table_name.camelize(:lower) %>Path} data-sg-visit={true}>Back</a>
27
34
  </div>
28
35
  )
@@ -1,4 +1,3 @@
1
1
  // Example:
2
2
  //
3
3
  // export const CLEAR_FORM_ERRORS = 'CLEAR_FORM_ERRORS'
4
- export const REHYDRATE = 'persist/REHYDRATE'
@@ -5,47 +5,13 @@ import thunk from 'redux-thunk';
5
5
  import { Provider } from 'react-redux';
6
6
  import { render } from 'react-dom';
7
7
  import { ApplicationBase, fragmentMiddleware } from '@thoughtbot/superglue';
8
- import { persistStore, persistReducer } from 'redux-persist';
9
- import storage from 'redux-persist/lib/storage';
10
8
  import { applicationRootReducer, applicationPagesReducer } from './reducer';
11
9
  import { buildVisitAndRemote } from './application_visit';
10
+ import { pageIdentifierToPageComponent } from './page_to_page_mapping';
12
11
 
13
- // Mapping between your props template to Component, you must add to this
14
- // to register any new page level component you create. If you are using the
15
- // scaffold, it will auto append the identifers for you.
16
- //
17
- // e.g {'posts/new': PostNew}
18
- const identifierToComponentMapping = {
19
- };
20
-
21
- if (typeof window !== "undefined") {
22
- document.addEventListener("DOMContentLoaded", function () {
23
- const appEl = document.getElementById("app");
24
- const location = window.location;
25
-
26
- if (appEl) {
27
- render(
28
- <Application
29
- appEl={appEl}
30
- // The base url prefixed to all calls made by the `visit`
31
- // and `remote` thunks.
32
- baseUrl={location.origin}
33
- // The global var SUPERGLUE_INITIAL_PAGE_STATE is set by your erb
34
- // template, e.g., index.html.erb
35
- initialPage={window.SUPERGLUE_INITIAL_PAGE_STATE}
36
- // The initial path of the page, e.g., /foobar
37
- path={location.pathname + location.search + location.hash}
38
- buildVisitAndRemote={buildVisitAndRemote}
39
- />,
40
- appEl
41
- );
42
- }
43
- });
44
- }
45
-
46
- export default class Application extends ApplicationBase {
12
+ class Application extends ApplicationBase {
47
13
  mapping() {
48
- return identifierToComponentMapping;
14
+ return pageIdentifierToPageComponent;
49
15
  }
50
16
 
51
17
  visitAndRemote(navRef, store) {
@@ -58,57 +24,46 @@ export default class Application extends ApplicationBase {
58
24
  const composeEnhancers =
59
25
  (this.hasWindow && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
60
26
  compose;
61
- const reducer = this.wrapWithPersistReducer(
62
- reduceReducers(
27
+ const reducer = reduceReducers(
63
28
  combineReducers({
64
29
  superglue: superglueReducer,
65
30
  pages: reduceReducers(pagesReducer, applicationPagesReducer),
66
31
  }),
67
32
  applicationRootReducer
68
- )
69
33
  );
34
+
70
35
  const store = createStore(
71
36
  reducer,
72
37
  initialState,
73
38
  composeEnhancers(applyMiddleware(thunk, fragmentMiddleware))
74
39
  );
75
40
 
76
- if (this.hasWindow) {
77
- // Persist the store using Redux-Persist
78
- persistStore(store);
79
- }
80
-
81
41
  return store;
82
42
  }
43
+ }
83
44
 
84
- wrapWithPersistReducer(reducers) {
85
- // Redux Persist settings
86
- // The key is set to the stringified JS asset path to remove the need for
87
- // migrations when hydrating.
88
- if (!this.hasWindow) {
89
- return reducers;
90
- }
91
- const prefix = "superglue";
92
- const persistKey =
93
- prefix +
94
- this.props.initialPage.assets
95
- .filter((asset) => asset.endsWith(".js"))
96
- .join(",");
97
- const persistConfig = {
98
- key: persistKey,
99
- storage,
100
- };
45
+ if (typeof window !== "undefined") {
46
+ document.addEventListener("DOMContentLoaded", function () {
47
+ const appEl = document.getElementById("app");
48
+ const location = window.location;
101
49
 
102
- // Remove older storage items that were used by previous JS assets
103
- if (this.hasWindow) {
104
- const storedKeys = Object.keys(localStorage);
105
- storedKeys.forEach((key) => {
106
- if (key.startsWith(`persist:${prefix}`) && key !== persistKey) {
107
- localStorage.removeItem(key);
108
- }
109
- });
50
+ if (appEl) {
51
+ render(
52
+ <Application
53
+ appEl={appEl}
54
+ // The base url prefixed to all calls made by the `visit`
55
+ // and `remote` thunks.
56
+ baseUrl={location.origin}
57
+ // The global var SUPERGLUE_INITIAL_PAGE_STATE is set by your erb
58
+ // template, e.g., index.html.erb
59
+ initialPage={window.SUPERGLUE_INITIAL_PAGE_STATE}
60
+ // The initial path of the page, e.g., /foobar
61
+ path={location.pathname + location.search + location.hash}
62
+ buildVisitAndRemote={buildVisitAndRemote}
63
+ />,
64
+ appEl
65
+ );
110
66
  }
111
-
112
- return persistReducer(persistConfig, reducers);
113
- }
67
+ });
114
68
  }
69
+
@@ -7,10 +7,7 @@ end
7
7
  json.component_identifier local_assigns[:virtual_path_of_template]
8
8
  json.defers json.deferred!
9
9
  json.fragments json.fragments!
10
- json.assets [
11
- asset_pack_path('application.js'),
12
- asset_path('application.css')
13
- ]
10
+ json.assets [ asset_path('application.js') ]
14
11
 
15
12
  if protect_against_forgery?
16
13
  json.csrf_token form_authenticity_token
@@ -1 +1 @@
1
- require 'props_template/core_ext'
1
+ require "props_template/core_ext"
@@ -0,0 +1,12 @@
1
+ // import your page component
2
+ // e.g import PostsEdit from '../views/posts/edit'
3
+
4
+
5
+ // Mapping between your props template to Component, you must add to this
6
+ // to register any new page level component you create. If you are using the
7
+ // scaffold, it will auto append the identifers for you.
8
+ //
9
+ // e.g {'posts/new': PostNew}
10
+ export const pageIdentifierToPageComponent = {
11
+ };
12
+
@@ -20,9 +20,6 @@
20
20
  // }
21
21
  // }
22
22
 
23
- import {
24
- REHYDRATE,
25
- } from './actions'
26
23
 
27
24
  // The applicationPageReducer is for cross page reducers
28
25
  // Its common to add to this. You'll typically have to pass a pageKey to the
@@ -38,34 +35,9 @@ export const applicationPagesReducer = (state = {}, action) => {
38
35
  }
39
36
 
40
37
  // The applicationRootReducer is for app wide reducers
41
- // Its rare to be adding to this. Included out of the box ix a reducer for
42
- // Redux Persist.
43
- //
44
- // The REHYDRATE reducer is generated by Superglue and is needed to persist state
45
- // on any changes made to the initial state that gets injected into
46
- // window.SUPERGLUE_INITIAL_PAGE_STATE.
38
+ // Its rare to be adding to this.
47
39
  export const applicationRootReducer = (state = {}, action) => {
48
40
  switch(action.type) {
49
- case REHYDRATE: {
50
- if (action.payload) {
51
- const {
52
- pages: hydratedPages
53
- } = action.payload
54
- const { pages } = state
55
- const nextPages = { ...pages, ...hydratedPages }
56
-
57
- for (const key in pages) {
58
- if (pages[key] && hydratedPages[key] &&
59
- pages[key].renderedAt > hydratedPages[key].renderedAt) {
60
- nextPages[key] = { ...pages[key] }
61
- }
62
- }
63
-
64
- return { ...state, pages: nextPages }
65
- } else {
66
- return state
67
- }
68
- }
69
41
  default:
70
42
  return state
71
43
  }
data/lib/install/web.rb CHANGED
@@ -1,7 +1,3 @@
1
- require "webpacker/configuration"
2
-
3
- babel_config = Rails.root.join("babel.config.js")
4
-
5
1
  def add_member_methods
6
2
  inject_into_file "app/models/application_record.rb", after: "class ApplicationRecord < ActiveRecord::Base\n" do
7
3
  <<-RUBY
@@ -16,35 +12,27 @@ def add_member_methods
16
12
  end
17
13
  end
18
14
 
19
- say "Copying module-resolver preset to your babel.config.js"
20
- resolver_snippet = <<~JAVASCRIPT
21
- [
22
- require('babel-plugin-module-resolver').default, {
23
- "root": ["./app"],
24
- "alias": {
25
- "views": "./app/views",
26
- "components": "./app/components",
27
- "javascript": "./app/javascript"
28
- }
29
- }
30
- ],
31
- JAVASCRIPT
32
- insert_into_file "babel.config.js", resolver_snippet, after: /plugins: \[\n/
15
+ def app_js_path
16
+ "app/javascript/"
17
+ end
18
+
19
+ say "Copying application.js file to #{app_js_path}"
20
+ copy_file "#{__dir__}/templates/web/application.js", "#{app_js_path}/application.js"
33
21
 
34
- say "Copying application.js file to #{Webpacker.config.source_entry_path}"
35
- copy_file "#{__dir__}/templates/web/application.js", "#{Webpacker.config.source_entry_path}/application.js"
22
+ say "Copying page_to_page_mapping.js file to #{app_js_path}"
23
+ copy_file "#{__dir__}/templates/web/page_to_page_mapping.js", "#{app_js_path}/page_to_page_mapping.js"
36
24
 
37
- say "Copying reducer.js file to #{Webpacker.config.source_entry_path}"
38
- copy_file "#{__dir__}/templates/web/reducer.js", "#{Webpacker.config.source_entry_path}/reducer.js"
25
+ say "Copying reducer.js file to #{app_js_path}"
26
+ copy_file "#{__dir__}/templates/web/reducer.js", "#{app_js_path}/reducer.js"
39
27
 
40
- say "Copying action_creators.js file to #{Webpacker.config.source_entry_path}"
41
- copy_file "#{__dir__}/templates/web/action_creators.js", "#{Webpacker.config.source_entry_path}/action_creators.js"
28
+ say "Copying action_creators.js file to #{app_js_path}"
29
+ copy_file "#{__dir__}/templates/web/action_creators.js", "#{app_js_path}/action_creators.js"
42
30
 
43
- say "Copying actions.js file to #{Webpacker.config.source_entry_path}"
44
- copy_file "#{__dir__}/templates/web/actions.js", "#{Webpacker.config.source_entry_path}/actions.js"
31
+ say "Copying actions.js file to #{app_js_path}"
32
+ copy_file "#{__dir__}/templates/web/actions.js", "#{app_js_path}/actions.js"
45
33
 
46
- say "Copying application_visit.js file to #{Webpacker.config.source_entry_path}"
47
- copy_file "#{__dir__}/templates/web/application_visit.js", "#{Webpacker.config.source_entry_path}/application_visit.js"
34
+ say "Copying application_visit.js file to #{app_js_path}"
35
+ copy_file "#{__dir__}/templates/web/application_visit.js", "#{app_js_path}/application_visit.js"
48
36
 
49
37
  say "Copying Superglue initializer"
50
38
  copy_file "#{__dir__}/templates/web/initializer.rb", "config/initializers/superglue.rb"
@@ -55,12 +43,10 @@ copy_file "#{__dir__}/templates/web/application.json.props", "app/views/layouts/
55
43
  say "Adding required member methods to ApplicationRecord"
56
44
  add_member_methods
57
45
 
58
- say "Installing React, Redux, and Superglue"
59
- run "yarn add babel-plugin-module-resolver history html-react-parser react-redux redux-thunk redux redux-persist reduce-reducers immer @thoughtbot/superglue --save"
46
+ say "Installing FormProps"
47
+ run "bundle add form_props"
60
48
 
61
- # For newer webpacker
62
- insert_into_file Webpacker.config.config_path, "'app/views', 'app/components'", after: /additional_paths: \[/
63
- # For older webpacker
64
- insert_into_file Webpacker.config.config_path, "'app/views', 'app/components'", after: /resolved_paths: \[/
49
+ say "Installing React, Redux, and Superglue"
50
+ run "yarn add history react-redux redux-thunk redux reduce-reducers immer @thoughtbot/superglue --save"
65
51
 
66
- say "Webpacker now supports superglue.js 🎉", :green
52
+ say "Superglue is Installed! 🎉", :green