effective_developer 0.6.1 → 0.6.6

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: fc26ec312df01c35b4f0541fbb8fee46f5b93c32c615cd3c1f0c8c659b67110a
4
- data.tar.gz: 74a960c89033ea9531c3d0950e97d2e4bcac7c4d7a64ee4e9bc6cd1029e7ac51
3
+ metadata.gz: f3a6071b2027da0c4eb454ff1d2446f014c557a99cb495190c5594d2d9ecda81
4
+ data.tar.gz: 3bdec7afda572520e2ac59ba94ca47116ea4019a2b582cc71e6c4bd0e28e0467
5
5
  SHA512:
6
- metadata.gz: d63cb384af0910ac4f33e2696e4c72ab388fce049c31e35174bd940da6cbfc699e0bc5dcf821e72a60a1d000d6644b351ed231d9b5c5a180bcca8da7d71f5566
7
- data.tar.gz: efeb52d66a9c083038609146ac5901ed8cd9521ff5ef74e0cd7537d4ac1fe2d9609095a2d79d998150612c7e2e52ce11ab1f377b824cd6bac21a574d62c1701b
6
+ metadata.gz: 2c013f0c196b01b41860abe74341736f2a5bffbc45781a5190c38e68cb642145c5de1784b3473183a83e1b72fc97991be459f169f7d72165f37961c406a17115
7
+ data.tar.gz: 27a7d4470f8c02d76826e220861d9f43fa6cbe715059363a3fa010721878541586f6d831281114226806075adcb00bc994bb96deb1a1fdca49e0fe3addfbc365
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2018 Code and Effect Inc.
1
+ Copyright 2021 Code and Effect Inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -0,0 +1,17 @@
1
+ module Effective
2
+ class AssetReplacerJob < ::ApplicationJob
3
+
4
+ queue_as :default
5
+
6
+ if defined?(Sidekiq)
7
+ # The retry setting works. But none of these waits seem to. Still getting exponential backoff.
8
+ sidekiq_options retry: 2, retry_in: 10, wait: 10
9
+ sidekiq_retry_in { |count, exception| 10 }
10
+ end
11
+
12
+ def perform(attachment, box)
13
+ Effective::AssetReplacer.new.replace_attachment!(attachment, box)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,81 @@
1
+ # Writes the effective_resource do .. end block into the model file
2
+ module Effective
3
+ class Annotator
4
+
5
+ def initialize(resource: 'All', folders: 'app/models/')
6
+ @resources = Array(resource).map { |resource| resource.to_s.classify }
7
+ @folders = Array(folders)
8
+ end
9
+
10
+ def annotate!
11
+ @folders.each do |folder|
12
+ Dir.glob(folder + '**/*').each do |path|
13
+ next if File.directory?(path)
14
+
15
+ name = path.sub(folder, '').split('.')[0...-1].join('.')
16
+ resource = Effective::Resource.new(name)
17
+ klass = resource.klass
18
+
19
+ next if klass.blank?
20
+ next unless klass.ancestors.include?(ActiveRecord::Base)
21
+ next if klass.abstract_class?
22
+ next unless @resources.include?('All') || @resources.include?(klass.name)
23
+
24
+ annotate(resource, path)
25
+ end
26
+ end
27
+
28
+ puts 'All Done. Have a great day.'
29
+ true
30
+ end
31
+
32
+ private
33
+
34
+ def annotate(resource, path)
35
+ puts "Annotate: #{path}"
36
+
37
+ Effective::CodeWriter.new(path) do |writer|
38
+ index = find_insert_at(writer)
39
+ content = build_content(resource)
40
+
41
+ remove_existing(writer)
42
+ writer.insert(content, index)
43
+ end
44
+ end
45
+
46
+ def find_insert_at(writer)
47
+ index = writer.first { |line| line.include?('effective_resource do') || line.include?('structure do') }
48
+
49
+ index ||= begin
50
+ index = writer.first { |line| line.include?('validates :') || line.include?('scope :') || line.include?('def ') }
51
+ index - 1 if index
52
+ end
53
+
54
+ [1, index.to_i-1].max
55
+ end
56
+
57
+ def remove_existing(writer)
58
+ from = writer.first { |line| line.include?('effective_resource do') || line.include?('structure do') }
59
+ return unless from.present?
60
+
61
+ to = writer.first(from: from) { |line| line == 'end' || line == '# end' }
62
+ return unless to.present?
63
+
64
+ writer.remove(from: from, to: to+1)
65
+ end
66
+
67
+ def build_content(resource)
68
+ attributes = resource.klass_attributes(all: true)
69
+ atts = attributes.except(resource.klass.primary_key.to_sym, :created_at, :updated_at)
70
+
71
+ max = atts.map { |k, v| k.to_s.length }.max.to_i + 4
72
+ max = max + 1 unless (max % 2 == 0)
73
+
74
+ lines = atts.map { |k, v| k.to_s + (' ' * (max - k.to_s.length)) + ":#{v.first}" }
75
+ lines += ['', 'timestamps'] if attributes.key?(:created_at) && attributes.key?(:updated_at)
76
+
77
+ ['effective_resource do'] + lines + ['end']
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,156 @@
1
+ # Looks at the Effective::Asset and Effective::Attachments and converts to ActiveStorage
2
+ #
3
+ # 1. Put in the has_attached_files to each model to be upgraded
4
+ # 2. Remove the acts_as_asset_box
5
+
6
+ require 'timeout'
7
+
8
+ module Effective
9
+ class AssetReplacer
10
+ include ActiveStorage::Blob::Analyzable
11
+
12
+ BATCH_SIZE = 500
13
+ TIMEOUT = 120
14
+
15
+ def replace!(skip_existing: false)
16
+ verify!
17
+
18
+ attachments = attachments_to_process().to_a
19
+
20
+ while(true)
21
+ wait_for_active_job!
22
+
23
+ puts "\nEnqueuing #{attachments.length} attachments with ids #{attachments.first.id} to #{attachments.last.id}"
24
+
25
+ attachments.each do |attachment|
26
+ asset = attachment.asset
27
+ attachable = attachment.attachable
28
+ next if asset.blank? || attachable.blank?
29
+
30
+ box = attachment.box.singularize
31
+ boxes = attachment.box
32
+
33
+ one = attachable.respond_to?(box) && attachable.send(box).kind_of?(ActiveStorage::Attached::One)
34
+ many = attachable.respond_to?(boxes) && attachable.send(boxes).kind_of?(ActiveStorage::Attached::Many)
35
+ box = (one ? box : boxes)
36
+
37
+ if skip_existing
38
+ existing = Array(attachable.send(box))
39
+
40
+ if existing.any? { |obj| obj.respond_to?(:filename) && obj.filename.to_s == asset.file_name }
41
+ puts("Skipping existing #{attachable.class.name} #{attachable.id} #{box} #{asset.file_name}.")
42
+ next
43
+ end
44
+ end
45
+
46
+ Effective::AssetReplacerJob.perform_later(attachment, box)
47
+ end
48
+
49
+ attachments = attachments_to_process().where.not(id: attachments.map(&:id))
50
+ break if attachments.to_a.blank?
51
+
52
+ GC.start
53
+ end
54
+
55
+ puts "\nAll Done. Have a great day."
56
+ true
57
+ end
58
+
59
+ # This is called on the background by the AssetReplacerJob
60
+ def replace_attachment!(attachment, box)
61
+ raise('expected an Effective::Attachment') unless attachment.kind_of?(Effective::Attachment)
62
+ puts("Processing attachment ##{attachment.id}")
63
+
64
+ asset = attachment.asset
65
+ attachable = attachment.attachable
66
+
67
+ attachable.replacing_asset = true if attachable.respond_to?(:replacing_asset=)
68
+
69
+ Timeout.timeout(TIMEOUT) do
70
+ attachable.send(box).attach(
71
+ io: URI.open(asset.url),
72
+ filename: asset.file_name,
73
+ content_type: asset.content_type.presence,
74
+ identify: (asset.content_type.blank?)
75
+ )
76
+
77
+ attachment.update_column(:replaced, true)
78
+ end
79
+
80
+ true
81
+ end
82
+
83
+ def verify!
84
+ raise('expected effective assets') unless defined?(Effective::Asset)
85
+ raise('expected active storage') unless defined?(ActiveStorage)
86
+
87
+ unless Effective::Attachment.new.respond_to?(:replaced?)
88
+ raise('please add a replaced boolean to Effective::Attachment. add_column :attachments, :replaced, :boolean')
89
+ end
90
+
91
+ (Effective::Attachment.all.pluck(:attachable_type, :box).uniq).each do |name, boxes|
92
+ next if name.blank? || boxes.blank?
93
+
94
+ box = boxes.singularize
95
+
96
+ klass = name.safe_constantize
97
+ raise("invalid class #{klass}") unless klass.present?
98
+
99
+ instance = klass.new
100
+
101
+ if instance.respond_to?(:effective_assets)
102
+ raise("please remove acts_as_asset_box() from #{klass.name}")
103
+ end
104
+
105
+ unless instance.respond_to?(box) || instance.respond_to?(boxes)
106
+ raise("expected #{klass.name} to has_one_attached :#{box} or has_many_attached :#{boxes}")
107
+ end
108
+
109
+ one = instance.respond_to?(box) && instance.send(box).kind_of?(ActiveStorage::Attached::One)
110
+ many = instance.respond_to?(boxes) && instance.send(boxes).kind_of?(ActiveStorage::Attached::Many)
111
+
112
+ unless one.present? || many.present?
113
+ raise("expected #{klass.name} to has_one_attached :#{box} or has_many_attached :#{boxes}")
114
+ end
115
+ end
116
+
117
+ puts 'All attachment classes verified.'
118
+
119
+ true
120
+ end
121
+
122
+ def reset!
123
+ Effective::Attachment.update_all(replaced: false)
124
+ end
125
+
126
+ private
127
+
128
+ def wait_for_active_job!
129
+ while(true)
130
+ if(jobs = enqueued_jobs_count) > (BATCH_SIZE / 10)
131
+ print '.'; sleep(3)
132
+ else
133
+ break
134
+ end
135
+ end
136
+ end
137
+
138
+ # The last BATCH_SIZE attachments
139
+ def attachments_to_process
140
+ Effective::Attachment.all
141
+ .includes(:asset)
142
+ .where(replaced: [nil, false])
143
+ .reorder(id: :desc)
144
+ .limit(BATCH_SIZE)
145
+ end
146
+
147
+ def enqueued_jobs_count
148
+ if Rails.application.config.active_job.queue_adapter == :sidekiq
149
+ Sidekiq::Stats.new.enqueued.to_i
150
+ else
151
+ ActiveJob::Base.queue_adapter.enqueued_jobs.count
152
+ end
153
+ end
154
+
155
+ end
156
+ end
@@ -228,13 +228,17 @@ module Effective
228
228
  lines.each { |line| @changed = true if line.gsub!(source, target) }
229
229
  end
230
230
 
231
+ def remove(from:, to:)
232
+ raise('expected from to be less than to') unless from.present? && to.present? && (from < to)
233
+ @changed = true
234
+ (to - from).times { lines.delete_at(from) }
235
+ end
236
+
231
237
  def replace(index, content)
232
238
  @changed = true
233
239
  lines[index].replace(content.to_s)
234
240
  end
235
241
 
236
- private
237
-
238
242
  def write!
239
243
  return false unless changed?
240
244
 
@@ -245,6 +249,8 @@ module Effective
245
249
  true
246
250
  end
247
251
 
252
+ private
253
+
248
254
  def open?(content)
249
255
  stripped = ss(content)
250
256
 
@@ -0,0 +1,197 @@
1
+ # Upgrades simple_form_for to effective_form_with
2
+ module Effective
3
+ class FormUpgrader
4
+
5
+ def initialize(folder: 'app/views/')
6
+ @folders = Array(folder)
7
+ end
8
+
9
+ def upgrade!
10
+ @folders.each do |folder|
11
+ Dir.glob(folder + '**/*').each do |path|
12
+ next if File.directory?(path)
13
+ next unless path.include?('.html')
14
+
15
+ writer = Effective::CodeWriter.new(path)
16
+
17
+ name = path.split('/')[0...-1] - ['app', 'views']
18
+ resource = Effective::Resource.new(name)
19
+
20
+ if writer.find { |line| line.include?('simple_form_for') }
21
+ upgrade_simple_form(writer, resource)
22
+ elsif writer.find { |line| line.include?('semantic_form_for') }
23
+ upgrade_formtastic(writer, resource)
24
+ elsif writer.find { |line| line.include?('form_for') }
25
+ upgrade_form_for(writer, resource)
26
+ else
27
+ next # Nothing to do
28
+ end
29
+
30
+ writer.write!
31
+ end
32
+ end
33
+
34
+ puts 'All Done. Have a great day.'
35
+ true
36
+ end
37
+
38
+ private
39
+
40
+ SIMPLE_FORM_FOR_REGEX = /simple_form_for( |\()(\[:[^,]+, ?[^,]+\])?(([^,]+),)?.+do \|(\w+)\|/
41
+ SIMPLE_FORM_INPUT_ATTRIBUTE = /\.input( |\():(\w+)/
42
+ SIMPLE_FORM_INPUT_AS_ONE = /(as: :(\w+))/
43
+ SIMPLE_FORM_INPUT_AS_TWO = /(:as => :(\w+))/
44
+ SIMPLE_FORM_INPUT_COLLECTION_ONE = /(collection: ([^,]+?))(,|$)/
45
+ SIMPLE_FORM_INPUT_COLLECTION_TWO = /(:collection => :([^,]+?))(,|$)/
46
+
47
+ def upgrade_simple_form(writer, resource)
48
+ puts "Upgrading simple form: #{writer.filename}"
49
+
50
+ letter = nil
51
+ model = nil
52
+
53
+ # Replace simple_form_for
54
+ writer.all { |line| line.include?('simple_form_for') }.each do |line|
55
+ content = writer.lines[line]
56
+ matched = content.match(SIMPLE_FORM_FOR_REGEX)
57
+ raise("unable to match simple_form_for from:\n#{content}") unless matched.present?
58
+
59
+ original = matched[0]
60
+ model = matched[2] || matched[4]
61
+ letter = matched[5]
62
+
63
+ raise("unable to determine simple_form_for subject from:\n#{content}") unless original && model && letter
64
+
65
+ content.sub!(original, "effective_form_with(model: #{model}) do |#{letter}|")
66
+ writer.replace(line, content)
67
+ end
68
+
69
+ # Try to figure out klass again if its missing from filename
70
+ if resource.klass.blank? && model.present?
71
+ name = model.sub('[', '').sub(']', '').sub(' ', '').split(',').map do |value|
72
+ value.sub('current_', '').sub('@', '').sub(':', '')
73
+ end
74
+
75
+ resource = Effective::Resource.new(name)
76
+ end
77
+
78
+ if resource.klass.blank? && writer.filename.include?('/devise/')
79
+ resource = Effective::Resource.new('user')
80
+ end
81
+
82
+ if resource.klass.blank?
83
+ puts " => Warning: Unable to determine klass of #{model}"
84
+ end
85
+
86
+ # Replace .input
87
+ writer.all { |line| line.include?('.input :') }.each do |line|
88
+ content = writer.lines[line]
89
+ attribute = content.match(SIMPLE_FORM_INPUT_ATTRIBUTE)
90
+ raise("unable to match simple_form_for input attribute from\n#{content}") unless attribute.present?
91
+
92
+ as = content.match(SIMPLE_FORM_INPUT_AS_ONE) || content.match(SIMPLE_FORM_INPUT_AS_TWO)
93
+ collection = content.match(SIMPLE_FORM_INPUT_COLLECTION_ONE) || content.match(SIMPLE_FORM_INPUT_COLLECTION_TWO)
94
+
95
+ if as.present?
96
+ content.sub!(",#{as[0]}", '')
97
+ content.sub!(", #{as[0]}", '')
98
+ end
99
+
100
+ if collection.present?
101
+ content.sub!(",#{collection[0]}", ',')
102
+ content.sub!(", #{collection[0]}", ',')
103
+ content.sub!(attribute[0], "#{attribute[0]} #{collection[2]},")
104
+ end
105
+
106
+ input_type = find_input_type(resource: resource, attribute: attribute[2], as: (as[2] if as))
107
+
108
+ content.sub!('input', input_type)
109
+ writer.replace(line, content)
110
+ end
111
+
112
+ # Replace simple_fields_for
113
+ writer.all { |line| line.include?(".simple_fields_for") }.each do |line|
114
+ content = writer.lines[line]
115
+
116
+ content.sub!(".simple_fields_for", ".has_many")
117
+ writer.replace(line, content)
118
+ end
119
+
120
+ # Replace f.submit
121
+ writer.all { |line| line.include?("#{letter}.submit") }.each do |line|
122
+ content = writer.lines[line]
123
+
124
+ content.sub!("#{letter}.submit", "#{letter}.save")
125
+ writer.replace(line, content)
126
+ end
127
+
128
+ # Replace f.button :submit
129
+ writer.all { |line| line.include?(".button :submit,") }.each do |line|
130
+ content = writer.lines[line]
131
+
132
+ content.sub!(".button :submit,", ".submit")
133
+ writer.replace(line, content)
134
+ end
135
+
136
+ # Replace .form-actions
137
+ writer.all { |line| line == '.form-actions' }.each do |line|
138
+ content = writer.lines[line]
139
+
140
+ content.sub!('.form-actions', "= #{letter}.submit do")
141
+ writer.replace(line, content)
142
+ end
143
+ end
144
+
145
+ def upgrade_formtastic(writer, resource)
146
+ puts "Detected formtastic: #{writer.filename}"
147
+ end
148
+
149
+ def upgrade_form_for(writer, resource)
150
+ puts "Detected rails form_for: #{writer.filename}"
151
+ end
152
+
153
+ def find_input_type(attribute:, resource:, as: nil)
154
+ input_type = (as || resource.sql_type(attribute)).to_s
155
+
156
+ case input_type
157
+ when 'asset_box_simple_form' then 'file_field'
158
+ when 'belongs_to', 'belongs_to_polymorphic' then 'select'
159
+ when 'boolean' then 'check_box'
160
+ when 'check_boxes' then 'checks'
161
+ when 'date' then 'date_field'
162
+ when 'datetime' then 'datetime_field'
163
+ when 'decimal' then 'float_field'
164
+ when 'effective_ckeditor_text_area' then 'rich_text_area' # I guess
165
+ when 'effective_date_picker' then 'date_field'
166
+ when 'effective_date_time_picker' then 'datetime_field'
167
+ when 'effective_email' then 'email_field'
168
+ when 'effective_price' then 'price_field'
169
+ when 'effective_radio_buttons' then 'radios'
170
+ when 'effective_select' then 'select'
171
+ when 'effective_static_control' then 'static_field'
172
+ when 'effective_tel' then 'phone_field'
173
+ when 'effective_time_picker' then 'time_field'
174
+ when 'effective_url' then 'url_field'
175
+ when 'email' then 'email_field'
176
+ when 'file' then 'file_field'
177
+ when 'hidden' then 'hidden_field'
178
+ when 'integer' then 'number_field'
179
+ when 'number' then 'number_field'
180
+ when 'password' then 'password_field'
181
+ when 'phone' then 'phone_field'
182
+ when 'price' then 'price_field'
183
+ when 'radio_buttons' then 'radios'
184
+ when 'search' then 'search_field'
185
+ when 'select' then 'select'
186
+ when 'static_control' then 'static_field'
187
+ when 'string' then 'text_field'
188
+ when 'tel', 'telephone' then 'phone_field'
189
+ when 'text' then 'text_area'
190
+ when 'url' then 'url_field'
191
+ else
192
+ raise("unknown input type #{input_type} (for attribute :#{attribute})")
193
+ end
194
+ end
195
+
196
+ end
197
+ end
@@ -32,7 +32,5 @@ module Effective
32
32
  retval
33
33
  end
34
34
 
35
-
36
35
  end
37
-
38
36
  end
@@ -0,0 +1,66 @@
1
+ # Replaces the [snippet_x] in all effective regions with static content
2
+
3
+ module Effective
4
+ class SnippetReplacer
5
+ include ActiveStorage::Blob::Analyzable
6
+ include ActionView::Helpers::UrlHelper
7
+ include ActionView::Helpers::AssetTagHelper
8
+
9
+ def replace!
10
+ raise('expected effective regions') unless defined?(Effective::Region)
11
+ raise('expected effective assets') unless defined?(Effective::Asset)
12
+ raise('expected active storage') unless defined?(ActiveStorage)
13
+
14
+ Effective::Region.with_snippets.find_each do |region|
15
+ region.snippet_objects.each do |snippet|
16
+ print('.')
17
+
18
+ begin
19
+ case snippet.class.name
20
+ when 'Effective::Snippets::EffectiveAsset'
21
+ replace_effective_asset(region, snippet)
22
+ else
23
+ raise("unsupported snippet: #{snippet.class.name}")
24
+ end
25
+ rescue => e
26
+ puts "\nError: #{e}\n"
27
+ remove_snippet(region, snippet)
28
+ end
29
+ end
30
+
31
+ region.save!
32
+ end
33
+
34
+ puts 'All Done. Have a great day.'
35
+ true
36
+ end
37
+
38
+ private
39
+
40
+ def replace_effective_asset(region, snippet)
41
+ asset = snippet.asset
42
+ raise("Effective:Asset id=#{snippet.asset_id || 'none'} does not exist") unless asset.present?
43
+
44
+ blob = ActiveStorage::Blob.create_and_upload!(io: URI.open(asset.url), filename: asset.file_name)
45
+ url = Rails.application.routes.url_helpers.rails_blob_url(blob, only_path: true)
46
+
47
+ content = if asset.image?
48
+ image_tag(url, class: snippet.html_class, alt: snippet.link_title)
49
+ else
50
+ link_to(snippet.link_title, url, class: snippet.html_class, title: snippet.link_title)
51
+ end
52
+
53
+ region.content.sub!("[#{snippet.id}]", content.to_s)
54
+ region.snippets.delete(snippet.id)
55
+
56
+ true
57
+ end
58
+
59
+ def remove_snippet(region, snippet)
60
+ region.content.sub!("[#{snippet.id}]", '')
61
+ region.snippets.delete(snippet.id)
62
+ end
63
+
64
+
65
+ end
66
+ end
@@ -2,6 +2,9 @@ module EffectiveDeveloper
2
2
  class Engine < ::Rails::Engine
3
3
  engine_name 'effective_developer'
4
4
 
5
+ config.autoload_paths += Dir["#{config.root}/models/jobs/"]
6
+ config.eager_load_paths += Dir["#{config.root}/models/jobs/"]
7
+
5
8
  # Set up our default configuration options.
6
9
  initializer 'effective_developer.defaults', before: :load_config_initializers do |app|
7
10
  # Set up our defaults, as per our initializer template
@@ -1,3 +1,3 @@
1
1
  module EffectiveDeveloper
2
- VERSION = '0.6.1'.freeze
2
+ VERSION = '0.6.6'.freeze
3
3
  end
@@ -0,0 +1,8 @@
1
+ # bundle exec rake annotate
2
+ # bundle exec rake annotate[user]
3
+
4
+ desc 'Adds an effective_resources do .. end block to all ActiveRecord model files'
5
+ task :annotate, [:resource] => :environment do |t, args|
6
+ args.with_defaults(resource: 'all')
7
+ Effective::Annotator.new(resource: args.resource).annotate!
8
+ end
@@ -50,7 +50,7 @@ namespace :pg do
50
50
  end
51
51
 
52
52
  # Hatchbox mode
53
- if (ENV['HATCHBOX_IP'] || args[:remote]).count('.') == 3
53
+ if (ENV['HATCHBOX_IP'] || args[:remote]).to_s.count('.') == 3
54
54
  args.with_defaults(
55
55
  remote: ENV.fetch('HATCHBOX_IP'),
56
56
  app: ENV['HATCHBOX_APP'] || `pwd`.split('/').last.chomp,
@@ -0,0 +1,5 @@
1
+ # bundle exec rake replace_effective_assets
2
+ desc 'Replaces effective_assets with ActiveStorage'
3
+ task :replace_effective_assets => :environment do
4
+ Effective::AssetReplacer.new.replace!
5
+ end
@@ -0,0 +1,5 @@
1
+ # bundle exec rake replace_effective_snippets
2
+ desc 'Replaces effective_assets snippets with ActiveStorage uploads'
3
+ task :replace_effective_snippets => :environment do
4
+ Effective::SnippetReplacer.new.replace!
5
+ end
@@ -0,0 +1,7 @@
1
+ # bundle exec rake upgrade_forms
2
+ # bundle exec rake upgrade_forms[app/views/admin/]
3
+ desc 'Upgrades simple_form_for to effective_form_with'
4
+ task :upgrade_forms, [:folder] => :environment do |t, args|
5
+ args.with_defaults(folder: 'app/views/')
6
+ Effective::FormUpgrader.new(folder: args.folder).upgrade!
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_developer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-15 00:00:00.000000000 Z
11
+ date: 2021-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -48,10 +48,15 @@ files:
48
48
  - MIT-LICENSE
49
49
  - README.md
50
50
  - Rakefile
51
+ - app/jobs/effective/asset_replacer_job.rb
52
+ - app/models/effective/annotator.rb
53
+ - app/models/effective/asset_replacer.rb
51
54
  - app/models/effective/code_writer.rb
52
55
  - app/models/effective/csv_importer.rb
56
+ - app/models/effective/form_upgrader.rb
53
57
  - app/models/effective/live_generator.rb
54
58
  - app/models/effective/profiler.rb
59
+ - app/models/effective/snippet_replacer.rb
55
60
  - config/effective_developer.rb
56
61
  - lib/effective_developer.rb
57
62
  - lib/effective_developer/engine.rb
@@ -95,10 +100,14 @@ files:
95
100
  - lib/scaffolds/importers/csv_importer.rb
96
101
  - lib/scaffolds/models/model.rb
97
102
  - lib/scaffolds/views/_resource.html.haml
103
+ - lib/tasks/annotate.rake
98
104
  - lib/tasks/effective_csv_importer.rake
99
105
  - lib/tasks/pg_pull.rake
100
106
  - lib/tasks/rename_class.rake
107
+ - lib/tasks/replace_effective_assets.rake
108
+ - lib/tasks/replace_effective_snippets.rake
101
109
  - lib/tasks/reset_pk_sequence.rake
110
+ - lib/tasks/upgrade_forms.rake
102
111
  - lib/tasks/validate.rake
103
112
  homepage: https://github.com/code-and-effect/effective_developer
104
113
  licenses: