formgen 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Charlie
1
+ Copyright (c) 2011 Pullmonkey
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
@@ -1,23 +1,29 @@
1
1
  = formgen
2
2
 
3
- rails g skizmo:form --help
3
+ rails g skizmo:form --help
4
+
4
5
  === Usage:
5
6
  rails generate skizmo:form NAME [options]
6
7
 
7
8
  === Options:
8
- [--javascript] # Indicates when to generate javascript
9
- # Default: true
10
- [--helpers] # Indicates when to generate helpers
11
- # Default: true
9
+ [--helpers] # Indicates when to generate helpers
10
+ # Default: true
11
+ [--javascript] # Indicates when to generate javascript
12
+ # Default: true
13
+ [--select-boxes] # Indicates when to generate select boxes
14
+ # Default: true
12
15
 
13
16
  === Runtime options:
14
- -p, [--pretend] # Run but do not make any changes
17
+ -f, [--force] # Overwrite files that already exist
15
18
  -s, [--skip] # Skip files that already exist
16
19
  -q, [--quiet] # Supress status output
17
- -f, [--force] # Overwrite files that already exist
20
+ -p, [--pretend] # Run but do not make any changes
18
21
 
19
22
  === Description:
20
- Generates a form per usual but with fields_for for the has_many and belongs_to associations.
23
+ Generates a form per usual but with fields_for for the has_many and belongs_to associations that are
24
+ "accepted_nested_attributes". If the fields are not accepted nested attributes, then they are
25
+ selectable options, multi-select for has_many and single select for belongs_to. 'has_attached_file'
26
+ will trigger the file_field input and create a multipart form.
21
27
 
22
28
  === Example:
23
29
  rails generate skizmo:form Foo
@@ -29,11 +35,14 @@ rails g skizmo:form --help
29
35
 
30
36
  accepts_nested_attributes_for :bars
31
37
  accepts_nested_attributes_for :baz
38
+
39
+ has_attached_file :image
32
40
  end
33
41
 
34
42
  This will create:
35
43
  public/javascripts/jquery.add_remove_links.js
36
44
  app/helpers/add_remove_links_helper.rb
45
+ app/helpers/foo_setup_helper.rb
37
46
  app/views/foos/new.html.erb
38
47
  app/views/foos/edit.html.erb
39
48
  app/views/foos/_form.html.erb
@@ -41,6 +50,15 @@ rails g skizmo:form --help
41
50
  app/views/foos/_baz_fields.html.erb
42
51
 
43
52
 
