inline_forms 7.10.2 → 7.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Rakefile +18 -1
- data/docs/prompt/test-the-example-app.md +3 -3
- data/inline_forms.gemspec +6 -21
- data/lib/inline_forms/gem_files.rb +39 -0
- data/lib/inline_forms/version.rb +1 -1
- metadata +10 -76
- data/bin/inline_forms +0 -141
- data/bin/inline_forms_app_template.rb +0 -22
- data/bin/inline_forms_installer_core.rb +0 -886
- data/lib/generators/templates/capistrano/Capfile +0 -39
- data/lib/generators/templates/capistrano/deploy.rb +0 -59
- data/lib/generators/templates/capistrano/production.rb +0 -7
- data/lib/generators/templates/unicorn/production.rb +0 -39
- data/lib/installer_templates/dartsass/devise_main.scss +0 -2
- data/lib/installer_templates/dartsass/inline_forms_dartsass_builds.rb +0 -14
- data/lib/installer_templates/dartsass/inline_forms_main.scss +0 -2
- data/lib/installer_templates/example_app_tests/test/example_app/example_integration_test_case.rb +0 -36
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_field_turbo_test.rb +0 -73
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_name_list_test.rb +0 -73
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_name_required_test.rb +0 -21
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_opening_date_test.rb +0 -49
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_photos_pagination_test.rb +0 -440
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_row_turbo_test.rb +0 -103
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_top_level_new_test.rb +0 -70
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_top_level_pagination_test.rb +0 -40
- data/lib/installer_templates/example_app_tests/test/integration/example_app_apartment_versions_turbo_test.rb +0 -120
- data/lib/installer_templates/example_app_tests/test/integration/example_app_guest_access_test.rb +0 -21
- data/lib/installer_templates/example_app_tests/test/integration/example_app_photo_revert_test.rb +0 -94
- data/lib/installer_templates/example_app_tests/test/integration/example_app_photos_test.rb +0 -22
- data/lib/installer_templates/example_app_tests/test/integration/example_app_routing_test.rb +0 -15
- data/lib/installer_templates/example_app_tests/test/integration/example_app_turbo_layout_test.rb +0 -25
- data/lib/installer_templates/example_app_tests/test/integration/example_app_validation_hints_test.rb +0 -40
- data/lib/installer_templates/example_app_tests/test/models/example_app_apartment_name_validation_test.rb +0 -16
- data/lib/installer_templates/example_app_tests/test/models/example_app_apartment_photo_test.rb +0 -26
- data/lib/installer_templates/example_app_tests/test/models/example_app_paper_trail_changeset_test.rb +0 -78
- data/lib/installer_templates/example_app_tests/test/models/example_app_plain_text_rich_text_edge_cases_test.rb +0 -46
- data/lib/installer_templates/example_app_views/apartments/name_list.html.erb +0 -26
- data/lib/installer_templates/example_app_views/inline_forms/_header.html.erb +0 -45
|
@@ -1,886 +0,0 @@
|
|
|
1
|
-
GENERATOR_PATH = File.dirname(File.expand_path(__FILE__)) + '/../'
|
|
2
|
-
|
|
3
|
-
# Rails 7 dropped --skip-gemfile, so `rails new` always writes its own Gemfile.
|
|
4
|
-
# Remove it so our `create_file` below does not prompt for overwrite.
|
|
5
|
-
remove_file 'Gemfile' if File.exist?('Gemfile')
|
|
6
|
-
create_file 'Gemfile', "# created by inline_forms #{ENV['inline_forms_version']} on #{Date.today}\n"
|
|
7
|
-
|
|
8
|
-
# `rails new` is invoked with whatever the system `rails` binary points at
|
|
9
|
-
# (often Rails 8.x once it lands in the global gemset), so the generated
|
|
10
|
-
# `config/application.rb` may carry Rails 7.1+/8.0 idioms (`load_defaults
|
|
11
|
-
# 8.0`, `config.autoload_lib(...)`). The Gemfile we write below pins
|
|
12
|
-
# `rails ~> 7.0.0`, so Rails 7.0 must be able to interpret application.rb;
|
|
13
|
-
# otherwise the first `bundle exec rails …` aborts with `Unknown version
|
|
14
|
-
# "8.0"` or `NoMethodError: undefined method 'autoload_lib'`.
|
|
15
|
-
if File.exist?('config/application.rb')
|
|
16
|
-
gsub_file 'config/application.rb',
|
|
17
|
-
/config\.load_defaults\s+\d+\.\d+/,
|
|
18
|
-
'config.load_defaults 7.1'
|
|
19
|
-
# Strip Rails 7.1+ `config.autoload_lib(ignore: ...)` (and any surrounding
|
|
20
|
-
# explanatory comment block). Not supported on Rails 7.0.
|
|
21
|
-
gsub_file 'config/application.rb',
|
|
22
|
-
/^\s*#[^\n]*\n(\s*#[^\n]*\n)*\s*config\.autoload_lib\([^)]*\)\s*\n/,
|
|
23
|
-
""
|
|
24
|
-
gsub_file 'config/application.rb',
|
|
25
|
-
/^\s*config\.autoload_lib\([^)]*\)\s*\n/,
|
|
26
|
-
""
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
add_source 'https://rubygems.org'
|
|
30
|
-
|
|
31
|
-
gem 'cancancan'
|
|
32
|
-
gem 'carrierwave', '~> 3.1'
|
|
33
|
-
gem 'devise', '~> 5.0'
|
|
34
|
-
gem 'devise-i18n', '~> 1.16'
|
|
35
|
-
gem 'autoprefixer-rails'
|
|
36
|
-
# foundation-rails 6.7+ uses Dart Sass (`sass:math`); sass-rails/sassc removed.
|
|
37
|
-
# Visually tuned against foundation-rails ~> 6.6.2; current pin ~> 6.9 (6.9.0.x).
|
|
38
|
-
gem 'foundation-rails', '~> 6.9'
|
|
39
|
-
gem 'i18n-active_record', :git => 'https://github.com/acesuares/i18n-active_record.git'
|
|
40
|
-
generator_repo = File.expand_path(GENERATOR_PATH)
|
|
41
|
-
# Always use the generator source path (repo checkout OR installed gem dir).
|
|
42
|
-
# This guarantees the generated app uses the exact inline_forms code that
|
|
43
|
-
# launched `inline_forms create`, including unreleased local builds.
|
|
44
|
-
gem 'inline_forms', path: generator_repo
|
|
45
|
-
gem 'jquery-rails'
|
|
46
|
-
gem 'jquery-timepicker-rails'
|
|
47
|
-
# jQuery UI JavaScript (`//= require jquery.ui.all` in inline_forms.js). SCSS + PNGs
|
|
48
|
-
# are vendored in the inline_forms engine (Dart Sass cannot evaluate sass-rails
|
|
49
|
-
# `image-path()`). Pin matches former jquery-ui-sass-rails 4.0.3.x stack.
|
|
50
|
-
gem 'jquery-ui-rails', '4.0.3'
|
|
51
|
-
# Foundation Icons SCSS + fonts are vendored in the inline_forms engine (Dart Sass;
|
|
52
|
-
# foundation-icons-sass-rails depended on sass-rails).
|
|
53
|
-
gem 'mini_magick'
|
|
54
|
-
gem 'mysql2'
|
|
55
|
-
gem 'paper_trail', '~> 16.0'
|
|
56
|
-
gem 'rails-i18n', '~> 7.0'
|
|
57
|
-
gem 'rails-jquery-autocomplete'
|
|
58
|
-
gem 'rails', '~> 7.1.5'
|
|
59
|
-
gem 'rake'
|
|
60
|
-
gem 'rvm'
|
|
61
|
-
gem 'dartsass-rails'
|
|
62
|
-
# Rails 7 no longer adds sprockets-rails to the default Gemfile; declare it
|
|
63
|
-
# explicitly because the gem's own assets (foundation, jquery, etc.) live in
|
|
64
|
-
# app/assets and rely on the Sprockets pipeline.
|
|
65
|
-
gem 'sprockets-rails'
|
|
66
|
-
# Rails 7 default JavaScript tooling: importmap-rails replaces Webpacker.
|
|
67
|
-
gem 'importmap-rails'
|
|
68
|
-
# Hotwire/Turbo. Loaded from layouts as `<script type="module">`; inline flows
|
|
69
|
-
# use `<turbo-frame>` + HTML responses (see docs/ujs-to-turbo.md). Registers the
|
|
70
|
-
# `turbo_stream` MIME type for optional stream responses.
|
|
71
|
-
gem 'turbo-rails'
|
|
72
|
-
gem 'tabs_on_rails', :git => 'https://github.com/acesuares/tabs_on_rails.git', :branch => 'update_remote_before_action'
|
|
73
|
-
gem 'unicorn'
|
|
74
|
-
gem 'validation_hints', '~> 6.3'
|
|
75
|
-
gem 'will_paginate' #, git: 'https://github.com/acesuares/will_paginate.git'
|
|
76
|
-
|
|
77
|
-
gem_group :test do
|
|
78
|
-
# Rails 7 still expects Minitest 5; 6.x breaks the railties test runner.
|
|
79
|
-
gem 'minitest', '~> 5.25'
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
gem_group :development do
|
|
83
|
-
gem 'capistrano-bundler', require: false
|
|
84
|
-
gem 'capistrano-rails', require: false
|
|
85
|
-
gem 'capistrano', require: false
|
|
86
|
-
gem 'capistrano3-unicorn'
|
|
87
|
-
gem 'listen'
|
|
88
|
-
gem 'rvm-capistrano', :require => false
|
|
89
|
-
gem 'rvm1-capistrano3', require: false
|
|
90
|
-
gem 'seed_dump', '~> 0.5.3'
|
|
91
|
-
# Rails 6.1 ActiveRecord's sqlite3 adapter requires sqlite3 ~> 1.4; 2.x activates first and breaks.
|
|
92
|
-
gem 'sqlite3', '~> 1.4'
|
|
93
|
-
gem 'thin'
|
|
94
|
-
gem 'yaml_db'
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
gem_group :production do
|
|
98
|
-
gem 'mini_racer'
|
|
99
|
-
gem 'uglifier'
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
say "- Running bundle..."
|
|
103
|
-
run "gem install bundler"
|
|
104
|
-
vh_gem_dirs = [
|
|
105
|
-
ENV["VALIDATION_HINTS_ROOT"],
|
|
106
|
-
File.expand_path("~/validation_hints"),
|
|
107
|
-
File.expand_path("~/code/validation_hints"),
|
|
108
|
-
File.expand_path("../validation_hints", GENERATOR_PATH)
|
|
109
|
-
].compact.uniq
|
|
110
|
-
vh_gem = vh_gem_dirs.flat_map { |dir| Dir[File.join(dir, "validation_hints-*.gem")] }.sort.last
|
|
111
|
-
if vh_gem && File.file?(vh_gem)
|
|
112
|
-
say "- Installing #{File.basename(vh_gem)} (local build; not on RubyGems yet)..."
|
|
113
|
-
run "gem install #{vh_gem} --no-document"
|
|
114
|
-
end
|
|
115
|
-
run "bundle install"
|
|
116
|
-
|
|
117
|
-
say "- Dart Sass: inline_forms stylesheet entrypoints + initializer..."
|
|
118
|
-
copy_file File.join(GENERATOR_PATH, "lib/installer_templates/dartsass/inline_forms_dartsass_builds.rb"),
|
|
119
|
-
"config/initializers/inline_forms_dartsass_builds.rb"
|
|
120
|
-
copy_file File.join(GENERATOR_PATH, "lib/installer_templates/dartsass/inline_forms_main.scss"),
|
|
121
|
-
"app/assets/stylesheets/inline_forms_install/inline_forms_main.scss"
|
|
122
|
-
copy_file File.join(GENERATOR_PATH, "lib/installer_templates/dartsass/devise_main.scss"),
|
|
123
|
-
"app/assets/stylesheets/inline_forms_install/devise_main.scss"
|
|
124
|
-
|
|
125
|
-
say "- Dart Sass: rails dartsass:install (builds/, manifest, Procfile.dev)..."
|
|
126
|
-
run "bundle exec rails dartsass:install"
|
|
127
|
-
|
|
128
|
-
say "- Dart Sass: drop default application.css (manifest links builds/*.css only)..."
|
|
129
|
-
remove_file "app/assets/stylesheets/application.css"
|
|
130
|
-
|
|
131
|
-
insert_into_file "test/test_helper.rb", <<~'DARTSASS_TEST', after: %(require "rails/test_help"\n)
|
|
132
|
-
|
|
133
|
-
# Dart Sass writes CSS to app/assets/builds; Sprockets does not compile .scss.
|
|
134
|
-
Rails.application.load_tasks
|
|
135
|
-
Rake::Task["dartsass:build"].invoke
|
|
136
|
-
DARTSASS_TEST
|
|
137
|
-
|
|
138
|
-
say "- Database setup: creating config/database.yml with development database #{ENV['database']}"
|
|
139
|
-
remove_file "config/database.yml" # the one that 'rails new' created
|
|
140
|
-
if ENV['using_sqlite'] == 'true'
|
|
141
|
-
create_file "config/database.yml", <<-END_DATABASEYML.strip_heredoc
|
|
142
|
-
development:
|
|
143
|
-
adapter: sqlite3
|
|
144
|
-
database: db/development.sqlite3
|
|
145
|
-
pool: 5
|
|
146
|
-
timeout: 5000
|
|
147
|
-
|
|
148
|
-
test:
|
|
149
|
-
adapter: sqlite3
|
|
150
|
-
database: db/test.sqlite3
|
|
151
|
-
pool: 5
|
|
152
|
-
timeout: 5000
|
|
153
|
-
|
|
154
|
-
END_DATABASEYML
|
|
155
|
-
else
|
|
156
|
-
create_file "config/database.yml", <<-END_DATABASEYML.strip_heredoc
|
|
157
|
-
development:
|
|
158
|
-
adapter: mysql2
|
|
159
|
-
database: <%= Rails.application.credentials[:db_name] %>
|
|
160
|
-
username: <%= Rails.application.credentials[:db_username] %>
|
|
161
|
-
password: <%= Rails.application.credentials[:db_password] %>
|
|
162
|
-
END_DATABASEYML
|
|
163
|
-
|
|
164
|
-
say "- Setting development database in credentials"
|
|
165
|
-
create_file "temp_development_database_credentials", <<-END_DEV_DB_CRED.strip_heredoc
|
|
166
|
-
|
|
167
|
-
# development database
|
|
168
|
-
db_name: #{app_name.downcase}_dev
|
|
169
|
-
db_username: #{app_name.downcase}_dev_user
|
|
170
|
-
db_password: #{app_name.downcase}_dev_password
|
|
171
|
-
|
|
172
|
-
END_DEV_DB_CRED
|
|
173
|
-
|
|
174
|
-
run "EDITOR='cat temp_development_database_credentials >> ' rails credentials:edit"
|
|
175
|
-
|
|
176
|
-
remove_file 'temp_development_database_credentials'
|
|
177
|
-
|
|
178
|
-
say "\n *** Please make sure to create a mysql development database with the following credentials:
|
|
179
|
-
db_name: #{app_name.downcase}_dev
|
|
180
|
-
db_username: #{app_name.downcase}_dev_user
|
|
181
|
-
db_password: #{app_name.downcase}_dev_password
|
|
182
|
-
|
|
183
|
-
or use 'rails credentials:edit' to change these values.\n\n", :red
|
|
184
|
-
|
|
185
|
-
end
|
|
186
|
-
append_file "config/database.yml", <<-END_DATABASEYML.strip_heredoc
|
|
187
|
-
production:
|
|
188
|
-
adapter: mysql2
|
|
189
|
-
database: <%= Rails.application.credentials[:db_name] %>
|
|
190
|
-
username: <%= Rails.application.credentials[:db_username] %>
|
|
191
|
-
password: <%= Rails.application.credentials[:db_password] %>
|
|
192
|
-
END_DATABASEYML
|
|
193
|
-
|
|
194
|
-
say "Setting production database in credentials"
|
|
195
|
-
create_file "temp_production_database_credentials", <<-END_PROD_DB_CRED.strip_heredoc
|
|
196
|
-
|
|
197
|
-
# production database
|
|
198
|
-
db_name: #{app_name.downcase}_prod
|
|
199
|
-
db_username: #{app_name.downcase}_prod_user
|
|
200
|
-
db_password:
|
|
201
|
-
|
|
202
|
-
END_PROD_DB_CRED
|
|
203
|
-
|
|
204
|
-
run "EDITOR='cat temp_production_database_credentials >> ' rails credentials:edit --environment production"
|
|
205
|
-
|
|
206
|
-
remove_file 'temp_production_database_credentials'
|
|
207
|
-
|
|
208
|
-
say "\n *** Please make sure to create a mysql production database and use 'rails credentials:edit' to set the password.\n\n", :red
|
|
209
|
-
|
|
210
|
-
say "- Devise install..."
|
|
211
|
-
run "bundle exec rails g devise:install"
|
|
212
|
-
|
|
213
|
-
say "- Create Devise route and add path_prefix..."
|
|
214
|
-
|
|
215
|
-
route <<-ROUTE.strip_heredoc
|
|
216
|
-
devise_for :users, :path_prefix => 'auth'
|
|
217
|
-
resources :users do
|
|
218
|
-
post 'revert', :on => :member
|
|
219
|
-
get 'list_versions', :on => :member
|
|
220
|
-
end
|
|
221
|
-
ROUTE
|
|
222
|
-
|
|
223
|
-
say "- Create devise migration file"
|
|
224
|
-
|
|
225
|
-
sleep 1 # to get unique migration number
|
|
226
|
-
create_file "db/migrate/" +
|
|
227
|
-
Time.now.utc.strftime("%Y%m%d%H%M%S") +
|
|
228
|
-
"_" +
|
|
229
|
-
"devise_create_users.rb", <<-DEVISE_MIGRATION.strip_heredoc
|
|
230
|
-
class DeviseCreateUsers < ActiveRecord::Migration[7.1]
|
|
231
|
-
|
|
232
|
-
def change
|
|
233
|
-
create_table(:users) do |t|
|
|
234
|
-
## Database authenticatable
|
|
235
|
-
t.string :email, null: false, default: ""
|
|
236
|
-
t.string :encrypted_password, null: false, default: ""
|
|
237
|
-
|
|
238
|
-
## Recoverable
|
|
239
|
-
t.string :reset_password_token
|
|
240
|
-
t.datetime :reset_password_sent_at
|
|
241
|
-
|
|
242
|
-
## Rememberable
|
|
243
|
-
t.datetime :remember_created_at
|
|
244
|
-
|
|
245
|
-
## Trackable
|
|
246
|
-
t.integer :sign_in_count, default: 0, null: false
|
|
247
|
-
t.datetime :current_sign_in_at
|
|
248
|
-
t.datetime :last_sign_in_at
|
|
249
|
-
t.string :current_sign_in_ip
|
|
250
|
-
t.string :last_sign_in_ip
|
|
251
|
-
|
|
252
|
-
## Confirmable
|
|
253
|
-
# t.string :confirmation_token
|
|
254
|
-
# t.datetime :confirmed_at
|
|
255
|
-
# t.datetime :confirmation_sent_at
|
|
256
|
-
# t.string :unconfirmed_email # Only if using reconfirmable
|
|
257
|
-
|
|
258
|
-
## Lockable
|
|
259
|
-
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
|
260
|
-
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
|
261
|
-
# t.datetime :locked_at
|
|
262
|
-
|
|
263
|
-
t.string :name
|
|
264
|
-
t.integer :locale_id
|
|
265
|
-
|
|
266
|
-
t.timestamps
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
add_index :users, :email, unique: true
|
|
270
|
-
add_index :users, :reset_password_token, unique: true
|
|
271
|
-
# add_index :users, :confirmation_token, unique: true
|
|
272
|
-
# add_index :users, :unlock_token, unique: true
|
|
273
|
-
end
|
|
274
|
-
end
|
|
275
|
-
DEVISE_MIGRATION
|
|
276
|
-
|
|
277
|
-
say "- Create User Controller..."
|
|
278
|
-
create_file "app/controllers/users_controller.rb", <<-USERS_CONTROLLER.strip_heredoc
|
|
279
|
-
class UsersController < InlineFormsController
|
|
280
|
-
set_tab :user
|
|
281
|
-
end
|
|
282
|
-
USERS_CONTROLLER
|
|
283
|
-
|
|
284
|
-
say "- Create User Model..."
|
|
285
|
-
create_file "app/models/user.rb", <<-USER_MODEL.strip_heredoc
|
|
286
|
-
class User < ApplicationRecord
|
|
287
|
-
|
|
288
|
-
# devise options
|
|
289
|
-
devise :database_authenticatable
|
|
290
|
-
# devise :registerable # uncomment this if you want people to be able to register
|
|
291
|
-
devise :recoverable
|
|
292
|
-
devise :rememberable
|
|
293
|
-
devise :trackable
|
|
294
|
-
devise :validatable
|
|
295
|
-
# devise :token_authenticatable
|
|
296
|
-
# devise :confirmable,
|
|
297
|
-
# devise :lockable
|
|
298
|
-
# devise :timeoutable
|
|
299
|
-
# devise :omniauthable
|
|
300
|
-
|
|
301
|
-
# Setup accessible (or protected) attributes for your model
|
|
302
|
-
attr_writer :inline_forms_attribute_list
|
|
303
|
-
#attr_accessible :email, :password, :locale, :remember_me
|
|
304
|
-
|
|
305
|
-
belongs_to :locale
|
|
306
|
-
has_and_belongs_to_many :roles
|
|
307
|
-
|
|
308
|
-
# validations
|
|
309
|
-
validates :name, :presence => true
|
|
310
|
-
|
|
311
|
-
default_scope {order :name}
|
|
312
|
-
|
|
313
|
-
# pagination
|
|
314
|
-
attr_reader :per_page
|
|
315
|
-
@per_page = 7
|
|
316
|
-
|
|
317
|
-
has_paper_trail
|
|
318
|
-
|
|
319
|
-
def _presentation
|
|
320
|
-
"\#{name}"
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
def role?(role)
|
|
324
|
-
return !!self.roles.find_by_name(role)
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
def inline_forms_attribute_list
|
|
328
|
-
@inline_forms_attribute_list ||= [
|
|
329
|
-
[ :header_user_login, '', :header ],
|
|
330
|
-
[ :name, '', :text_field ],
|
|
331
|
-
[ :email, '', :text_field ],
|
|
332
|
-
[ :locale , '', :dropdown ],
|
|
333
|
-
[ :password, '', :devise_password_field ],
|
|
334
|
-
[ :header_user_roles, '', :header ],
|
|
335
|
-
[ :roles, '', :check_list ],
|
|
336
|
-
[ :header_user_other_stuff, '', :header ],
|
|
337
|
-
[ :encrypted_password, '', :info ],
|
|
338
|
-
[ :reset_password_token, '', :info ],
|
|
339
|
-
[ :reset_password_sent_at, '', :info],
|
|
340
|
-
[ :remember_created_at, '', :info ],
|
|
341
|
-
[ :sign_in_count, '', :info ],
|
|
342
|
-
[ :current_sign_in_at, '', :info ],
|
|
343
|
-
[ :last_sign_in_at, '', :info ],
|
|
344
|
-
[ :current_sign_in_ip, '', :info ],
|
|
345
|
-
[ :last_sign_in_ip, '', :info ],
|
|
346
|
-
[ :created_at, '', :info ],
|
|
347
|
-
[ :updated_at, '', :info ],
|
|
348
|
-
]
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
def self.not_accessible_through_html?
|
|
352
|
-
false
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
def self.order_by_clause
|
|
356
|
-
nil
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
end
|
|
360
|
-
USER_MODEL
|
|
361
|
-
|
|
362
|
-
# Create Locales
|
|
363
|
-
say "- Create locales"
|
|
364
|
-
generate "inline_forms", "Locale name:string title:string users:has_many _enabled:yes _presentation:\#{title}"
|
|
365
|
-
append_to_file "db/seeds.rb", "Locale.create({ id: 1, name: 'en', title: 'English' })\n"
|
|
366
|
-
|
|
367
|
-
# Create Roles
|
|
368
|
-
say "- Create roles"
|
|
369
|
-
generate "inline_forms", "Role name:string description:text users:has_and_belongs_to_many _enabled:yes _presentation:\#{name}"
|
|
370
|
-
append_to_file "db/seeds.rb", "Role.create({ id: 1, name: 'superadmin', description: 'Super Admin can access all.' })\n"
|
|
371
|
-
|
|
372
|
-
# Create Admin User
|
|
373
|
-
|
|
374
|
-
say "- Adding admin user with email: #{ENV['email']}, password: #{ENV['password']} to seeds.rb"
|
|
375
|
-
append_to_file "db/seeds.rb", "User.create({ id: 1, email: '#{ENV['email']}', locale_id: 1, name: 'Admin', password: '#{ENV['password']}', password_confirmation: '#{ENV['password']}' })\n"
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
sleep 1 # to get unique migration number
|
|
379
|
-
create_file "db/migrate/" +
|
|
380
|
-
Time.now.utc.strftime("%Y%m%d%H%M%S") +
|
|
381
|
-
"_" +
|
|
382
|
-
"inline_forms_create_join_table_user_role.rb", <<-ROLES_MIGRATION.strip_heredoc
|
|
383
|
-
class InlineFormsCreateJoinTableUserRole < ActiveRecord::Migration[7.1]
|
|
384
|
-
def self.up
|
|
385
|
-
create_table :roles_users, :id => false, :force => true do |t|
|
|
386
|
-
t.integer :role_id
|
|
387
|
-
t.integer :user_id
|
|
388
|
-
end
|
|
389
|
-
execute 'INSERT INTO roles_users VALUES (1,1);'
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
def self.down
|
|
393
|
-
drop_table roles_users
|
|
394
|
-
end
|
|
395
|
-
end
|
|
396
|
-
ROLES_MIGRATION
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
say "- Installaing ZURB Foundation..."
|
|
400
|
-
#generate "foundation:install", "-f"
|
|
401
|
-
|
|
402
|
-
say "- Copy inline_forms_devise file for custom styles..."
|
|
403
|
-
copy_file File.join(GENERATOR_PATH, 'lib/generators/assets/stylesheets/inline_forms_devise.css'), 'app/assets/stylesheets/inline_forms_devise.css'
|
|
404
|
-
|
|
405
|
-
say "- Sprockets: link inline_forms_devise.css (logical path; dartsass:install drops link_directory ../stylesheets)..."
|
|
406
|
-
append_to_file "app/assets/config/manifest.js", "//= link inline_forms_devise.css\n"
|
|
407
|
-
|
|
408
|
-
say "- Add human_attribute_name in app/models/application_record.rb"
|
|
409
|
-
remove_file 'app/models/application_record.rb' # the one that 'rails new' created
|
|
410
|
-
copy_file File.join(GENERATOR_PATH, 'lib/generators/templates/application_record.rb'), "app/models/application_record.rb"
|
|
411
|
-
|
|
412
|
-
say "- Install ActionText..."
|
|
413
|
-
run "bundle exec rails active_storage:install"
|
|
414
|
-
run "bundle exec rails action_text:install:migrations"
|
|
415
|
-
run "bundle install"
|
|
416
|
-
|
|
417
|
-
say "- Paper_trail install..."
|
|
418
|
-
# Upstream paper_trail (>= 13) detects MySQL via the live ActiveRecord connection,
|
|
419
|
-
# so the migration's InnoDB options are added only when the dev DB is mysql.
|
|
420
|
-
# For mysql installs the user has been instructed above to create the development
|
|
421
|
-
# database before continuing; for sqlite the file is created on first connection.
|
|
422
|
-
generate "paper_trail:install --with-changes"
|
|
423
|
-
# paper_trail emits two migrations in one second; the next generator would reuse that timestamp.
|
|
424
|
-
sleep 1
|
|
425
|
-
|
|
426
|
-
say "- Track ActionText (rich_text) edits with PaperTrail..."
|
|
427
|
-
# `has_rich_text :foo` stores the body in the separate `action_text_rich_texts`
|
|
428
|
-
# table, not on the parent model, so `has_paper_trail` on the parent never
|
|
429
|
-
# sees rich_text edits. The standard fix (recommended by paper_trail's
|
|
430
|
-
# maintainer in https://stackoverflow.com/q/55544935) is to declare
|
|
431
|
-
# `has_paper_trail` directly on `ActionText::RichText`. We surface those
|
|
432
|
-
# versions in the parent's versions panel from `inline_forms_versions_for`.
|
|
433
|
-
#
|
|
434
|
-
# Note: PaperTrail >= 16 raises if `has_paper_trail` is called twice on the
|
|
435
|
-
# same model, so this initializer must be the only place it's added to
|
|
436
|
-
# `ActionText::RichText` in the generated app.
|
|
437
|
-
create_file 'config/initializers/rich_text_paper_trail.rb', <<-PT_RICH_TEXT.strip_heredoc
|
|
438
|
-
# Generated by inline_forms.
|
|
439
|
-
ActiveSupport.on_load(:action_text_rich_text) do
|
|
440
|
-
has_paper_trail
|
|
441
|
-
end
|
|
442
|
-
PT_RICH_TEXT
|
|
443
|
-
|
|
444
|
-
say "- Configure ActiveRecord YAML permitted classes for PaperTrail changesets..."
|
|
445
|
-
# PaperTrail's YAML serializer (>= 13) uses `YAML.safe_load` and reads its
|
|
446
|
-
# allow-list from `ActiveRecord.yaml_column_permitted_classes`. Rails 7's
|
|
447
|
-
# default is `[Symbol]`, so any update that touches `updated_at`
|
|
448
|
-
# (an `ActiveSupport::TimeWithZone`) raises `Psych::DisallowedClass` inside
|
|
449
|
-
# `version.changeset`; PaperTrail rescues that and returns `{}`, which is why
|
|
450
|
-
# the inline_forms versions list rendered every changeset as `empty`. Permit
|
|
451
|
-
# the classes PT actually emits so `version.changeset` round-trips.
|
|
452
|
-
create_file 'config/initializers/paper_trail_yaml_safe_load.rb', <<-PT_YAML.strip_heredoc
|
|
453
|
-
# Generated by inline_forms.
|
|
454
|
-
# See https://github.com/paper-trail-gem/paper_trail and
|
|
455
|
-
# ActiveRecord::Coders::YAMLColumn safe-loading rules.
|
|
456
|
-
Rails.application.config.active_record.yaml_column_permitted_classes ||= []
|
|
457
|
-
Rails.application.config.active_record.yaml_column_permitted_classes |= [
|
|
458
|
-
Symbol,
|
|
459
|
-
Date,
|
|
460
|
-
Time,
|
|
461
|
-
BigDecimal,
|
|
462
|
-
ActiveSupport::TimeWithZone,
|
|
463
|
-
ActiveSupport::TimeZone,
|
|
464
|
-
ActiveSupport::HashWithIndifferentAccess
|
|
465
|
-
]
|
|
466
|
-
ActiveRecord.yaml_column_permitted_classes |= Rails.application.config.active_record.yaml_column_permitted_classes
|
|
467
|
-
PT_YAML
|
|
468
|
-
|
|
469
|
-
# Create Translations
|
|
470
|
-
say "- Generate models and tables and views for translations..." # TODO Translations need to be done in inline_forms, and then generate a yml file, perhaps
|
|
471
|
-
generate "inline_forms", "InlineFormsLocale name:string inline_forms_translations:belongs_to _enabled:yes _presentation:\#{name}"
|
|
472
|
-
sleep 1 # unique migration timestamps per generator
|
|
473
|
-
generate "inline_forms", "InlineFormsKey name:string inline_forms_translations:has_many inline_forms_translations:associated _enabled:yes _presentation:\#{name}"
|
|
474
|
-
sleep 1
|
|
475
|
-
generate "inline_forms", "InlineFormsTranslation inline_forms_key:belongs_to inline_forms_locale:dropdown value:text interpolations:text is_proc:boolean _presentation:\#{value}"
|
|
476
|
-
# Plain long text uses :plain_text; ActionText-backed fields use :rich_text.
|
|
477
|
-
sleep 1 # to get unique migration number
|
|
478
|
-
create_file "db/migrate/" +
|
|
479
|
-
Time.now.utc.strftime("%Y%m%d%H%M%S") +
|
|
480
|
-
"_" +
|
|
481
|
-
"inline_forms_create_view_for_translations.rb", <<-VIEW_MIGRATION.strip_heredoc
|
|
482
|
-
class InlineFormsCreateViewForTranslations < ActiveRecord::Migration[7.1]
|
|
483
|
-
def self.up
|
|
484
|
-
execute 'CREATE VIEW translations
|
|
485
|
-
AS
|
|
486
|
-
SELECT L.name AS locale,
|
|
487
|
-
K.name AS thekey,
|
|
488
|
-
T.value AS value,
|
|
489
|
-
T.interpolations AS interpolations,
|
|
490
|
-
T.is_proc AS is_proc
|
|
491
|
-
FROM inline_forms_keys K, inline_forms_locales L, inline_forms_translations T
|
|
492
|
-
WHERE T.inline_forms_key_id = K.id AND T.inline_forms_locale_id = L.id '
|
|
493
|
-
end
|
|
494
|
-
def self.down
|
|
495
|
-
execute 'DROP VIEW translations'
|
|
496
|
-
end
|
|
497
|
-
end
|
|
498
|
-
VIEW_MIGRATION
|
|
499
|
-
|
|
500
|
-
say "- Creating application title via locales..."
|
|
501
|
-
create_file "config/locales/inline_forms_local.en.yml", <<-END_LOCALE.strip_heredoc
|
|
502
|
-
en:
|
|
503
|
-
inline_forms:
|
|
504
|
-
general:
|
|
505
|
-
application_title: #{app_name}
|
|
506
|
-
devise:
|
|
507
|
-
title_for_devise: #{app_name}
|
|
508
|
-
welcome: Welcome to #{app_name}!
|
|
509
|
-
END_LOCALE
|
|
510
|
-
|
|
511
|
-
say "- Migrating Database (only when using sqlite)"
|
|
512
|
-
run "bundle exec rake db:migrate" if ENV['using_sqlite'] == 'true'
|
|
513
|
-
|
|
514
|
-
say "- Seeding the database (only when using sqlite)"
|
|
515
|
-
run "bundle exec rake db:seed" if ENV['using_sqlite'] == 'true'
|
|
516
|
-
|
|
517
|
-
say "- Recreating ApplicationHelper to set application_name and application_title..."
|
|
518
|
-
remove_file "app/helpers/application_helper.rb" # the one that 'rails new' created
|
|
519
|
-
create_file "app/helpers/application_helper.rb", <<-END_APPHELPER.strip_heredoc
|
|
520
|
-
module ApplicationHelper
|
|
521
|
-
def application_name
|
|
522
|
-
'#{app_name}'
|
|
523
|
-
end
|
|
524
|
-
def application_title
|
|
525
|
-
'#{app_name}'
|
|
526
|
-
end
|
|
527
|
-
end
|
|
528
|
-
END_APPHELPER
|
|
529
|
-
|
|
530
|
-
say "- Creating inline_forms initializer"
|
|
531
|
-
create_file "config/initializers/inline_forms.rb", <<-END_INITIALIZER.strip_heredoc
|
|
532
|
-
Rails.application.reloader.to_prepare do
|
|
533
|
-
MODEL_TABS = %w()
|
|
534
|
-
end
|
|
535
|
-
END_INITIALIZER
|
|
536
|
-
|
|
537
|
-
say "- Recreating ApplicationController to add devise, cancan, I18n stuff..."
|
|
538
|
-
remove_file "app/controllers/application_controller.rb" # the one that 'rails new' created
|
|
539
|
-
create_file "app/controllers/application_controller.rb", <<-END_APPCONTROLLER.strip_heredoc
|
|
540
|
-
class ApplicationController < InlineFormsApplicationController
|
|
541
|
-
protect_from_forgery
|
|
542
|
-
|
|
543
|
-
# add whodunnit
|
|
544
|
-
before_action :set_paper_trail_whodunnit
|
|
545
|
-
|
|
546
|
-
# Comment next lines if you don't want Devise authentication
|
|
547
|
-
before_action :authenticate_user!
|
|
548
|
-
check_authorization unless: :devise_controller?
|
|
549
|
-
|
|
550
|
-
rescue_from CanCan::AccessDenied do |exception|
|
|
551
|
-
respond_to do |format|
|
|
552
|
-
format.json { head :forbidden, content_type: 'text/html' }
|
|
553
|
-
format.html { redirect_to main_app.root_url, notice: exception.message }
|
|
554
|
-
format.js { head :forbidden, content_type: 'text/html' }
|
|
555
|
-
end
|
|
556
|
-
end
|
|
557
|
-
# Comment previous lines if you don't want Devise authentication
|
|
558
|
-
|
|
559
|
-
# Uncomment next line if you want I18n (based on subdomain)
|
|
560
|
-
# before_action :set_locale
|
|
561
|
-
|
|
562
|
-
# Uncomment next line and specify default locale
|
|
563
|
-
# I18n.default_locale = :en
|
|
564
|
-
|
|
565
|
-
# Uncomment next line and specify available locales
|
|
566
|
-
# I18n.available_locales = [ :en, :nl, :pp ]
|
|
567
|
-
|
|
568
|
-
# Uncomment next nine line if you want locale based on subdomain, like 'it.example.com, de.example.com'
|
|
569
|
-
# def set_locale
|
|
570
|
-
# I18n.locale = extract_locale_from_subdomain || I18n.default_locale
|
|
571
|
-
# end
|
|
572
|
-
#
|
|
573
|
-
# def extract_locale_from_subdomain
|
|
574
|
-
# locale = request.subdomains.first
|
|
575
|
-
# return nil if locale.nil?
|
|
576
|
-
# I18n.available_locales.include?(locale.to_sym) ? locale.to_s : nil
|
|
577
|
-
# end
|
|
578
|
-
end
|
|
579
|
-
END_APPCONTROLLER
|
|
580
|
-
|
|
581
|
-
say "- Creating Ability model so that the superadmin can access all..."
|
|
582
|
-
create_file "app/models/ability.rb", <<-END_ABILITY.strip_heredoc
|
|
583
|
-
class Ability
|
|
584
|
-
include CanCan::Ability
|
|
585
|
-
|
|
586
|
-
def initialize(user)
|
|
587
|
-
# See the wiki for details: https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
|
|
588
|
-
|
|
589
|
-
user ||= User.new # guest user
|
|
590
|
-
|
|
591
|
-
# use this if you get stuck:
|
|
592
|
-
# if user.id == 1 #quick hack
|
|
593
|
-
# can :manage, :all
|
|
594
|
-
if user.role? :superadmin
|
|
595
|
-
can :manage, :all
|
|
596
|
-
else
|
|
597
|
-
# put restrictions for other users here
|
|
598
|
-
end
|
|
599
|
-
end
|
|
600
|
-
end
|
|
601
|
-
END_ABILITY
|
|
602
|
-
|
|
603
|
-
# devise mailer stuff
|
|
604
|
-
say "- Injecting devise mailer stuff in environments/production.rb..."
|
|
605
|
-
# strip_heredoc_with_indent(2) became strip_heredoc(2), but only in rails 4... :-(
|
|
606
|
-
insert_into_file "config/environments/production.rb", <<-DEVISE_MAILER_PROD_STUFF.strip_heredoc, :before => "end\n"
|
|
607
|
-
|
|
608
|
-
# for devise
|
|
609
|
-
config.action_mailer.default_url_options = { protocol: 'https', host: Rails.application.credentials[:smtp_app_host] }
|
|
610
|
-
config.action_mailer.delivery_method = :smtp
|
|
611
|
-
config.action_mailer.smtp_settings = {
|
|
612
|
-
address: Rails.application.credentials[:smtp_host],
|
|
613
|
-
enable_starttls_auto: true,
|
|
614
|
-
password: Rails.application.credentials[:smtp_password] ,
|
|
615
|
-
user_name: Rails.application.credentials[:smtp_username]
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
DEVISE_MAILER_PROD_STUFF
|
|
619
|
-
|
|
620
|
-
say "Setting production smtp settings in credentials"
|
|
621
|
-
create_file "temp_production_smtp_credentials", <<-END_PROD_SMTP_CRED.strip_heredoc
|
|
622
|
-
|
|
623
|
-
# devise mailer stuff for production:
|
|
624
|
-
smtp_app_host: APP_HOST
|
|
625
|
-
smtp_host: SMTP_HOST
|
|
626
|
-
smtp_username: USERNAME
|
|
627
|
-
smtp_password: PASSWORD
|
|
628
|
-
|
|
629
|
-
END_PROD_SMTP_CRED
|
|
630
|
-
|
|
631
|
-
run "EDITOR='cat temp_production_smtp_credentials >> ' rails credentials:edit --environment production"
|
|
632
|
-
|
|
633
|
-
remove_file 'temp_production_smtp_credentials'
|
|
634
|
-
|
|
635
|
-
say "- Injecting devise mailer stuff in environments/development.rb..."
|
|
636
|
-
# strip_heredoc_with_indent(2) became strip_heredoc(2), but only in rails 4... :-(
|
|
637
|
-
insert_into_file "config/environments/development.rb", <<-DEVISE_MAILER_DEV_STUFF.strip_heredoc, :before => "\nend\n"
|
|
638
|
-
# for devise
|
|
639
|
-
config.action_mailer.default_url_options = { protocol: 'http', host: 'localhost', port: 3000 }
|
|
640
|
-
config.action_mailer.delivery_method = :smtp
|
|
641
|
-
config.action_mailer.smtp_settings = {
|
|
642
|
-
address: Rails.application.credentials[:smtp_host],
|
|
643
|
-
enable_starttls_auto: true,
|
|
644
|
-
password: Rails.application.credentials[:smtp_password] ,
|
|
645
|
-
user_name: Rails.application.credentials[:smtp_username]
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
DEVISE_MAILER_DEV_STUFF
|
|
649
|
-
|
|
650
|
-
say "Setting development smtp settings in credentials"
|
|
651
|
-
create_file "temp_development_smtp_credentials", <<-END_DEV_SMTP_CRED.strip_heredoc
|
|
652
|
-
|
|
653
|
-
# devise mailers stuff for development:
|
|
654
|
-
smtp_app_host: APP_HOST
|
|
655
|
-
smtp_host: SMTP_HOST
|
|
656
|
-
smtp_username: USERNAME
|
|
657
|
-
smtp_password: PASSWORD
|
|
658
|
-
|
|
659
|
-
END_DEV_SMTP_CRED
|
|
660
|
-
|
|
661
|
-
run "EDITOR='cat temp_development_smtp_credentials >> ' rails credentials:edit"
|
|
662
|
-
|
|
663
|
-
remove_file 'temp_development_smtp_credentials'
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
# capify
|
|
668
|
-
say "- Capify..."
|
|
669
|
-
run 'bundle exec cap install'
|
|
670
|
-
remove_file "config/deploy.rb" # remove the file capify created!
|
|
671
|
-
copy_file File.join(GENERATOR_PATH,'lib/generators/templates/capistrano/deploy.rb'), "config/deploy.rb"
|
|
672
|
-
remove_file "config/deploy/production.rb" # remove the production file capify created!
|
|
673
|
-
copy_file File.join(GENERATOR_PATH,'lib/generators/templates/capistrano/production.rb'), "config/deploy/production.rb"
|
|
674
|
-
remove_file "Capfile" # remove the Capfile file capify created!
|
|
675
|
-
copy_file File.join(GENERATOR_PATH,'lib/generators/templates/capistrano/Capfile'), "Capfile"
|
|
676
|
-
|
|
677
|
-
# Unicorn
|
|
678
|
-
say "- Unicorn Config..."
|
|
679
|
-
copy_file File.join(GENERATOR_PATH,'lib/generators/templates/unicorn/production.rb'), "config/unicorn/production.rb"
|
|
680
|
-
|
|
681
|
-
# Git
|
|
682
|
-
say "- adding and committing to git..."
|
|
683
|
-
|
|
684
|
-
git add: "."
|
|
685
|
-
git commit: " -a -m 'Initial Commit'"
|
|
686
|
-
|
|
687
|
-
# example
|
|
688
|
-
if ENV['install_example'] == 'true'
|
|
689
|
-
say "\nInstalling example application..."
|
|
690
|
-
run 'bundle exec rails g inline_forms Photo name:string caption:string image:image_field description:rich_text apartment:belongs_to _presentation:\'#{name}\''
|
|
691
|
-
run 'bundle exec rails generate uploader Image'
|
|
692
|
-
run 'bundle exec rails g inline_forms Apartment name:string title:string opening_date:date description:rich_text photos:has_many photos:associated _enabled:yes _presentation:\'#{name}\''
|
|
693
|
-
|
|
694
|
-
say "- Apartment name is required..."
|
|
695
|
-
inject_into_file "app/models/apartment.rb",
|
|
696
|
-
"\n validates :name, presence: true\n",
|
|
697
|
-
after: " has_paper_trail\n"
|
|
698
|
-
|
|
699
|
-
# CarrierWave + PaperTrail history.
|
|
700
|
-
# PaperTrail snapshots the column scalar (the stored filename) on update,
|
|
701
|
-
# but CarrierWave's default `remove_previously_stored_files_after_update`
|
|
702
|
-
# deletes the old file on disk and re-uses the same filename, so a
|
|
703
|
-
# PaperTrail revert restores a filename whose bytes are gone.
|
|
704
|
-
# We keep every uploaded file on disk and namespace filenames with a
|
|
705
|
-
# per-upload token so successive uploads do not collide. See
|
|
706
|
-
# https://stackoverflow.com/questions/9423279/papertrail-and-carrierwave
|
|
707
|
-
# (Answers 2, 4 and 5).
|
|
708
|
-
say "- Configuring CarrierWave to keep previously stored files (PaperTrail history)..."
|
|
709
|
-
create_file "config/initializers/carrierwave.rb", <<-CWINIT.strip_heredoc
|
|
710
|
-
# Keep previously stored files on disk so PaperTrail-driven restore
|
|
711
|
-
# actually returns the previous image bytes. See
|
|
712
|
-
# https://stackoverflow.com/questions/9423279/papertrail-and-carrierwave
|
|
713
|
-
# The per-uploader overrides in app/uploaders/image_uploader.rb
|
|
714
|
-
# complement this by giving every upload a unique on-disk filename
|
|
715
|
-
# and by no-op'ing `remove!` so destroyed records keep their files.
|
|
716
|
-
CarrierWave.configure do |config|
|
|
717
|
-
config.remove_previously_stored_files_after_update = false
|
|
718
|
-
end
|
|
719
|
-
CWINIT
|
|
720
|
-
|
|
721
|
-
inject_into_file "app/uploaders/image_uploader.rb",
|
|
722
|
-
after: "class ImageUploader < CarrierWave::Uploader::Base\n" do
|
|
723
|
-
<<-RUBY.strip_heredoc.gsub(/^/, " ")
|
|
724
|
-
# PaperTrail history support. CarrierWave's default behaviour wipes the
|
|
725
|
-
# previous file on update and reuses the same filename; PaperTrail only
|
|
726
|
-
# stores the column scalar, so a plain `version.reify; save!` restores a
|
|
727
|
-
# filename whose bytes are gone. The knobs below preserve every byte:
|
|
728
|
-
#
|
|
729
|
-
# * `remove_previously_stored_files_after_update = false` is set
|
|
730
|
-
# globally in config/initializers/carrierwave.rb (covers
|
|
731
|
-
# `multi_image_field` uploaders too).
|
|
732
|
-
# * `remove!` is a no-op so hard-destroyed records keep their files
|
|
733
|
-
# and revert-after-destroy still finds the bytes on disk.
|
|
734
|
-
# * `filename` is prefixed with a per-upload UUID so successive
|
|
735
|
-
# uploads never collide on disk.
|
|
736
|
-
#
|
|
737
|
-
# Trade-off: files accumulate on disk; sweeping is out of scope.
|
|
738
|
-
# Source: https://stackoverflow.com/questions/9423279/papertrail-and-carrierwave
|
|
739
|
-
def remove!
|
|
740
|
-
# no-op: keep the file so PaperTrail revert can restore it.
|
|
741
|
-
end
|
|
742
|
-
|
|
743
|
-
def filename
|
|
744
|
-
# CarrierWave 3.x calls `filename` again after storing to record the
|
|
745
|
-
# persisted name; at that point `original_filename` may be nil and we
|
|
746
|
-
# must still return the memoized name (see
|
|
747
|
-
# https://github.com/carrierwaveuploader/carrierwave/issues/2708).
|
|
748
|
-
@name ||= "\#{secure_token}-\#{original_filename}" if original_filename
|
|
749
|
-
@name
|
|
750
|
-
end
|
|
751
|
-
|
|
752
|
-
private
|
|
753
|
-
|
|
754
|
-
def secure_token
|
|
755
|
-
var = :"@\#{mounted_as}_secure_token"
|
|
756
|
-
model.instance_variable_get(var) || model.instance_variable_set(var, SecureRandom.uuid)
|
|
757
|
-
end
|
|
758
|
-
RUBY
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
say "- Lower Photo.per_page so the seeded gallery paginates..."
|
|
762
|
-
# The model template (lib/generators/templates/model.erb) emits
|
|
763
|
-
# attr_reader :per_page
|
|
764
|
-
# @per_page = 7
|
|
765
|
-
# which is a long-standing typo: `attr_reader :per_page` defines an
|
|
766
|
-
# *instance* method, then `@per_page = 7` (executed in the class body)
|
|
767
|
-
# actively *clobbers* the class-level per_page that will_paginate
|
|
768
|
-
# exposes via `class_attribute :per_page` (its singleton-ivar storage
|
|
769
|
-
# also lives on `@per_page`). Net effect: nothing reads 7 anywhere,
|
|
770
|
-
# and the class-level per_page silently reverts to will_paginate's
|
|
771
|
-
# 30-default. Replace the pair on Photo with a real `self.per_page = 5`
|
|
772
|
-
# so the seeded gallery (12 photos) actually paginates 5/5/2.
|
|
773
|
-
gsub_file "app/models/photo.rb",
|
|
774
|
-
/^\s*attr_reader\s+:per_page\s*\n\s*@per_page\s*=\s*\d+\s*\n/,
|
|
775
|
-
" self.per_page = 5\n"
|
|
776
|
-
|
|
777
|
-
run 'bundle exec rake db:migrate'
|
|
778
|
-
|
|
779
|
-
# Seed the photos gallery from a local `pics/` folder. The folder is
|
|
780
|
-
# *gitignored* in the gem source (so the built .gem stays small and
|
|
781
|
-
# the gallery images are not committed) which means GENERATOR_PATH/pics
|
|
782
|
-
# exists only when the installer is run from the source repo, not when
|
|
783
|
-
# it is run from an installed gem on the developer's box. We therefore
|
|
784
|
-
# check, in order:
|
|
785
|
-
# 1. ENV['INLINE_FORMS_SEED_PICS'] -- explicit override path
|
|
786
|
-
# 2. GENERATOR_PATH/pics -- gem source repo checkout
|
|
787
|
-
# 3. /home/code/inline_forms/pics -- local dev convention
|
|
788
|
-
# and copy whichever is found into the generated app's db/seed_images/.
|
|
789
|
-
# The migration generated below is what reads from db/seed_images at
|
|
790
|
-
# `db:migrate` / `db:test:prepare` time, so this copy is only ever a
|
|
791
|
-
# one-shot at app generation.
|
|
792
|
-
pics_candidates = [
|
|
793
|
-
ENV["INLINE_FORMS_SEED_PICS"],
|
|
794
|
-
File.join(GENERATOR_PATH, "pics"),
|
|
795
|
-
"/home/code/inline_forms/pics",
|
|
796
|
-
].compact
|
|
797
|
-
pics_src = pics_candidates.find { |p| Dir.exist?(p) }
|
|
798
|
-
if pics_src
|
|
799
|
-
seed_pics = Dir.glob(File.join(pics_src, "*.{jpg,jpeg,JPG,JPEG,png,PNG,gif,GIF}")).sort
|
|
800
|
-
if seed_pics.any?
|
|
801
|
-
say "- Copying #{seed_pics.size} sample photo(s) into db/seed_images/..."
|
|
802
|
-
empty_directory "db/seed_images"
|
|
803
|
-
seed_pics.each do |abs|
|
|
804
|
-
copy_file abs, File.join("db/seed_images", File.basename(abs))
|
|
805
|
-
end
|
|
806
|
-
|
|
807
|
-
say "- Generating Konferensha apartment + photos seed migration..."
|
|
808
|
-
sleep 1 # unique migration timestamp
|
|
809
|
-
seed_ts = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
810
|
-
create_file "db/migrate/#{seed_ts}_seed_konferensha_photos.rb", <<-SEED_MIGRATION.strip_heredoc
|
|
811
|
-
class SeedKonferenshaPhotos < ActiveRecord::Migration[7.1]
|
|
812
|
-
# Seed an Apartment with a gallery of photos so the nested
|
|
813
|
-
# has_many list (apartments -> photos) has enough rows to
|
|
814
|
-
# trigger pagination. Driven by db/seed_images/, which the
|
|
815
|
-
# inline_forms installer copies from the gem's pics/ dir.
|
|
816
|
-
# Runs in development (via db:migrate) and against the test
|
|
817
|
-
# DB (via db:test:prepare), so integration tests can assert
|
|
818
|
-
# the paginated <turbo-frame> renders without seeding manually.
|
|
819
|
-
def up
|
|
820
|
-
apartment = Apartment.find_or_create_by!(name: "Konferensha") do |a|
|
|
821
|
-
a.title = "Konferensha sobre Papiamentu"
|
|
822
|
-
a.opening_date = Date.new(2020, 5, 18)
|
|
823
|
-
end
|
|
824
|
-
|
|
825
|
-
seed_dir = Rails.root.join("db", "seed_images")
|
|
826
|
-
return unless seed_dir.directory?
|
|
827
|
-
|
|
828
|
-
Dir.glob(seed_dir.join("*.{jpg,jpeg,png,gif}"), File::FNM_CASEFOLD).sort.each do |abs|
|
|
829
|
-
base = File.basename(abs)
|
|
830
|
-
next if Photo.exists?(name: base, apartment_id: apartment.id)
|
|
831
|
-
File.open(abs, "rb") do |io|
|
|
832
|
-
Photo.create!(
|
|
833
|
-
name: base,
|
|
834
|
-
caption: "Konferensha foto \#{base}",
|
|
835
|
-
apartment: apartment,
|
|
836
|
-
image: io
|
|
837
|
-
)
|
|
838
|
-
end
|
|
839
|
-
end
|
|
840
|
-
end
|
|
841
|
-
|
|
842
|
-
def down
|
|
843
|
-
apartment = Apartment.find_by(name: "Konferensha")
|
|
844
|
-
return unless apartment
|
|
845
|
-
apartment.photos.destroy_all
|
|
846
|
-
apartment.destroy
|
|
847
|
-
end
|
|
848
|
-
end
|
|
849
|
-
SEED_MIGRATION
|
|
850
|
-
|
|
851
|
-
run "bundle exec rake db:migrate"
|
|
852
|
-
end
|
|
853
|
-
end
|
|
854
|
-
|
|
855
|
-
remove_file 'public/index.html'
|
|
856
|
-
|
|
857
|
-
say "- Apartment name list demo (field-level inline edit without _show)..."
|
|
858
|
-
inject_into_file "app/controllers/apartments_controller.rb",
|
|
859
|
-
"\n skip_load_and_authorize_resource only: :name_list\n\n def name_list\n authorize! :read, Apartment\n @apartments = Apartment.accessible_by(current_ability).order(:id).limit(10)\n end\n",
|
|
860
|
-
after: "set_tab :apartment\n"
|
|
861
|
-
|
|
862
|
-
example_views_root = File.join(GENERATOR_PATH, "lib/installer_templates/example_app_views")
|
|
863
|
-
Dir.glob(File.join(example_views_root, "**", "*")).sort.each do |abs|
|
|
864
|
-
next unless File.file?(abs)
|
|
865
|
-
rel = abs.delete_prefix(example_views_root + File::SEPARATOR).tr("\\", "/")
|
|
866
|
-
create_file File.join("app/views", rel), File.read(abs)
|
|
867
|
-
end
|
|
868
|
-
|
|
869
|
-
route 'get "apartments/name_list", to: "apartments#name_list", as: :apartment_name_list'
|
|
870
|
-
route "root :to => 'apartments#index'"
|
|
871
|
-
|
|
872
|
-
say "- Adding example app regression tests (bundle exec rails test)..."
|
|
873
|
-
example_tests_root = File.join(GENERATOR_PATH, "lib/installer_templates/example_app_tests")
|
|
874
|
-
Dir.glob(File.join(example_tests_root, "**", "*.rb")).sort.each do |abs|
|
|
875
|
-
rel = abs.delete_prefix(example_tests_root + File::SEPARATOR).tr("\\", "/")
|
|
876
|
-
create_file rel, File.read(abs)
|
|
877
|
-
end
|
|
878
|
-
|
|
879
|
-
say "\nDone! Example app (Photo + Apartment) is ready.", :yellow
|
|
880
|
-
say " bundle exec rails test # example regression tests", :yellow
|
|
881
|
-
say " bundle exec rails s # then http://localhost:3000/apartments", :yellow
|
|
882
|
-
say " More menu → Apartment names (first 10) # /apartments/name_list", :yellow
|
|
883
|
-
say " Log in: #{ENV["email"]} / #{ENV["password"]}", :yellow
|
|
884
|
-
end
|
|
885
|
-
# done!
|
|
886
|
-
say "\nDone! Now make your tables with 'bundle exec rails g inline_forms ...", :yellow
|