hot-glue 0.5.8 → 0.5.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -2
- data/Gemfile +1 -1
- data/README.md +267 -149
- data/app/helpers/hot_glue/controller_helper.rb +9 -6
- data/config/hot_glue.yml +2 -0
- data/lib/generators/hot_glue/direct_upload_install_generator.rb +48 -0
- data/lib/generators/hot_glue/dropzone_install_generator.rb +42 -0
- data/lib/generators/hot_glue/field_factory.rb +57 -0
- data/lib/generators/hot_glue/fields/association_field.rb +76 -0
- data/lib/generators/hot_glue/fields/attachment_field.rb +9 -0
- data/lib/generators/hot_glue/fields/boolean_field.rb +18 -0
- data/lib/generators/hot_glue/fields/date_field.rb +10 -0
- data/lib/generators/hot_glue/fields/date_time_field.rb +23 -0
- data/lib/generators/hot_glue/fields/enum_field.rb +27 -0
- data/lib/generators/hot_glue/fields/field.rb +51 -0
- data/lib/generators/hot_glue/fields/float_field.rb +11 -0
- data/lib/generators/hot_glue/fields/integer_field.rb +26 -0
- data/lib/generators/hot_glue/fields/string_field.rb +33 -0
- data/lib/generators/hot_glue/fields/text_field.rb +14 -0
- data/lib/generators/hot_glue/fields/time_field.rb +6 -0
- data/lib/generators/hot_glue/fields/uuid_field.rb +12 -0
- data/lib/generators/hot_glue/layout/builder.rb +15 -6
- data/lib/generators/hot_glue/layout_strategy/base.rb +2 -0
- data/lib/generators/hot_glue/layout_strategy/bootstrap.rb +4 -0
- data/lib/generators/hot_glue/markup_templates/erb.rb +158 -117
- data/lib/generators/hot_glue/scaffold_generator.rb +296 -306
- data/lib/generators/hot_glue/templates/computer_code.jpg +0 -0
- data/lib/generators/hot_glue/templates/controller.rb.erb +15 -9
- data/lib/generators/hot_glue/templates/erb/_list.erb +19 -6
- data/lib/generators/hot_glue/templates/erb/_show.erb +6 -4
- data/lib/generators/hot_glue/templates/javascript/dropzone_controller.js +191 -0
- data/lib/generators/hot_glue/templates/system_spec.rb.erb +32 -111
- data/lib/hotglue/version.rb +1 -1
- data/script/clean_generated_code +1 -1
- metadata +22 -4
@@ -79,11 +79,14 @@ module HotGlue
|
|
79
79
|
hawk_schema.each do |hawk_key,hawk_definition|
|
80
80
|
hawk_root = hawk_definition[0]
|
81
81
|
# hawk_scope = hawk_definition[1]
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
|
83
|
+
unless modified_params[hawk_key.to_s].blank?
|
84
|
+
begin
|
85
|
+
eval("hawk_root").find(modified_params[hawk_key.to_s])
|
86
|
+
rescue ActiveRecord::RecordNotFound => e
|
87
|
+
@hawk_alarm << "You aren't allowed to set #{hawk_key.to_s} to #{modified_params[hawk_key.to_s]}. "
|
88
|
+
modified_params.tap { |hs| hs.delete(hawk_key.to_s) }
|
89
|
+
end
|
87
90
|
end
|
88
91
|
end
|
89
92
|
modified_params
|
@@ -95,4 +98,4 @@ module HotGlue
|
|
95
98
|
Time.now.strftime("%z").to_i/100
|
96
99
|
end
|
97
100
|
end
|
98
|
-
end
|
101
|
+
end
|
data/config/hot_glue.yml
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module HotGlue
|
4
|
+
class DirectUploadInstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
6
|
+
|
7
|
+
def filepath_prefix
|
8
|
+
# todo: inject the context
|
9
|
+
'spec/dummy/' if Rails.env.test?
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(*args) #:nodoc:
|
13
|
+
super
|
14
|
+
|
15
|
+
if Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }['importmap-rails'] # impomrtmaps
|
16
|
+
|
17
|
+
file_contents = File.read("#{filepath_prefix}app/javascript/application.js")
|
18
|
+
|
19
|
+
if !file_contents.include?("//= require activestorage")
|
20
|
+
file_contents << "//= require activestorage"
|
21
|
+
File.write("#{filepath_prefix}app/javascript/application.js", file_contents)
|
22
|
+
puts " HOTGLUE --> added to #{filepath_prefix}app/javascript/application.js: `//= require activestorage"
|
23
|
+
else
|
24
|
+
puts " HOTGLUE --> #{filepath_prefix}app/javascript/application.js already contains `//= require activestorage`"
|
25
|
+
end
|
26
|
+
|
27
|
+
elsif Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }['jsbundling-rails']
|
28
|
+
file_contents = File.read("#{filepath_prefix}app/javascript/application.js")
|
29
|
+
|
30
|
+
if !file_contents.include?("ActiveStorage.start()")
|
31
|
+
file_contents << "import * as ActiveStorage from \"@rails/activestorage\"
|
32
|
+
ActiveStorage.start()"
|
33
|
+
File.write("#{filepath_prefix}app/javascript/application.js", file_contents)
|
34
|
+
puts " HOTGLUE --> added to #{filepath_prefix}app/javascript/application.js: `ActiveStorage.start()"
|
35
|
+
else
|
36
|
+
puts " HOTGLUE --> #{filepath_prefix}app/javascript/application.js already contains `ActiveStorage.start()`"
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
else
|
41
|
+
puts " HOTGLUE --> could not detect either importmap-rails or jsbundling-rails app"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module HotGlue
|
2
|
+
class DropzoneInstallGenerator < Rails::Generators::Base
|
3
|
+
source_root File.expand_path('templates', __dir__)
|
4
|
+
|
5
|
+
def filepath_prefix
|
6
|
+
# todo: inject the context
|
7
|
+
'spec/dummy/' if Rails.env.test?
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def initialize(*args) #:nodoc:
|
12
|
+
super
|
13
|
+
system("./bin/rails generate stimulus Dropzone")
|
14
|
+
copy_file "javascript/dropzone_controller.js", "#{filepath_prefix}app/javascript/controllers/dropzone_controller.js"
|
15
|
+
puts "HOT GLUE --> copying dropzone stimulus controller into app/javascript/controllers/dropzone_controller.js"
|
16
|
+
|
17
|
+
|
18
|
+
if File.exist?("#{filepath_prefix}app/assets/stylesheets/application.bootstrap.scss")
|
19
|
+
scss_file = "#{filepath_prefix}app/assets/stylesheets/application.bootstrap.scss"
|
20
|
+
elsif File.exist?("#{filepath_prefix}app/assets/stylesheets/application.scss")
|
21
|
+
scss_file = "#{filepath_prefix}app/assets/stylesheets/application.scss"
|
22
|
+
else
|
23
|
+
raise HotGlue::Error, "Could not detect your stylesheet, aborting..."
|
24
|
+
end
|
25
|
+
|
26
|
+
file_contents = File.read(scss_file)
|
27
|
+
|
28
|
+
if !file_contents.include?("@import \"dropzone/dist/dropzone\"")
|
29
|
+
file_contents << "\n@import \"dropzone/dist/dropzone\";\n@import \"dropzone/dist/basic\";"
|
30
|
+
|
31
|
+
|
32
|
+
File.write(scss_file, file_contents)
|
33
|
+
puts " HOTGLUE --> added to #{scss_file}: @import dropzone ... "
|
34
|
+
else
|
35
|
+
puts " HOTGLUE --> #{scss_file} already contains @import dropzone"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative "fields/association_field"
|
2
|
+
require_relative "fields/boolean_field"
|
3
|
+
require_relative "fields/date_field"
|
4
|
+
require_relative "fields/date_time_field"
|
5
|
+
require_relative "fields/enum_field"
|
6
|
+
require_relative "fields/float_field"
|
7
|
+
require_relative "fields/integer_field"
|
8
|
+
require_relative "fields/string_field"
|
9
|
+
require_relative "fields/text_field"
|
10
|
+
require_relative "fields/time_field"
|
11
|
+
require_relative "fields/uuid_field"
|
12
|
+
require_relative "fields/attachment_field"
|
13
|
+
|
14
|
+
|
15
|
+
class FieldFactory
|
16
|
+
attr_accessor :field, :class_name
|
17
|
+
def initialize(type: , name: , generator: )
|
18
|
+
field_class = case type
|
19
|
+
when :integer
|
20
|
+
if name.to_s.ends_with?("_id")
|
21
|
+
AssociationField
|
22
|
+
else
|
23
|
+
IntegerField
|
24
|
+
end
|
25
|
+
when :uuid
|
26
|
+
UUIDField
|
27
|
+
when :string
|
28
|
+
StringField
|
29
|
+
when :text
|
30
|
+
TextField
|
31
|
+
when :float
|
32
|
+
FloatField
|
33
|
+
when :datetime
|
34
|
+
DateTimeField
|
35
|
+
when :date
|
36
|
+
DateField
|
37
|
+
when :time
|
38
|
+
TimeField
|
39
|
+
when :boolean
|
40
|
+
BooleanField
|
41
|
+
when :enum
|
42
|
+
EnumField
|
43
|
+
when :attachment
|
44
|
+
AttachmentField
|
45
|
+
end
|
46
|
+
@class_name = class_name
|
47
|
+
|
48
|
+
@field = field_class.new(name: name,
|
49
|
+
hawk_keys: generator.hawk_keys,
|
50
|
+
auth: generator.auth,
|
51
|
+
class_name: generator.singular_class,
|
52
|
+
alt_lookups: generator.alt_lookups,
|
53
|
+
singular: generator.singular,
|
54
|
+
update_show_only: generator.update_show_only,
|
55
|
+
sample_file_path: generator.sample_file_path)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
require_relative './field.rb'
|
3
|
+
|
4
|
+
class AssociationField < Field
|
5
|
+
|
6
|
+
def initialize(name: , class_name: , alt_lookups: , singular: , update_show_only: ,
|
7
|
+
hawk_keys: , auth: , sample_file_path: )
|
8
|
+
super
|
9
|
+
assoc_model = eval("#{class_name}.reflect_on_association(:#{assoc})")
|
10
|
+
|
11
|
+
if assoc_model.nil?
|
12
|
+
exit_message = "*** Oops: The model #{class_name} is missing an association for :#{assoc_name} or the model #{assoc_name.titlecase} doesn't exist. TODO: Please implement a model for #{assoc_name.titlecase}; or add to #{class_name} `belongs_to :#{assoc_name}`. To make a controller that can read all records, specify with --god."
|
13
|
+
puts exit_message
|
14
|
+
raise(HotGlue::Error, exit_message)
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
assoc_class = eval(assoc_model.try(:class_name))
|
19
|
+
end
|
20
|
+
|
21
|
+
name_list = [:name, :to_label, :full_name, :display_name, :email]
|
22
|
+
|
23
|
+
if assoc_class && name_list.collect{ |field|
|
24
|
+
assoc_class.respond_to?(field.to_s) || assoc_class.instance_methods.include?(field)
|
25
|
+
}.none?
|
26
|
+
exit_message = "Oops: Missing a label for `#{assoc_class}`. Can't find any column to use as the display label for the #{@assoc_name} association on the #{class_name} model. TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name 5) email. You can implement any of these directly on your`#{assoc_class}` model (can be database fields or model methods) or alias them to field you want to use as your display label. Then RERUN THIS GENERATOR. (Field used will be chosen based on rank here.)"
|
27
|
+
raise(HotGlue::Error, exit_message)
|
28
|
+
end
|
29
|
+
|
30
|
+
# set teh assoc label
|
31
|
+
end
|
32
|
+
|
33
|
+
def assoc_label
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def assoc_name
|
38
|
+
assoc
|
39
|
+
end
|
40
|
+
|
41
|
+
def assoc
|
42
|
+
name.to_s.gsub('_id','')
|
43
|
+
end
|
44
|
+
|
45
|
+
def spec_setup_and_change_act(which_partial)
|
46
|
+
if which_partial == :update && update_show_only.include?(name)
|
47
|
+
# do not update tests
|
48
|
+
elsif alt_lookups.keys.include?(name.to_s)
|
49
|
+
lookup = alt_lookups[name.to_s][:lookup_as]
|
50
|
+
" find(\"[name='#{singular}[__lookup_#{lookup}]']\").fill_in( with: #{assoc}1.#{lookup} )"
|
51
|
+
else
|
52
|
+
" #{name}_selector = find(\"[name='#{singular}[#{name}]']\").click \n" +
|
53
|
+
" #{name}_selector.first('option', text: #{assoc}1.name).select_option"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def spec_make_assertion
|
58
|
+
" expect(page).to have_content(#{assoc}1.name)"
|
59
|
+
end
|
60
|
+
|
61
|
+
def spec_setup_let_arg
|
62
|
+
"#{name.to_s.gsub('_id','')}: #{name.to_s.gsub('_id','')}1"
|
63
|
+
end
|
64
|
+
|
65
|
+
def spec_list_view_assertion
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def spec_related_column_lets
|
70
|
+
the_foreign_class = eval(class_name + ".reflect_on_association(:" + assoc + ")").class_name.split("::").last.underscore
|
71
|
+
|
72
|
+
hawk_keys_on_lets = (hawk_keys["#{assoc}_id".to_sym] ? ", #{auth.gsub('current_', '')}: #{auth}": "")
|
73
|
+
|
74
|
+
" let!(:#{assoc}1) {create(:#{the_foreign_class}" + hawk_keys_on_lets + ")}"
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class BooleanField < Field
|
2
|
+
def spec_setup_and_change_act(which_partial = nil)
|
3
|
+
" new_#{name} = 1 \n" +
|
4
|
+
" find(\"[name='#{testing_name}[#{name}]'][value='\#{new_" + name.to_s + "}']\").choose"
|
5
|
+
end
|
6
|
+
|
7
|
+
def spec_make_assertion
|
8
|
+
["expect(page).to have_content(#{singular}#{1}.#{name} ? 'YES' : 'NO')"].join("\n ")
|
9
|
+
end
|
10
|
+
|
11
|
+
def spec_setup_let_arg
|
12
|
+
"#{name}: !!rand(2).floor"
|
13
|
+
end
|
14
|
+
|
15
|
+
def spec_list_view_assertion
|
16
|
+
" " + ["expect(page).to have_content(#{singular}#{1}.#{name} ? 'YES' : 'NO')"].join("\n ")
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class DateField < Field
|
2
|
+
def spec_setup_and_change_act(which_partial = nil)
|
3
|
+
" " + "new_#{name} = Date.current + (rand(100).days) \n" +
|
4
|
+
' ' + "find(\"[name='#{testing_name}[#{ name.to_s }]']\").fill_in(with: new_#{name.to_s})"
|
5
|
+
end
|
6
|
+
|
7
|
+
def spec_setup_let_arg
|
8
|
+
"#{name}: Date.current + rand(50).days"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class DateTimeField < Field
|
2
|
+
def spec_random_data
|
3
|
+
Time.now + rand(1..5).days
|
4
|
+
end
|
5
|
+
|
6
|
+
def spec_setup_and_change_act(which_partial = nil)
|
7
|
+
" " + "new_#{name} = DateTime.current + (rand(100).days) \n" +
|
8
|
+
' ' + "find(\"[name='#{testing_name}[#{ name.to_s }]']\").fill_in(with: new_#{name.to_s})"
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def spec_make_assertion
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def spec_setup_let_arg
|
17
|
+
"#{name}: DateTime.current + rand(1000).seconds"
|
18
|
+
end
|
19
|
+
|
20
|
+
def spec_list_view_assertion
|
21
|
+
" " + ["expect(page).to have_content(#{singular}#{1}.#{name}.in_time_zone(current_timezone).strftime('%m/%d/%Y @ %l:%M %p ').gsub(' ', ' ') + timezonize(current_timezone) )"].join("\n ")
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class EnumField < Field
|
2
|
+
def spec_setup_and_change_act(which_partial = nil)
|
3
|
+
" list_of_#{name.to_s} = #{singular_class}.defined_enums['#{name.to_s}'].keys \n" +
|
4
|
+
" " + "new_#{name.to_s} = list_of_#{name.to_s}[rand(list_of_#{name.to_s}.length)].to_s \n" +
|
5
|
+
' find("select[name=\'' + singular + '[' + name.to_s + ']\'] option[value=\'#{new_' + name.to_s + '}\']").select_option'
|
6
|
+
end
|
7
|
+
|
8
|
+
def spec_make_assertion
|
9
|
+
if(eval("#{singular_class}.respond_to?(:#{name}_labels)"))
|
10
|
+
"expect(page).to have_content(#{singular_class}.#{name}_labels[new_#{name}])"
|
11
|
+
else
|
12
|
+
"expect(page).to have_content(new_#{name})"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def spec_setup_let_args
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def spec_list_view_assertion
|
21
|
+
if(eval("#{singular_class}.respond_to?(:#{name}_labels)"))
|
22
|
+
" " + "expect(page).to have_content(#{singular_class}.#{name}_labels[#{singular}#{1}.#{name}])"
|
23
|
+
else
|
24
|
+
" " + "expect(page).to have_content(#{singular}1.#{name})"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Field
|
2
|
+
attr_accessor :name, :object, :singular_class, :class_name, :singular,
|
3
|
+
:update_show_only
|
4
|
+
attr_accessor :assoc_model, :assoc_name, :assoc_class, :associations, :alt_lookups, :assoc_label
|
5
|
+
|
6
|
+
attr_accessor :hawk_keys, :auth, :sample_file_path
|
7
|
+
|
8
|
+
def initialize(name: , class_name: , alt_lookups: , singular: , update_show_only: ,
|
9
|
+
hawk_keys: , auth: , sample_file_path: nil)
|
10
|
+
@name = name
|
11
|
+
@alt_lookups = alt_lookups
|
12
|
+
@singular = singular
|
13
|
+
@class_name = class_name
|
14
|
+
@update_show_only = update_show_only
|
15
|
+
@hawk_keys = hawk_keys
|
16
|
+
@auth = auth
|
17
|
+
@sample_file_path = sample_file_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def getName
|
21
|
+
@name
|
22
|
+
end
|
23
|
+
|
24
|
+
def spec_random_data
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def testing_name
|
29
|
+
class_name.to_s.gsub("::","_").underscore
|
30
|
+
end
|
31
|
+
|
32
|
+
def spec_setup_and_change_act(which_partial = nil)
|
33
|
+
""
|
34
|
+
end
|
35
|
+
|
36
|
+
def spec_make_assertion
|
37
|
+
"expect(page).to have_content(new_#{name})"
|
38
|
+
end
|
39
|
+
|
40
|
+
def spec_setup_let_arg
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def spec_list_view_assertion
|
45
|
+
" " + ["expect(page).to have_content(#{singular}#{1}.#{name})"].join("\n ")
|
46
|
+
end
|
47
|
+
|
48
|
+
def spec_related_column_lets
|
49
|
+
""
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class FloatField < Field
|
2
|
+
def spec_setup_and_change_act(which_partial = nil)
|
3
|
+
" " + "new_#{name} = rand(10) \n" +
|
4
|
+
" find(\"[name='#{testing_name}[#{ name.to_s }]']\").fill_in(with: new_#{name.to_s})"
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
def spec_setup_let_arg
|
9
|
+
"#{name}: rand(1)*10000"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class IntegerField < Field
|
2
|
+
def spec_random_data
|
3
|
+
rand(1...1000)
|
4
|
+
end
|
5
|
+
|
6
|
+
def spec_setup_and_change_act(which_partial = nil)
|
7
|
+
if name.to_s.ends_with?("_id")
|
8
|
+
capybara_block_for_association(name_name: name, which_partial: which_partial)
|
9
|
+
else
|
10
|
+
" new_#{name} = rand(10) \n" +
|
11
|
+
" find(\"[name='#{testing_name}[#{ name.to_s }]']\").fill_in(with: new_#{name.to_s})"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def spec_make_assertion
|
16
|
+
"expect(page).to have_content(new_#{name})"
|
17
|
+
end
|
18
|
+
|
19
|
+
def spec_setup_let_arg
|
20
|
+
"#{name}: rand(100)"
|
21
|
+
end
|
22
|
+
|
23
|
+
def spec_list_view_assertion
|
24
|
+
" " + ["expect(page).to have_content(#{singular}#{1}.#{name})"].join("\n ")
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class StringField < Field
|
2
|
+
def spec_random_data
|
3
|
+
FFaker::AnimalUS.common_name
|
4
|
+
end
|
5
|
+
|
6
|
+
def spec_setup_and_change_act(which_partial = nil)
|
7
|
+
faker_string =
|
8
|
+
if name.to_s.include?('email')
|
9
|
+
"FFaker::Internet.email"
|
10
|
+
elsif name.to_s.include?('domain')
|
11
|
+
"FFaker::Internet.domain_name"
|
12
|
+
elsif name.to_s.include?('ip_address') || name.to_s.ends_with?('_ip')
|
13
|
+
"FFaker::Internet.ip_v4_address"
|
14
|
+
else
|
15
|
+
"FFaker::Movie.title"
|
16
|
+
end
|
17
|
+
|
18
|
+
return " " + "new_#{name} = #{faker_string} \n" +
|
19
|
+
" find(\"[name='#{testing_name}[#{ name.to_s }]']\").fill_in(with: new_#{name.to_s})"
|
20
|
+
end
|
21
|
+
|
22
|
+
def spec_setup_let_arg
|
23
|
+
if name.to_s.include?('email')
|
24
|
+
"#{name}: FFaker::Internet.email"
|
25
|
+
elsif name.to_s.include?('domain')
|
26
|
+
"#{name}: FFaker::Internet.domain_name"
|
27
|
+
elsif name.to_s.include?('ip_address') || name.to_s.ends_with?('_ip')
|
28
|
+
"#{name}: FFaker::Internet.ip_v4_address"
|
29
|
+
else
|
30
|
+
"#{name}: FFaker::Movie.title"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class TextField < Field
|
2
|
+
def spec_random_data
|
3
|
+
FFaker::AnimalUS.common_name
|
4
|
+
end
|
5
|
+
|
6
|
+
def spec_setup_and_change_act(which_partial = nil)
|
7
|
+
" " + "new_#{name} = FFaker::Lorem.paragraphs(1).join("") \n" +
|
8
|
+
" find(\"[name='#{testing_name}[#{ name.to_s }]']\").fill_in(with: new_#{name.to_s})"
|
9
|
+
end
|
10
|
+
|
11
|
+
def spec_setup_let_arg
|
12
|
+
"#{name}: FFaker::Lorem.paragraphs(10).join(" ")"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class UUIDField < Field
|
2
|
+
def spec_setup_let_arg
|
3
|
+
"#{name.to_s.gsub('_id','')}: #{name.to_s.gsub('_id','')}1"
|
4
|
+
end
|
5
|
+
|
6
|
+
def spec_list_view_assertion
|
7
|
+
assoc_name = name.to_s.gsub('_id','')
|
8
|
+
association = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
|
9
|
+
" " + ["expect(page).to have_content(#{singular}#{1}.#{assoc_name}.#{HotGlue.derrive_reference_name(association.class_name)})"].join("\n ")
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -6,13 +6,14 @@ module HotGlue
|
|
6
6
|
attr_reader :include_setting,
|
7
7
|
:downnest_object,
|
8
8
|
:buttons_width, :columns,
|
9
|
-
:smart_layout, :specified_grouping_mode
|
9
|
+
:smart_layout, :specified_grouping_mode, :stacked_downnesting
|
10
10
|
|
11
11
|
def initialize(include_setting: nil,
|
12
12
|
downnest_object: nil,
|
13
13
|
buttons_width: nil,
|
14
14
|
smart_layout: nil,
|
15
|
-
columns: nil
|
15
|
+
columns: nil,
|
16
|
+
stacked_downnesting: false)
|
16
17
|
@include_setting = include_setting
|
17
18
|
@downnest_object = downnest_object
|
18
19
|
@buttons_width = buttons_width
|
@@ -21,6 +22,7 @@ module HotGlue
|
|
21
22
|
|
22
23
|
@no_buttons = @buttons_width == 0
|
23
24
|
@specified_grouping_mode = include_setting.include?(":")
|
25
|
+
@stacked_downnesting = stacked_downnesting
|
24
26
|
end
|
25
27
|
|
26
28
|
def construct
|
@@ -44,21 +46,28 @@ module HotGlue
|
|
44
46
|
|
45
47
|
bootstrap_columns = (12 - @buttons_width )
|
46
48
|
|
47
|
-
|
49
|
+
if(!stacked_downnesting)
|
50
|
+
bootstrap_columns = bootstrap_columns - (downnest_object.collect{|k,v| v}.sum)
|
51
|
+
else
|
52
|
+
bootstrap_columns = bootstrap_columns - 4
|
53
|
+
end
|
48
54
|
|
49
55
|
available_columns = (bootstrap_columns / 2).floor # bascially turns the 12-column grid into a 6-column grid
|
50
56
|
|
51
57
|
if available_columns < 0
|
52
58
|
raise "Cannot build layout with #{how_many_downnest} downnested portals"
|
53
59
|
end
|
54
|
-
|
60
|
+
#
|
61
|
+
# if !stacked_downnesting
|
62
|
+
#
|
63
|
+
# else
|
64
|
+
#
|
65
|
+
# end
|
55
66
|
downnest_children_width = []
|
56
|
-
|
57
67
|
downnest_object.each do |child, size|
|
58
68
|
layout_object[:portals][child] = {size: size}
|
59
69
|
end
|
60
70
|
|
61
|
-
|
62
71
|
if smart_layout
|
63
72
|
# automatic control
|
64
73
|
#
|
@@ -5,6 +5,7 @@ module LayoutStrategy
|
|
5
5
|
@builder = scaffold_builder
|
6
6
|
end
|
7
7
|
|
8
|
+
def button_applied_classes; end
|
8
9
|
def column_classes_for_button_column; ""; end
|
9
10
|
def button_classes; ""; end
|
10
11
|
def button_column_style; "" ; end
|
@@ -23,6 +24,7 @@ module LayoutStrategy
|
|
23
24
|
(col_width/(builder.columns.count)).to_i
|
24
25
|
end
|
25
26
|
def list_classes; ""; end
|
27
|
+
def magic_button_classes; ""; end
|
26
28
|
def row_classes; ""; end
|
27
29
|
def row_heading_classes; ""; end
|
28
30
|
def page_begin; '<div> '; end
|
@@ -41,6 +41,10 @@ class LayoutStrategy::Bootstrap < LayoutStrategy::Base
|
|
41
41
|
"col-sm-#{ builder.layout_object[:portals][downnest][:size] }"
|
42
42
|
end
|
43
43
|
|
44
|
+
def downnest_portal_stacked_column_width
|
45
|
+
"col-sm-4"
|
46
|
+
end
|
47
|
+
|
44
48
|
def page_begin
|
45
49
|
'<div class="row"> <div class="col-md-12">'
|
46
50
|
end
|