53
+ == FAQ
54
+
55
+ * I'm getting this error:
56
+
57
+ undefined method `setup_something' for #<#<Class:
58
+
59
+ Make sure the generated helper is being loaded - restart your rails server.
60
+
61
+
44
62
  == Contributing to formgen
45
63
 
46
64
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -5,16 +5,15 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{formgen}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Pullmonkey"]
12
- s.date = %q{2011-11-15}
12
+ s.date = %q{2011-11-16}
13
13
  s.description = %q{Ruby on Rails form generator based on has_many and belongs_to associations. Includes the helpers and javascript for adding and removing fields_for form attributes.}
14
14
  s.email = %q{info@skizmo.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
- "README",
18
17
  "README.rdoc"
19
18
  ]
20
19
  s.files = [
@@ -22,7 +21,6 @@ Gem::Specification.new do |s|
22
21
  "Gemfile",
23
22
  "Gemfile.lock",
24
23
  "LICENSE.txt",
25
- "README",
26
24
  "README.rdoc",
27
25
  "Rakefile",
28
26
  "VERSION",
@@ -36,6 +34,7 @@ Gem::Specification.new do |s|
36
34
  "lib/generators/skizmo/form/templates/helper.rb",
37
35
  "lib/generators/skizmo/form/templates/javascript.js",
38
36
  "lib/generators/skizmo/form/templates/new.html.erb",
37
+ "lib/generators/skizmo/form/templates/setup_helper.rb",
39
38
  "test/helper.rb",
40
39
  "test/test_formgen.rb"
41
40
  ]
@@ -1,5 +1,5 @@
1
1
  Description:
2
- Generates a form per usual but with fields_for for the has_many and belongs_to associations.
2
+ Generates a form per usual but with fields_for for the has_many and belongs_to associations that are "accepted_nested_attributes". If the fields are not accepted nested attributes, then they are selectable options, multi-select for has_many and single select for belongs_to. 'has_attached_file' will trigger the file_field input and create a multipart form.
3
3
 
4
4
  Example:
5
5
  rails generate skizmo:form Foo
@@ -11,11 +11,14 @@ Example:
11
11
 
12
12
  accepts_nested_attributes_for :bars
13
13
  accepts_nested_attributes_for :baz
14
+
15
+ has_attached_file :image
14
16
  end
15
17
 
16
18
  This will create:
17
19
  public/javascripts/jquery.add_remove_links.js
18
20
  app/helpers/add_remove_links_helper.rb
21
+ app/helpers/foo_setup_helper.rb
19
22
  app/views/foos/new.html.erb
20
23
  app/views/foos/edit.html.erb
21
24
  app/views/foos/_form.html.erb
@@ -6,15 +6,21 @@ module Skizmo
6
6
  class_option :javascript, :type => :boolean, :default => true,
7
7
  :description => "Include javascript to add and remove associated attributes if there are has_many associations"
8
8
  class_option :helpers, :type => :boolean, :default => true,
9
- :description => "Update helpers to add link_to_add and link_to_remove methods if there are has_many associations"
9
+ :description => "Update helpers to add link_to_add and link_to_remove methods if there are has_many associations, as well as a setup method for building objects required for nested attribute associations and for building selectable lists for select boxes"
10
+ class_option :select_boxes, :type => :boolean, :default => true,
11
+ :description => "Generates select box selections for belongs_to and has_many associations that are not accepted as nested_attributes"
10
12
 
11
13
  def generate_form
12
14
  unless nested_has_many_classes.empty?
13
15
  copy_file "javascript.js", "public/javascripts/jquery.add_remove_links.js" if options.javascript?
14
16
  copy_file "helper.rb", "app/helpers/add_remove_links_helper.rb" if options.helpers?
15
17
  end
18
+ unless nested_classes_with_attributes.empty?
19
+ template "setup_helper.rb", "app/helpers/#{file_name}_setup_helper.rb" if options.helpers?
20
+ end
16
21
  template "new.html.erb", "app/views/#{file_name.pluralize}/new.html.erb"
17
22
  template "edit.html.erb", "app/views/#{file_name.pluralize}/edit.html.erb"
23
+ @have_attachment_string = have_attachments? ? ", :html => { :multipart => true }" : ""
18
24
  template "_form.html.erb", "app/views/#{file_name.pluralize}/_form.html.erb"
19
25
  nested_classes_with_attributes.each do |hash_with_kls_and_attrs|
20
26
  @kls = hash_with_kls_and_attrs[:kls] # class object
@@ -28,22 +34,40 @@ module Skizmo
28
34
  private
29
35
 
30
36
  def file_name
31
- name.underscore
37
+ cls_underscore
32
38
  end
33
39
 
34
40
  def cls
35
- name.classify.constantize
41
+ cls_classname.constantize
36
42
  end
37
43
 
44
+ def cls_classname
45
+ name.classify.to_s
46
+ end
47
+
48
+ def cls_underscore
49
+ name.to_s.underscore
50
+ end
51
+
52
+ # Base this on has_attached_file
38
53
  def attributes_worth_using_in_the_form(options={})
39
54
  kls = options[:class] || cls
40
55
  rejects = ["created_at","updated_at","created_on","updated_on","id",/_id$/]
41
- kls.column_names.reject do |x|
42
- rejects.include?(x) || !rejects.select{|y| y.is_a?(Regexp) and x =~ y}.empty?
56
+ # consolidate x_file_name, x_content_type and x_file_size to just x
57
+ attachment_endings = ["_file_name", "_content_type", "_file_size", "_updated_at"]
58
+ attachments = attachments_for(kls) || []
59
+ attachment_rejects = attachment_endings.map{|x| attachments.map{|y| y.to_s + x.to_s}}.flatten.uniq
60
+ attrs_for_form = kls.column_names.reject do |x|
61
+ rejects.include?(x) || !rejects.select{|y| y.is_a?(Regexp) and x =~ y}.empty? ||
62
+ attachment_rejects.include?(x)
43
63
  end
64
+ attrs_for_form | attachments
44
65
  end
45
66
 
67
+ # Base this on has_attached_file
46
68
  def attr_form_method(kls, attr)
69
+ # consolidate x_file_name, x_content_type and x_file_size to just x and use file_field
70
+ return :file_field if atts = attachments_for(kls) and atts.include?(attr)
47
71
  case kls.columns.find{|c| c.name == attr}.try(:type)
48
72
  when :string, :integer, :float, :decimal, :datetime, :timestamp, :time, :date
49
73
  # using text fields for the date selectors b/c most people will use a js calendar
@@ -56,14 +80,31 @@ module Skizmo
56
80
  return :text_field
57
81
  end
58
82
  end
83
+
84
+ def attachments_for(kls)
85
+ if atts = kls.try(:attachment_definitions)
86
+ return atts.keys
87
+ else
88
+ return nil
89
+ end
90
+ end
59
91
 
92
+ def have_attachments?
93
+ (has_many_classes | belongs_to_classes).each do |kls|
94
+ return true if attachments_for(kls.to_s.classify.constantize)
95
+ end
96
+ return false
97
+ end
98
+
99
+ def nested_attributes
100
+ cls.nested_attributes_options.keys
101
+ end
102
+
60
103
  def class_reflections
61
104
  cls.reflections
62
105
  end
63
106
 
64
- # TODO only get the classes that have "nested attributes"
65
-
66
- def nested_has_many_classes
107
+ def has_many_classes
67
108
  has_many_through_associations = class_reflections.select{|k,v| v.macro == :has_many and v.options.has_key?(:through)}
68
109
  through_assocs = has_many_through_associations.map{|x| x.last.options[:through]}
69
110
  # we don't care about the associations that primarily exist to assist the has_many :through
@@ -73,10 +114,28 @@ module Skizmo
73
114
  # these are the keys of the reflections we care about
74
115
  (has_many_through_associations | has_many_associations).map(&:first)
75
116
  end
117
+
118
+ # only get the classes that have "nested attributes"
119
+ def nested_has_many_classes
120
+ has_many_classes.select{|k| nested_attributes.include?(k)}
121
+ end
76
122
 
77
- def nested_belongs_to_classes
123
+ def non_nested_has_many_classes
124
+ has_many_classes.select{|k| !nested_attributes.include?(k)}
125
+ end
126
+
127
+ def belongs_to_classes
78
128
  class_reflections.select{|k,v| v.macro == :belongs_to}.map(&:first)
79
129
  end
130
+
131
+ # only get the classes that have "nested attributes"
132
+ def nested_belongs_to_classes
133
+ belongs_to_classes.select{|k| nested_attributes.include?(k)}
134
+ end
135
+
136
+ def non_nested_belongs_to_classes
137
+ belongs_to_classes.select{|k| !nested_attributes.include?(k)}
138
+ end
80
139
 
81
140
  def nested_classes
82
141
  {:belongs_to => nested_belongs_to_classes, :has_many => nested_has_many_classes}
@@ -93,7 +152,6 @@ module Skizmo
93
152
  end
94
153
  to_return
95
154
  end
96
-
97
155
  end
98
156
  end
99
157
  end
@@ -1,4 +1,8 @@
1
- <%%= form_for @<%= cls.to_s.underscore %> do |f| %>
1
+ <% if options.helpers? -%>
2
+ <%%= form_for setup_<%= cls_underscore %>(@<%= cls.to_s.underscore %>)<%= @have_attachment_string %> do |f| %>
3
+ <% else -%>
4
+ <%%= form_for @<%= cls.to_s.underscore %><%= @have_attachment_string %> do |f| %>
5
+ <% end -%>
2
6
  <%% if @<%= cls.to_s.underscore %>.errors.any? %>
3
7
  <div id="errorExplanation">
4
8
  <h2><%%= pluralize(@<%= cls.to_s.underscore %>.errors.count, "error") %> prohibited this <%= cls.to_s.underscore.gsub("_"," ") %> from being saved:</h2>
@@ -15,6 +19,20 @@
15
19
  <%%= f.<%= attr_form_method(cls, att) %> :<%= att %> %>
16
20
  </div>
17
21
  <% end -%>
22
+ <% if options.select_boxes? -%>
23
+ <% non_nested_belongs_to_classes.each do |cls_name| -%>
24
+ <div class="field">
25
+ <%%= f.label :<%= cls_name %>_id, "<%= cls_name.to_s.underscore.gsub("_", " ").camelize %>" %>
26
+ <%%= f.select :<%= cls_name %>_id, build_select_list(:<%= cls_name %>), {:prompt => "Please select one"} %>
27
+ </div>
28
+ <% end -%>
29
+ <% non_nested_has_many_classes.each do |cls_name| -%>
30
+ <div class="field">
31
+ <%%= f.label :<%= cls_name.to_s.singularize %>_ids, "<%= cls_name.to_s.underscore.gsub("_", " ").camelize %>" %>
32
+ <%%= f.select :<%= cls_name.to_s.singularize %>_ids, build_select_list(:<%= cls_name %>), {:prompt => "Please select"}, {:multiple => true, :size => 4} %>
33
+ </div>
34
+ <% end -%>
35
+ <% end -%>
18
36
  <% nested_belongs_to_classes.each do |cls_name| -%>
19
37
  <%%= f.fields_for :<%= cls_name %> do |nf| %>
20
38
  <%%= render '<%= cls_name.to_s.singularize.underscore %>_fields', :f => nf %>
@@ -0,0 +1,25 @@
1
+ module <%= cls_classname %>SetupHelper
2
+ def setup_<%= cls_underscore %>(obj)
3
+ <% nested_belongs_to_classes.each do |cls_name| -%>
4
+ obj.build_<%= cls_name %> if obj.<%= cls_name %>.blank?
5
+ <% end -%>
6
+ <% nested_has_many_classes.each do |cls_name| -%>
7
+ obj.<%= cls_name %>.build if obj.<%= cls_name %>.empty?
8
+ <% end -%>
9
+ return obj
10
+ end
11
+
12
+ <% if options.select_boxes? -%>
13
+ def build_select_list(assoc, options={})
14
+ name = options[:name] || "name"
15
+ scope = options[:scope] || "all"
16
+ begin
17
+ # name and id associations
18
+ assoc.to_s.classify.constantize.send(scope).map{|a| [a.send(name), a.id]}
19
+ rescue
20
+ # use id for text and value
21
+ assoc.to_s.classify.constantize.send(scope).map(&:id)
22
+ end
23
+ end
24
+ <% end -%>
25
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formgen
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Pullmonkey
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-15 00:00:00 -07:00
18
+ date: 2011-11-16 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -86,14 +86,12 @@ extensions: []
86
86
 
87
87
  extra_rdoc_files:
88
88
  - LICENSE.txt
89
- - README
90
89
  - README.rdoc
91
90
  files:
92
91
  - .document
93
92
  - Gemfile
94
93
  - Gemfile.lock
95
94
  - LICENSE.txt
96
- - README
97
95
  - README.rdoc
98
96
  - Rakefile
99
97
  - VERSION
@@ -107,6 +105,7 @@ files:
107
105
  - lib/generators/skizmo/form/templates/helper.rb
108
106
  - lib/generators/skizmo/form/templates/javascript.js
109
107
  - lib/generators/skizmo/form/templates/new.html.erb
108
+ - lib/generators/skizmo/form/templates/setup_helper.rb
110
109
  - test/helper.rb
111
110
  - test/test_formgen.rb
112
111
  has_rdoc: true
data/README DELETED
@@ -1,40 +0,0 @@
1
- rails g skizmo:form --help
2
- Usage:
3
- rails generate skizmo:form NAME [options]
4
-
5
- Options:
6
- [--javascript] # Indicates when to generate javascript
7
- # Default: true
8
- [--helpers] # Indicates when to generate helpers
9
- # Default: true
10
-
11
- Runtime options:
12
- -p, [--pretend] # Run but do not make any changes
13
- -s, [--skip] # Skip files that already exist
14
- -q, [--quiet] # Supress status output
15
- -f, [--force] # Overwrite files that already exist
16
-
17
- Description:
18
- Generates a form per usual but with fields_for for the has_many and belongs_to associations.
19
-
20
- Example:
21
- rails generate skizmo:form Foo
22
-
23
- With Foo.rb (model like this):
24
- class Foo < ActiveRecord::Base
25
- has_many :bars
26
- belongs_to :baz
27
-
28
- accepts_nested_attributes_for :bars
29
- accepts_nested_attributes_for :baz
30
- end
31
-
32
- This will create:
33
- public/javascripts/jquery.add_remove_links.js
34
- app/helpers/add_remove_links_helper.rb
35
- app/views/foos/new.html.erb
36
- app/views/foos/edit.html.erb
37
- app/views/foos/_form.html.erb
38
- app/views/foos/_bar_fields.html.erb
39
- app/views/foos/_baz_fields.html.erb
40
-