effective_developer 0.5.4 → 0.6.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b1e21ed1c3b2080e07244e8e7d01cb9b611ce045c9c8ffa2073caded089f6c1
4
- data.tar.gz: a0be18c08741489856b6aff27861d4b5408c4db12bd9e33b9e8898f072c47fd6
3
+ metadata.gz: 7e76b8818691ec2238e08a818d209ba7e4d1746734ef3c7c2c2cbe8f4e08aa12
4
+ data.tar.gz: a283fca85ffd1c0dc6d73287bd6c239c898e6b6e2aa8500ebc08642960f7ad5f
5
5
  SHA512:
6
- metadata.gz: 8c2822c02d0ce42a2f875ff1efa2dd84df01063e2d18dd14dcbb08b1379e9eaa19bcb6dafa1453943c953b8debaae210054973d6de7d6def7a3a4f0eb22ce6e0
7
- data.tar.gz: a0f964f2d4e70ee5624618cd44819d8a97cd3875e9a3dac2531552fe12484d1a09031d96a12ac1729e28522c4110ece5208c49e9d8765acd0efa649537d2e1e2
6
+ metadata.gz: 0dc45f6f25c607353f5ea9651cda2054e2d6f2996fac603ebd37df05191d4a2d7981662e7e68681163856a566eeb452c4b0030623d130f2d33507bea36956548
7
+ data.tar.gz: 8a4ec7eab0237e8f0ac37a80e1cb7ea3974514b8228a6f8711a9fa00b66e0d2cecb5b22d336c28afd954bb916337b809a1205b8820d3637fb66574829710b73d
@@ -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,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Effective::Profiler.allocations { my_method() }
4
+
5
+ module Effective
6
+ class Profiler
7
+
8
+ def self.allocations(sourcefiles: ['effective_'], &block)
9
+ raise('please install the allocation_stats gem') unless defined?(AllocationStats)
10
+
11
+ # Run block
12
+ retval = nil
13
+ stats = AllocationStats.trace { retval = yield(block) }
14
+
15
+ # Compute Allocations
16
+ allocations = stats.allocations.to_a
17
+
18
+ # Filter
19
+ if sourcefiles.present?
20
+ sourcefiles = Array(sourcefiles)
21
+ allocations = allocations.select! { |allocation| sourcefiles.any? { |str| allocation.sourcefile.include?(str) } }
22
+ end
23
+
24
+ # Sort
25
+ allocations = allocations.sort_by { |allocation| allocation.memsize }
26
+
27
+ # Print
28
+ puts AllocationStats::AllocationsProxy.new(allocations).to_text
29
+
30
+ puts "Total allocations: #{allocations.length}. Total size: #{allocations.sum(&:memsize)}"
31
+
32
+ retval
33
+ end
34
+
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module EffectiveDeveloper
2
- VERSION = '0.5.4'.freeze
2
+ VERSION = '0.6.3'.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,14 +1,43 @@
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
2
6
 
3
- bulk_actions do
4
- bulk_action 'Delete selected', <%= [resource.namespaces, resource, 'path'].flatten.compact.join('_') %>(:ids), data: { method: :delete, confirm: 'Really delete selected?' }
5
- end
7
+ col :updated_at, visible: false
8
+ col :created_at, visible: false
9
+ col :id, visible: false
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
6
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
7
38
  datatable do
8
39
  order :updated_at
9
40
 
10
- bulk_actions_col
11
-
12
41
  col :updated_at, visible: false
13
42
  col :created_at, visible: false
14
43
  col :id, visible: false
@@ -36,5 +65,5 @@ class <%= resource.namespaced_class_name.pluralize %>Datatable < Effective::Data
36
65
  collection do
37
66
  <%= resource.class_name %>.deep.all
38
67
  end
39
-
40
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
 
@@ -66,25 +87,48 @@ namespace :pg do
66
87
  #
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
90
+ # bundle exec rake pg:load filename=latest.dump database=example
91
+ # DATABASE=example bundle exec rake pg:load
69
92
  desc 'Loads a postgresql .dump file into the development database (latest.dump by default)'
70
- task :load, [:file_name] => :environment do |t, args|
71
- args.with_defaults(:file_name => 'latest.dump')
93
+ task :load, [:filename] => :environment do |t, args|
94
+ defaults = { database: nil, filename: (ENV['DATABASE'] || 'latest') + '.dump' }
95
+ env_keys = { database: ENV['DATABASE'], filename: ENV['FILENAME'] }
96
+ keywords = ARGV.map { |a| a.split('=') if a.include?('=') }.compact.inject({}) { |h, (k, v)| h[k.to_sym] = v; h }
97
+ args.with_defaults(defaults.compact.merge(env_keys.compact).merge(keywords))
98
+
99
+ # Validate filename
100
+ unless File.exists?(Rails.root + args.filename)
101
+ puts "#{args.filename || none} does not exist"; exit
102
+ end
72
103
 
104
+ # Validate Config
73
105
  config = ActiveRecord::Base.configurations[Rails.env]
74
- db = { username: (config['username'] || `whoami`), password: config['password'], host: config['host'], port: (config['port'] || 5432), database: config['database'] }
75
- db.transform_values! { |v| v.respond_to?(:chomp) ? v.chomp : v }
106
+ configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
107
+
108
+ if configs.length > 1 && args.database.blank?
109
+ puts "Multiple database configs exist for #{Rails.env} environment."
110
+ puts "Please run bundle exec rake pg:load database=x"
111
+ puts "Where x is one of: #{configs.map { |config| config.name }.to_sentence}"
112
+ exit
113
+ end
76
114
 
77
- puts "=== Loading #{args.file_name} into local '#{db[:database]}' database"
115
+ if configs.length > 1 && args.database.present?
116
+ config = configs.find { |config| config.name == args.database }
117
+ end
78
118
 
79
- # bin/rails db:environment:set RAILS_ENV=development
80
- if Rails.env != 'production'
81
- ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK'] = '1'
119
+ if config.blank?
120
+ puts "Unable to find Rails database config for #{Rails.env}. Exiting."; exit
82
121
  end
83
122
 
84
- Rake::Task['db:drop'].invoke
85
- Rake::Task['db:create'].invoke
123
+ config = config.configuration_hash if config.respond_to?(:configuration_hash)
124
+ config = config.stringify_keys
86
125
 
87
- 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.file_name}")
126
+ db = { username: (config['username'] || `whoami`), password: config['password'], host: config['host'], port: (config['port'] || 5432), database: config['database'] }
127
+ db.transform_values! { |v| v.respond_to?(:chomp) ? v.chomp : v }
128
+
129
+ puts "=== Loading #{args.filename} into local '#{db[:database]}' database"
130
+
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}")
88
132
  puts "Loading database completed"
89
133
  else
90
134
  abort "Error loading database"
@@ -94,8 +138,11 @@ namespace :pg do
94
138
  # bundle exec rake pg:save => Will dump the database to latest.dump
95
139
  # bundle exec rake pg:save[something.dump] => Will dump the database to something.dump
96
140
  desc 'Saves the development database to a postgresql .dump file (latest.dump by default)'
97
- task :save, [:file_name] => :environment do |t, args|
98
- args.with_defaults(:file_name => 'latest.dump')
141
+ task :save, [:filename] => :environment do |t, args|
142
+ defaults = { database: nil, filename: (ENV['DATABASE'] || 'latest') + '.dump' }
143
+ env_keys = { database: ENV['DATABASE'], filename: ENV['FILENAME'] }
144
+ keywords = ARGV.map { |a| a.split('=') if a.include?('=') }.compact.inject({}) { |h, (k, v)| h[k.to_sym] = v; h }
145
+ args.with_defaults(defaults.compact.merge(env_keys.compact).merge(keywords))
99
146
 
100
147
  db = if ENV['DATABASE_URL'].to_s.length > 0
101
148
  uri = URI.parse(ENV['DATABASE_URL']) rescue nil
@@ -103,15 +150,36 @@ namespace :pg do
103
150
 
104
151
  { username: uri.user, password: uri.password, host: uri.host, port: (uri.port || 5432), database: uri.path.sub('/', '') }
105
152
  else
153
+ # Validate Config
106
154
  config = ActiveRecord::Base.configurations[Rails.env]
155
+ configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
156
+
157
+ if configs.length > 1 && args.database.blank?
158
+ puts "Multiple database configs exist for #{Rails.env} environment."
159
+ puts "Please run bundle exec rake pg:save database=x"
160
+ puts "Where x is one of: #{configs.map { |config| config.name }.to_sentence}"
161
+ exit
162
+ end
163
+
164
+ if configs.length > 1 && args.database.present?
165
+ config = configs.find { |config| config.name == args.database }
166
+ end
167
+
168
+ if config.blank?
169
+ puts "Unable to find Rails database config for #{Rails.env}. Exiting."; exit
170
+ end
171
+
172
+ config = config.configuration_hash if config.respond_to?(:configuration_hash)
173
+ config = config.stringify_keys
174
+
107
175
  { username: (config['username'] || `whoami`.chomp), password: config['password'], host: config['host'], port: (config['port'] || 5432), database: config['database'] }
108
176
  end
109
177
 
110
178
  db.transform_values! { |v| v.respond_to?(:chomp) ? v.chomp : v }
111
179
 
112
- puts "=== Saving local '#{db[:database]}' database to #{args.file_name}"
180
+ puts "=== Saving local '#{db[:database]}' database to #{args.filename}"
113
181
 
114
- if system("export PGPASSWORD=#{db[:password]}; pg_dump -Fc --no-acl --no-owner -h #{db[:host]} -p #{db[:port]} -U #{db[:username]} #{db[:database]} > #{args.file_name}")
182
+ if system("export PGPASSWORD=#{db[:password]}; pg_dump -Fc --no-acl --no-owner -h #{db[:host]} -p #{db[:port]} -U #{db[:username]} #{db[:database]} > #{args.filename}")
115
183
  puts "Saving database completed"
116
184
  else
117
185
  abort "Error saving database"
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.4
4
+ version: 0.6.3
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: 2020-09-09 00:00:00.000000000 Z
11
+ date: 2021-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -48,9 +48,11 @@ 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
53
54
  - app/models/effective/live_generator.rb
55
+ - app/models/effective/profiler.rb
54
56
  - config/effective_developer.rb
55
57
  - lib/effective_developer.rb
56
58
  - lib/effective_developer/engine.rb
@@ -94,6 +96,7 @@ files:
94
96
  - lib/scaffolds/importers/csv_importer.rb
95
97
  - lib/scaffolds/models/model.rb
96
98
  - lib/scaffolds/views/_resource.html.haml
99
+ - lib/tasks/annotate.rake
97
100
  - lib/tasks/effective_csv_importer.rake
98
101
  - lib/tasks/pg_pull.rake
99
102
  - lib/tasks/rename_class.rake