effective_developer 0.5.5 → 0.6.4

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: 4e4f396c9ab5a37dfca3a796aa10d204827c3e34de709bf9d1d8ce1db2af5201
4
- data.tar.gz: 4a6034049262d3f56c850dc6a2bc05de3f29201debd3b26ec3ae22851532bfa7
3
+ metadata.gz: 3d495b7c0e191545d03edac8297a4e6d70b0e73c60e3e750a7746a43a9c45ae0
4
+ data.tar.gz: fda29335818a87f2e76bd21c4f8018aab29833082682ca931339a127d7a9d1d0
5
5
  SHA512:
6
- metadata.gz: eaeec872eeb393fe930c08ea2a14d8ebd17af0e9df9a4ac2c7fdb21047b2888386c6d3b4f5afefd2ecd6e78d11dc81816c6ad6ae83e56e5af6877b4a6b903354
7
- data.tar.gz: ed971e8f872fa301fbb1dde42fac07f704f1e0eec46b53fb1250f634cc67e7787362a829d958f160c9084195f459daedd74d4fae6015f2012759318d33c49c64
6
+ metadata.gz: 4bbed134e5bc6f0b78231501cd866a581a878dd4b5734ca74b480bfc49bc014c25a5e2a23074a62ccdc4ac90d40220ed6a7f5fb42a8c68c44979fd909d427635
7
+ data.tar.gz: b97abb74e30855a39100c9ca66785e89148bfda8e1cc427170b67767007078a5818e194adf34541806d6c4809a3b45bf1bfba97305bff663c4643c21c319d347
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module EffectiveDeveloper
2
- VERSION = '0.5.5'.freeze
2
+ VERSION = '0.6.4'.freeze
3
3
  end
@@ -15,20 +15,26 @@ module Effective
15
15
 
16
16
  argument :actions, type: :array, default: ['crud'], banner: 'action action'
17
17
 
18
+ def validate_resource
19
+ exit unless resource_valid?
20
+ end
21
+
18
22
  def invoke_ability
19
23
  say_status :invoke, :ability, :white
20
24
  end
21
25
 
22
26
  def create_ability
23
- unless File.exists?('app/models/ability.rb')
27
+ unless File.exists?(resource.abilities_file)
24
28
  say_status(:skipped, :ability, :yellow) and return
25
29
  end
26
30
 
27
- Effective::CodeWriter.new('app/models/ability.rb') do |w|
28
- if w.find { |line, depth| depth == 2 && line == ability }
31
+ Effective::CodeWriter.new(resource.abilities_file) do |w|
32
+ if w.find { |line, depth| (depth == 2 || depth == 3) && line == ability }
29
33
  say_status :identical, ability, :blue
30
34
  else
31
- w.insert_into_first(ability) { |line, depth| line.start_with?('def initialize') }
35
+ w.insert_into_first(ability + "\n") { |line, depth| line.start_with?('def initialize') || line.end_with?('abilities(user)') }
36
+
37
+ say_status :ability, ability
32
38
  end
33
39
  end
34
40
  end
@@ -55,7 +61,13 @@ module Effective
55
61
  abilities = '[' + abilities.map { |action| ':' + action }.join(', ') + ']'
56
62
  end
57
63
 
58
- "can #{abilities}, #{resource.class_name}"
64
+ name = if resource.module_name.present?
65
+ resource.class_name.split('::').last
66
+ else
67
+ resource.class_name
68
+ end
69
+
70
+ "can #{abilities}, #{name}"
59
71
  )
60
72
  end
61
73
  end
@@ -17,6 +17,10 @@ module Effective
17
17
  argument :actions, type: :array, default: ['crud'], banner: 'action action'
18
18
  class_option :attributes, type: :array, default: [], desc: 'Included permitted params, otherwise read from model'
19
19
 
20
+ def validate_resource
21
+ exit unless resource_valid?
22
+ end
23
+
20
24
  def assign_actions
21
25
  @actions = invoked_actions
22
26
  end
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Generates a datatable
6
6
  # rails generate effective:datatable Thing
7
- # rails generate effective:controller Thing name:string description:text
7
+ # rails generate effective:datatable Thing name:string description:text
8
8
 
9
9
  module Effective
10
10
  module Generators
@@ -18,6 +18,10 @@ module Effective
18
18
  argument :actions, type: :array, default: ['crud'], banner: 'action action'
19
19
  class_option :attributes, type: :array, default: [], desc: 'Included permitted params, otherwise read from model'
20
20
 
21
+ def validate_resource
22
+ exit unless resource_valid?
23
+ end
24
+
21
25
  def assign_attributes
22
26
  @attributes = invoked_attributes.presence || resource_attributes(all: true)
23
27
  self.class.send(:attr_reader, :attributes)
@@ -32,7 +36,10 @@ module Effective
32
36
  say_status(:skipped, :datatable, :yellow) and return
33
37
  end
34
38
 
35
- template 'datatables/datatable.rb', resource.datatable_file
39
+ with_resource_tenant do
40
+ template 'datatables/datatable.rb', resource.datatable_file
41
+ end
42
+
36
43
  end
37
44
 
38
45
  end
@@ -20,6 +20,10 @@ module Effective
20
20
  argument :attributes, type: :array, default: [], banner: 'field[:type] field[:type]'
21
21
  class_option :tabbed, type: :string, default: 'true'
22
22
 
23
+ def validate_resource
24
+ exit unless resource_valid?
25
+ end
26
+
23
27
  def assign_attributes
24
28
  @attributes = invoked_attributes.presence || resource_attributes
25
29
  self.class.send(:attr_reader, :attributes)
@@ -30,15 +34,19 @@ module Effective
30
34
  end
31
35
 
32
36
  def create_flat_form
33
- if options[:tabbed] == 'false'
34
- template 'forms/flat/_form.html.haml', resource.view_file('form', partial: true)
37
+ with_resource_tenant do
38
+ if options[:tabbed] == 'false'
39
+ template 'forms/flat/_form.html.haml', resource.view_file('form', partial: true)
40
+ end
35
41
  end
36
42
  end
37
43
 
38
44
  def create_tabbed_form
39
- if options[:tabbed] == 'true'
40
- template 'forms/tabbed/_form.html.haml', resource.view_file('form', partial: true)
41
- template 'forms/tabbed/_form_resource.html.haml', resource.flat_view_file("form_#{resource.name}", partial: true)
45
+ with_resource_tenant do
46
+ if options[:tabbed] == 'true'
47
+ template 'forms/tabbed/_form.html.haml', resource.view_file('form', partial: true)
48
+ template 'forms/tabbed/_form_resource.html.haml', resource.view_file("form_#{resource.name}", partial: true)
49
+ end
42
50
  end
43
51
  end
44
52
 
@@ -4,6 +4,24 @@ module Effective
4
4
 
5
5
  protected
6
6
 
7
+ # This is kind of a validate for the resource
8
+ def resource_valid?
9
+ if resource.klass.blank?
10
+ say_status(:error, "Unable to find resource klass from #{name}", :red)
11
+ return false
12
+ end
13
+
14
+ true
15
+ end
16
+
17
+ def with_resource_tenant(&block)
18
+ if defined?(Tenant) && resource.tenant.present?
19
+ Tenant.as(resource.tenant) { yield }
20
+ else
21
+ yield
22
+ end
23
+ end
24
+
7
25
  def resource
8
26
  @resource ||= Effective::Resource.new(name)
9
27
  end
@@ -55,24 +73,26 @@ module Effective
55
73
  end
56
74
 
57
75
  def resource_attributes(all: false)
58
- klass_attributes = resource.klass_attributes(all: all)
76
+ with_resource_tenant do
77
+ klass_attributes = resource.klass_attributes(all: all)
59
78
 
60
- if klass_attributes.blank?
61
- if ActiveRecord::Migration.respond_to?(:check_pending!)
62
- pending = (ActiveRecord::Migration.check_pending! rescue true)
63
- else
64
- pending = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations(ActiveRecord::Migrator.migrations_paths)).pending_migrations.present?
65
- end
79
+ if klass_attributes.blank?
80
+ if ActiveRecord::Migration.respond_to?(:check_pending!)
81
+ pending = (ActiveRecord::Migration.check_pending! rescue true)
82
+ else
83
+ pending = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations(ActiveRecord::Migrator.migrations_paths)).pending_migrations.present?
84
+ end
66
85
 
67
- if pending
68
- migrate = ask("Unable to read the attributes of #{resource.klass || resource.name}. There are pending migrations. Run db:migrate now? [y/n]")
69
- system('bundle exec rake db:migrate') if migrate.to_s.include?('y')
86
+ if pending
87
+ migrate = ask("Unable to read the attributes of #{resource.klass || resource.name}. There are pending migrations. Run db:migrate now? [y/n]")
88
+ system('bundle exec rake db:migrate') if migrate.to_s.include?('y')
89
+ end
90
+
91
+ klass_attributes = resource.klass_attributes(all: all)
70
92
  end
71
93
 
72
- klass_attributes = resource.klass_attributes(all: all)
94
+ klass_attributes.presence || resource.model_attributes(all: all)
73
95
  end
74
-
75
- klass_attributes.presence || resource.model_attributes(all: all)
76
96
  end
77
97
 
78
98
  end
@@ -13,6 +13,10 @@ module Effective
13
13
 
14
14
  desc 'Adds a menu link to an existing _navbar.html.haml'
15
15
 
16
+ def validate_resource
17
+ exit unless resource_valid?
18
+ end
19
+
16
20
  def invoke_menu
17
21
  say_status :invoke, :menu, :white
18
22
  end
@@ -22,7 +26,7 @@ module Effective
22
26
  return unless resource.namespaces.blank?
23
27
 
24
28
  begin
25
- Effective::CodeWriter.new('app/views/layouts/_navbar.html.haml') do |w|
29
+ Effective::CodeWriter.new(resource.menu_file) do |w|
26
30
  if w.find { |line, _| line == menu_content.second.strip }
27
31
  say_status :identical, menu_path, :blue
28
32
  else
@@ -44,7 +48,7 @@ module Effective
44
48
  return unless resource.namespaces == ['admin']
45
49
 
46
50
  begin
47
- Effective::CodeWriter.new('app/views/layouts/_navbar_admin.html.haml') do |w|
51
+ Effective::CodeWriter.new(resource.admin_menu_file) do |w|
48
52
  if w.find { |line, _| line == menu_content.second.strip }
49
53
  say_status :identical, menu_path, :blue
50
54
  else
@@ -72,7 +76,8 @@ module Effective
72
76
  end
73
77
 
74
78
  def menu_path
75
- [resource.namespace, resource.plural_name, 'path'].compact * '_'
79
+ path = [resource.namespace, resource.plural_name, 'path'].compact * '_'
80
+ resource.tenant.present? ? "#{resource.tenant}.#{path}" : path
76
81
  end
77
82
  end
78
83
  end
@@ -16,21 +16,47 @@ module Effective
16
16
  desc 'Creates a migration.'
17
17
 
18
18
  argument :attributes, type: :array, default: [], banner: 'field[:type] field[:type]'
19
+ class_option :database, type: :string, desc: "Database to generate the migration for"
20
+
21
+ def validate_resource
22
+ exit unless resource_valid?
23
+ end
19
24
 
20
25
  def invoke_migration
21
26
  say_status :invoke, :migration, :white
22
27
  end
23
28
 
29
+ # rails generate effective:migration courses body:text --database example
24
30
  def create_migration
25
31
  if invoked_attributes.present?
26
- Rails::Generators.invoke('migration', ["create_#{plural_name}"] + (invokable(invoked_attributes) | timestamps))
27
- elsif resource.klass_attributes.present?
28
- raise 'klass_attributes already exist. We cant migrate (yet). Exiting.'
29
- elsif resource.model_attributes.present?
30
- Rails::Generators.invoke('migration', ["create_#{plural_name}"] + invokable(resource.model_attributes))
31
- else
32
- raise 'You need to specify some attributes or have a model file present'
32
+ args = ["create_#{plural_name}"] + (invokable(invoked_attributes) | timestamps)
33
+ args += ["--database", options['database']] if options['database']
34
+ Rails::Generators.invoke('migration', args)
35
+ return
36
+ end
37
+
38
+ return if with_resource_tenant do
39
+ table_name = resource.klass.table_name
40
+
41
+ if ActiveRecord::Base.connection.table_exists?(table_name)
42
+ say_status(:error, "#{table_name} table already exist. We can't migrate (yet). Exiting.", :red)
43
+ true
44
+ end
33
45
  end
46
+
47
+ if resource.model_attributes.blank?
48
+ say_status(:error, "No model attributes present. Please add the effective_resource do ... end block and try again", :red)
49
+ return
50
+ end
51
+
52
+ args = ["create_#{plural_name}"] + invokable(resource.model_attributes) - timestamps
53
+ args += ["--database", options['database']] if options['database']
54
+
55
+ if options['database'].blank? && defined?(Tenant)
56
+ args += ["--database", resource.klass.name.split('::').first.downcase]
57
+ end
58
+
59
+ Rails::Generators.invoke('migration', args)
34
60
  end
35
61
 
36
62
  protected
@@ -15,6 +15,10 @@ module Effective
15
15
 
16
16
  argument :actions, type: :array, default: ['crud'], banner: 'action action'
17
17
 
18
+ def validate_resource
19
+ exit unless resource_valid?
20
+ end
21
+
18
22
  def invoke_route
19
23
  say_status :invoke, :route, :white
20
24
  end
@@ -22,7 +26,7 @@ module Effective
22
26
  def create_route
23
27
  blocks = []
24
28
 
25
- Effective::CodeWriter.new('config/routes.rb') do |w|
29
+ Effective::CodeWriter.new(resource.routes_file) do |w|
26
30
  resource.namespaces.each do |namespace|
27
31
  index = nil
28
32
 
@@ -54,7 +58,7 @@ module Effective
54
58
 
55
59
  def resources
56
60
  @resources ||= (
57
- resources = "resources :#{plural_name}"
61
+ resources = "resources :#{resource.plural_name}"
58
62
 
59
63
  if ((crud_actions - ['show']) == invoked_actions)
60
64
  resources << ', except: [:show]'
@@ -16,6 +16,10 @@ module Effective
16
16
  argument :actions, type: :array, default: ['crud'], banner: 'action action'
17
17
  class_option :attributes, type: :array, default: [], desc: 'Included form attributes, otherwise read from model'
18
18
 
19
+ def validate_resource
20
+ exit unless resource_valid?
21
+ end
22
+
19
23
  def assign_attributes
20
24
  @attributes = (invoked_attributes.presence || resource_attributes).except(:archived)
21
25
  self.class.send(:attr_reader, :attributes)
@@ -1,3 +1,11 @@
1
- class <%= resource.namespaced_class_name.pluralize %>Controller < <%= [resource.namespace.try(:classify).presence, ApplicationController].compact.join('::') %>
1
+ <% if resource.module_name.present? -%>
2
+ module <%= resource.module_name %>
3
+ class <%= resource.module_namespaced %>Controller < <%= resource.module_namespace %>ApplicationController
4
+ include Effective::CrudController
5
+ end
6
+ end
7
+ <% else -%>
8
+ class <%= resource.namespaced_class_name.pluralize %>Controller < <%= resource.module_namespace %>ApplicationController
2
9
  include Effective::CrudController
3
10
  end
11
+ <% end -%>
@@ -1,5 +1,40 @@
1
- class <%= resource.namespaced_class_name.pluralize %>Datatable < Effective::Datatable
1
+ <% if resource.module_name.present? -%>
2
+ module <%= resource.module_name %>
3
+ class <%= resource.module_namespaced %>Datatable < Effective::Datatable
4
+ datatable do
5
+ order :updated_at
6
+
7
+ col :updated_at, visible: false
8
+ col :created_at, visible: false
9
+ col :id, visible: false
2
10
 
11
+ <% if resource.belong_tos.present? || resource.has_anys.present? -%>
12
+ <% resource.belong_tos.each do |reference| -%>
13
+ col :<%= reference.name %>
14
+ <% end -%>
15
+ <% resource.has_anys.each do |reference| -%>
16
+ col :<%= reference.name %>
17
+ <% end -%>
18
+
19
+ <% end -%>
20
+ <% attributes.except(:created_at, :updated_at, :id, :archived).each do |name, _| -%>
21
+ col :<%= name %>
22
+ <% end -%>
23
+ <% if attributes.key?(:archived) -%>
24
+
25
+ col :archived, search: { value: false }
26
+ <% end -%>
27
+
28
+ actions_col
29
+ end
30
+
31
+ collection do
32
+ <%= resource.class_name %>.deep.all
33
+ end
34
+ end
35
+ end
36
+ <% else -%>
37
+ class <%= resource.namespaced_class_name.pluralize %>Datatable < Effective::Datatable
3
38
  datatable do
4
39
  order :updated_at
5
40
 
@@ -30,5 +65,5 @@ class <%= resource.namespaced_class_name.pluralize %>Datatable < Effective::Data
30
65
  collection do
31
66
  <%= resource.class_name %>.deep.all
32
67
  end
33
-
34
68
  end
69
+ <% end -%>
@@ -1,6 +1,6 @@
1
1
  = tabs do
2
2
  = tab '<%= resource.human_name.titleize %>' do
3
- = render '/<%= resource.plural_name %>/form_<%= resource.name %>', <%= resource.name %>: <%= resource.name %>, namespace: <%= resource.namespace ? ":#{resource.namespace}" : 'nil' %>
3
+ = render '<%= resource.view_file_path("form_#{resource.name}") %>', <%= resource.name %>: <%= resource.name %>
4
4
 
5
5
  <%- if resource.nested_resources.present? || resource.instance.respond_to?(:log_changes_datatable) %>
6
6
  - if <%= resource.name %>.persisted?
@@ -1,4 +1,8 @@
1
- = effective_form_with(model: [(namespace if defined?(namespace)), <%= resource.name %>]) do |f|
1
+ <% if resource.namespace.present? -%>
2
+ = effective_form_with(model: [:<%= resource.namespace %>, <%= resource.name %>]) do |f|
3
+ <% else -%>
4
+ = effective_form_with(model: <%= resource.name %>) do |f|
5
+ <% end -%>
2
6
  <% resource.belong_tos.each do |reference| -%>
3
7
  <%= render_field(reference, depth: 1) %>
4
8
  <% 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
@@ -4,14 +4,35 @@ namespace :pg do
4
4
  # bundle exec rake pg:pull
5
5
  # bundle exec rake pg:pull[staging]
6
6
  # bundle exec rake pg:pull[158.204.33.124]
7
+
8
+ # bundle exec rake pg:pull
9
+ # bundle exec rake pg:pull[staging]
10
+ # bundle exec rake pg:pull[158.204.33.124]
11
+ # bundle exec rake pg:pull filename=latest.dump database=example
12
+ # DATABASE=example bundle exec rake pg:load
7
13
  desc 'Creates a new backup on remote server and downloads it to latest.dump'
8
14
  task :pull, [:remote] => :environment do |t, args|
15
+ defaults = { database: nil, filename: (ENV['DATABASE'] || 'latest') + '.dump' }
16
+ env_keys = { database: ENV['DATABASE'], filename: ENV['FILENAME'] }
17
+ keywords = ARGV.map { |a| a.split('=') if a.include?('=') }.compact.inject({}) { |h, (k, v)| h[k.to_sym] = v; h }
18
+ args.with_defaults(defaults.compact.merge(env_keys.compact).merge(keywords))
19
+
20
+ # Validate Config
21
+ config = ActiveRecord::Base.configurations[Rails.env]
22
+ configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
23
+
24
+ if configs.length > 1 && args.database.blank?
25
+ puts "Multiple database configs exist for #{Rails.env} environment."
26
+ puts "Please run bundle exec rake pg:pull database=x"
27
+ puts "Where x is one of: #{configs.map { |config| config.name }.to_sentence}"
28
+ exit
29
+ end
9
30
 
10
31
  # Heroku mode
11
32
  if `git remote -v | grep heroku`.length > 0
12
33
  args.with_defaults(remote: 'heroku')
13
34
 
14
- puts "=== Pulling remote '#{args.remote}' database into latest.dump"
35
+ puts "=== Pulling remote '#{args.remote}' #{args.database} database into #{args.filename}"
15
36
 
16
37
  # Create a backup on heroku
17
38
  unless system("heroku pg:backups:capture --remote #{args.remote}")
@@ -19,41 +40,41 @@ namespace :pg do
19
40
  end
20
41
 
21
42
  # Download it to local
22
- unless system("curl -o latest.dump `heroku pg:backups:public-url --remote #{args.remote}`")
43
+ unless system("curl -o #{args.filename} `heroku pg:backups:public-url --remote #{args.remote}`")
23
44
  abort("Error downloading database")
24
45
  end
25
46
 
26
47
  # Load it
27
- Rake::Task['pg:load'].invoke
48
+ Rake::Task['pg:load'].invoke(*args)
28
49
  exit
29
50
  end
30
51
 
31
52
  # Hatchbox mode
32
- if (ENV['HATCHBOX_IP'] || args[:remote]).count('.') == 3
53
+ if (ENV['HATCHBOX_IP'] || args[:remote]).to_s.count('.') == 3
33
54
  args.with_defaults(
34
55
  remote: ENV.fetch('HATCHBOX_IP'),
35
56
  app: ENV['HATCHBOX_APP'] || `pwd`.split('/').last.chomp,
36
57
  user: ENV['HATCHBOX_USER'] || 'deploy'
37
58
  )
38
59
 
39
- puts "=== Pulling hatchbox '#{args.remote}' #{args.app} database into latest.dump"
60
+ puts "=== Pulling hatchbox '#{args.remote}' #{args.app} #{args.database} database into #{args.filename}"
40
61
 
41
62
  # SSH into hatchbox and call rake pg:save there to create latest.dump
42
- unless(result = `ssh #{args.user}@#{args.remote} << EOF
63
+ unless(result = `ssh -T #{args.user}@#{args.remote} << EOF
43
64
  cd ~/#{args.app}/current/
44
- bundle exec rake pg:save[latest.dump]
65
+ bundle exec rake pg:save database=#{args.database} filename=#{args.filename}
45
66
  `).include?('Saving database completed') # The output of pg:save down below
46
67
  puts("Error calling ssh #{args.user}@#{args.remote} and running rake pg:save on hatchbox from ~/#{args.app}/current/")
47
68
  abort(result)
48
69
  end
49
70
 
50
71
  # SCP to copy the hatchkbox latest.dump to local
51
- unless system("scp #{args.user}@#{args.remote}:~/#{args.app}/current/latest.dump ./")
72
+ unless system("scp #{args.user}@#{args.remote}:~/#{args.app}/current/#{args.filename} ./")
52
73
  abort("Error downloading database")
53
74
  end
54
75
 
55
76
  # Load it
56
- Rake::Task['pg:load'].invoke
77
+ Rake::Task['pg:load'].invoke(*args)
57
78
  exit
58
79
  end
59
80
 
@@ -67,6 +88,7 @@ namespace :pg do
67
88
  # bundle exec rake pg:load => Will replace the current database with latest.dump
68
89
  # bundle exec rake pg:load[something.dump] => Will replace the current database with something.dump
69
90
  # bundle exec rake pg:load filename=latest.dump database=example
91
+ # DATABASE=example bundle exec rake pg:load
70
92
  desc 'Loads a postgresql .dump file into the development database (latest.dump by default)'
71
93
  task :load, [:filename] => :environment do |t, args|
72
94
  defaults = { database: nil, filename: (ENV['DATABASE'] || 'latest') + '.dump' }
@@ -106,19 +128,6 @@ namespace :pg do
106
128
 
107
129
  puts "=== Loading #{args.filename} into local '#{db[:database]}' database"
108
130
 
109
- # bin/rails db:environment:set RAILS_ENV=development
110
- if Rails.env != 'production'
111
- ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK'] = '1'
112
- end
113
-
114
- if configs.length > 1
115
- Rake::Task["db:drop:#{args.database}"].invoke
116
- Rake::Task["db:create:#{args.database}"].invoke
117
- else
118
- Rake::Task['db:drop'].invoke
119
- Rake::Task['db:create'].invoke
120
- end
121
-
122
131
  if system("export PGPASSWORD=#{db[:password]}; pg_restore --no-acl --no-owner --clean --if-exists -h #{db[:host]} -U #{db[:username]} -d #{db[:database]} #{args.filename}")
123
132
  puts "Loading database completed"
124
133
  else
@@ -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.5.5
4
+ version: 0.6.4
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-02-26 00:00:00.000000000 Z
11
+ date: 2021-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -48,8 +48,10 @@ files:
48
48
  - MIT-LICENSE
49
49
  - README.md
50
50
  - Rakefile
51
+ - app/models/effective/annotator.rb
51
52
  - app/models/effective/code_writer.rb
52
53
  - app/models/effective/csv_importer.rb
54
+ - app/models/effective/form_upgrader.rb
53
55
  - app/models/effective/live_generator.rb
54
56
  - app/models/effective/profiler.rb
55
57
  - config/effective_developer.rb
@@ -95,10 +97,12 @@ files:
95
97
  - lib/scaffolds/importers/csv_importer.rb
96
98
  - lib/scaffolds/models/model.rb
97
99
  - lib/scaffolds/views/_resource.html.haml
100
+ - lib/tasks/annotate.rake
98
101
  - lib/tasks/effective_csv_importer.rake
99
102
  - lib/tasks/pg_pull.rake
100
103
  - lib/tasks/rename_class.rake
101
104
  - lib/tasks/reset_pk_sequence.rake
105
+ - lib/tasks/upgrade_forms.rake
102
106
  - lib/tasks/validate.rake
103
107
  homepage: https://github.com/code-and-effect/effective_developer
104
108
  licenses: