document_form 0.1.0 → 0.1.2
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.
- data/MIT-LICENSE +3 -1
- data/Manifest +1 -3
- data/README.textile +94 -0
- data/Rakefile +1 -1
- data/document_form.gemspec +8 -9
- data/lib/document_form.rb +142 -51
- metadata +7 -22
- data/README +0 -13
- data/lib/mongo_mapper/plugins/multi_parameter_attributes.rb +0 -98
- data/lib/mongoid/multi_parameter_attributes.rb +0 -95
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2007-2008 Justin French
|
2
|
+
Copyright (c) 2010 Maurizio Casimirri
|
2
3
|
|
3
4
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
5
|
a copy of this software and associated documentation files (the
|
@@ -18,3 +19,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
19
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
20
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
21
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
data/Manifest
CHANGED
data/README.textile
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
h1. DocumentForm a Form Builder for Mongoid
|
2
|
+
|
3
|
+
DocumentForm is a Rails3 FormBuilder DSL that aims to provide a super fast and simple form-building tool to edit Mongoid documents in Rails3.
|
4
|
+
DocumentForm is a fork of <a href="http://github.com/justinfrench/formtastic">formtastic</a>.
|
5
|
+
|
6
|
+
h2. Basic Usage
|
7
|
+
|
8
|
+
DocumentForm allows you to create a form almost without coding.
|
9
|
+
|
10
|
+
Model
|
11
|
+
|
12
|
+
<pre>
|
13
|
+
class Person
|
14
|
+
include Mongoid::Document
|
15
|
+
include Mongoid::MultiParameterAttributes
|
16
|
+
|
17
|
+
validates_presence_of :name
|
18
|
+
|
19
|
+
field :name
|
20
|
+
field :secret, :private => true
|
21
|
+
field :birthday, :type => Date
|
22
|
+
field :department_number, :type => Integer, :range => 1..10
|
23
|
+
|
24
|
+
field :description, :long => true
|
25
|
+
end
|
26
|
+
</pre>
|
27
|
+
|
28
|
+
View
|
29
|
+
|
30
|
+
<pre>
|
31
|
+
<% document_form_for @object do |f| %>
|
32
|
+
<%= f.inputs %>
|
33
|
+
<%= f.buttons %>
|
34
|
+
<% end %>
|
35
|
+
</pre>
|
36
|
+
|
37
|
+
* Fields are rendered in the declaration order.
|
38
|
+
* Fields that has :private => true option are not rendered.
|
39
|
+
|
40
|
+
h2. File upload support
|
41
|
+
|
42
|
+
DocumentForm will render automatically file inputs for:
|
43
|
+
|
44
|
+
* Carrierwave
|
45
|
+
* Paperclip
|
46
|
+
* Any other upload library that generates a @_filename@ field in your model
|
47
|
+
|
48
|
+
DocumentForm will configure automatically your form with @:multipart => true@ for each models that has at least a @_filename@ field.
|
49
|
+
|
50
|
+
h2. Installation
|
51
|
+
|
52
|
+
Put this in your @Gemfile@
|
53
|
+
|
54
|
+
<pre>
|
55
|
+
gem document_form
|
56
|
+
</pre>
|
57
|
+
|
58
|
+
and run:
|
59
|
+
|
60
|
+
<pre>
|
61
|
+
bundle install
|
62
|
+
</pre>
|
63
|
+
|
64
|
+
h2. Some advanced examples
|
65
|
+
|
66
|
+
Belongs_to association
|
67
|
+
|
68
|
+
<pre>
|
69
|
+
class Person
|
70
|
+
include Mongoid::Document
|
71
|
+
|
72
|
+
referenced_in :department
|
73
|
+
end
|
74
|
+
</pre>
|
75
|
+
|
76
|
+
Will render a drop down list of departments
|
77
|
+
|
78
|
+
|
79
|
+
Has many association
|
80
|
+
|
81
|
+
<pre>
|
82
|
+
class Person
|
83
|
+
include Mongoid::Document
|
84
|
+
|
85
|
+
references_many :departments, :stored_as => :array
|
86
|
+
end
|
87
|
+
</pre>
|
88
|
+
|
89
|
+
Will render a sequence of checkboxes to pick multiple departments
|
90
|
+
|
91
|
+
h2. Other usage details
|
92
|
+
|
93
|
+
Please refer to <a href="http://github.com/justinfrench/formtastic">formtastic documentation</a> for a more detailed usage guide until DocumentForm documentation will be available.
|
94
|
+
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('document_form', '0.1.
|
5
|
+
Echoe.new('document_form', '0.1.2') do |p|
|
6
6
|
p.description = "Form Builder for Rails3 and MongoID or MongoMapper"
|
7
7
|
p.url = "http://github.com/mcasimir/document_form"
|
8
8
|
p.author = "Maurizio Casimirri"
|
data/document_form.gemspec
CHANGED
@@ -2,24 +2,23 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{document_form}
|
5
|
-
s.version = "0.1.
|
5
|
+
s.version = "0.1.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = [
|
9
|
-
s.date = %q{
|
8
|
+
s.authors = [%q{Maurizio Casimirri}]
|
9
|
+
s.date = %q{2011-12-04}
|
10
10
|
s.description = %q{Form Builder for Rails3 and MongoID or MongoMapper}
|
11
11
|
s.email = %q{maurizio.cas@gmail.com}
|
12
|
-
s.extra_rdoc_files = [
|
13
|
-
s.files = [
|
12
|
+
s.extra_rdoc_files = [%q{README.textile}, %q{lib/document_form.rb}, %q{lib/document_form/i18n.rb}]
|
13
|
+
s.files = [%q{MIT-LICENSE}, %q{README.textile}, %q{Rakefile}, %q{init.rb}, %q{lib/document_form.rb}, %q{lib/document_form/i18n.rb}, %q{Manifest}, %q{document_form.gemspec}]
|
14
14
|
s.homepage = %q{http://github.com/mcasimir/document_form}
|
15
|
-
s.rdoc_options = [
|
16
|
-
s.require_paths = [
|
15
|
+
s.rdoc_options = [%q{--line-numbers}, %q{--inline-source}, %q{--title}, %q{Document_form}, %q{--main}, %q{README.textile}]
|
16
|
+
s.require_paths = [%q{lib}]
|
17
17
|
s.rubyforge_project = %q{document_form}
|
18
|
-
s.rubygems_version = %q{1.
|
18
|
+
s.rubygems_version = %q{1.8.5}
|
19
19
|
s.summary = %q{Form Builder for Rails3 and MongoID or MongoMapper}
|
20
20
|
|
21
21
|
if s.respond_to? :specification_version then
|
22
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
22
|
s.specification_version = 3
|
24
23
|
|
25
24
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
data/lib/document_form.rb
CHANGED
@@ -20,12 +20,15 @@ if defined? Mongoid
|
|
20
20
|
access = name.to_s
|
21
21
|
|
22
22
|
@field_list << access
|
23
|
-
|
23
|
+
check_field_name!(name)
|
24
|
+
add_field(access, options)
|
24
25
|
attr_protected name if options[:accessible] == false
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
30
|
+
|
31
|
+
|
29
32
|
end
|
30
33
|
|
31
34
|
|
@@ -36,7 +39,7 @@ module DocumentForm #:nodoc:
|
|
36
39
|
@@default_text_field_size = 60
|
37
40
|
@@all_fields_required_by_default = false
|
38
41
|
@@include_blank_for_select_by_default = true
|
39
|
-
@@required_string = proc { (%{<abbr title="#{::DocumentForm::I18n.t(:required)}">*</abbr>}).html_safe }
|
42
|
+
@@required_string = "*" #proc { (%{<abbr title="#{::DocumentForm::I18n.t(:required)}">*</abbr>}).html_safe }
|
40
43
|
@@optional_string = ''
|
41
44
|
@@inline_errors = :sentence
|
42
45
|
@@label_str_method = :humanize
|
@@ -51,7 +54,7 @@ module DocumentForm #:nodoc:
|
|
51
54
|
:required_string, :optional_string, :inline_errors, :label_str_method, :collection_label_methods,
|
52
55
|
:inline_order, :file_methods, :priority_countries, :i18n_lookups_by_default, :default_commit_button_accesskey
|
53
56
|
|
54
|
-
RESERVED_COLUMNS = [:_id, :created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
|
57
|
+
RESERVED_COLUMNS = [:_id, :_type, :created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
|
55
58
|
|
56
59
|
INLINE_ERROR_TYPES = [:sentence, :list, :first]
|
57
60
|
|
@@ -104,11 +107,25 @@ module DocumentForm #:nodoc:
|
|
104
107
|
#
|
105
108
|
def input(method, options = {})
|
106
109
|
|
110
|
+
if options[:class].present?
|
111
|
+
options[:input_html] ||= {}
|
112
|
+
options[:input_html][:class] = options[:class]
|
113
|
+
end
|
114
|
+
|
107
115
|
|
108
116
|
options[:required] = method_required?(method) unless options.key?(:required)
|
109
117
|
mm_key = mongomapper_key(method)
|
110
118
|
|
111
|
-
|
119
|
+
if mm_key
|
120
|
+
return nil if !options[:as] && mm_key.type.nil?
|
121
|
+
|
122
|
+
if(!options[:as] && mm_key.options[:in].present?)
|
123
|
+
options[:as] = :select
|
124
|
+
options[:collection] = mm_key.options[:in]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
112
129
|
options[:as] ||= default_input_type(method, options)
|
113
130
|
|
114
131
|
html_class = [ options[:as], (options[:required] ? :required : :optional) ]
|
@@ -289,6 +306,7 @@ module DocumentForm #:nodoc:
|
|
289
306
|
inputs_for_nested_attributes(*(args << html_options), &block)
|
290
307
|
elsif block_given?
|
291
308
|
field_set_and_list_wrapping(*(args << html_options), &block)
|
309
|
+
return nil
|
292
310
|
else
|
293
311
|
if @object && args.empty?
|
294
312
|
args = []
|
@@ -465,7 +483,7 @@ module DocumentForm #:nodoc:
|
|
465
483
|
protected
|
466
484
|
|
467
485
|
class FieldAdapter
|
468
|
-
attr_accessor :name, :type, :required, :options
|
486
|
+
attr_accessor :name, :type, :required, :options, :association, :macro
|
469
487
|
end
|
470
488
|
|
471
489
|
class OrderedHashWithIndifferentAccess < ActiveSupport::OrderedHash
|
@@ -504,7 +522,8 @@ module DocumentForm #:nodoc:
|
|
504
522
|
mmfl.delete("_id")
|
505
523
|
mmfl
|
506
524
|
when :mongoid
|
507
|
-
resource_class.fields.stringify_keys
|
525
|
+
#raise resource_class.fields.stringify_keys.inspect
|
526
|
+
resource_class.fields.stringify_keys
|
508
527
|
end || {}
|
509
528
|
|
510
529
|
flds.keys.each do |name|
|
@@ -513,7 +532,7 @@ module DocumentForm #:nodoc:
|
|
513
532
|
fa = FieldAdapter.new
|
514
533
|
fa.name = name
|
515
534
|
fa.options = field.options
|
516
|
-
fa.type = field.type
|
535
|
+
fa.type = (name.to_s =~ /_id$/) ? BSON::ObjectId : field.type
|
517
536
|
fa.required = is_required_field?(field)
|
518
537
|
|
519
538
|
flds[name] = fa
|
@@ -527,6 +546,19 @@ module DocumentForm #:nodoc:
|
|
527
546
|
f = unordered[fn]
|
528
547
|
if f
|
529
548
|
@df_resource_fields[fn] = f
|
549
|
+
|
550
|
+
elsif orm == :mongoid
|
551
|
+
f = resource_class.associations[fn]
|
552
|
+
|
553
|
+
if f && !f.options[:private]
|
554
|
+
fa = FieldAdapter.new
|
555
|
+
fa.name = fn
|
556
|
+
fa.options = f.options
|
557
|
+
fa.type = f.association
|
558
|
+
fa.required = is_required_field?(f)
|
559
|
+
@df_resource_fields[fn] = fa
|
560
|
+
end
|
561
|
+
|
530
562
|
end
|
531
563
|
}
|
532
564
|
|
@@ -618,7 +650,12 @@ module DocumentForm #:nodoc:
|
|
618
650
|
# configuration option @@all_fields_required_by_default is used.
|
619
651
|
#
|
620
652
|
def method_required?(attribute) #:nodoc:
|
621
|
-
|
653
|
+
rf = resource_fields[attribute]
|
654
|
+
if !rf.nil?
|
655
|
+
rf.required
|
656
|
+
else
|
657
|
+
false
|
658
|
+
end
|
622
659
|
end
|
623
660
|
|
624
661
|
# Determines whether the given options evaluate to true
|
@@ -657,13 +694,22 @@ module DocumentForm #:nodoc:
|
|
657
694
|
|
658
695
|
# Outputs a label and standard Rails text field inside the wrapper.
|
659
696
|
def numeric_input(method, options)
|
697
|
+
options ||= {}
|
698
|
+
html_options = options[:input_html] || {}
|
699
|
+
|
700
|
+
html_options[:size] ||= 8
|
701
|
+
options[:input_html] = html_options
|
702
|
+
|
660
703
|
basic_input_helper(:text_field, :numeric, method, options)
|
661
704
|
end
|
662
705
|
|
663
706
|
# Ouputs a label and standard Rails text area inside the wrapper.
|
664
707
|
def text_input(method, options)
|
665
708
|
options[:input_html] ||= {}
|
666
|
-
options[:input_html][:cols] ||=
|
709
|
+
options[:input_html][:cols] ||= options[:cols]
|
710
|
+
options[:input_html][:rows] ||= options[:rows]
|
711
|
+
|
712
|
+
#options[:input_html][:cols] ||= 60
|
667
713
|
basic_input_helper(:text_area, :text, method, options)
|
668
714
|
end
|
669
715
|
|
@@ -676,6 +722,7 @@ module DocumentForm #:nodoc:
|
|
676
722
|
def markup_input(method, options)
|
677
723
|
options[:input_html] ||= {}
|
678
724
|
options[:input_html][:class] = "markup"
|
725
|
+
options[:input_html][:rows] ||= 20
|
679
726
|
basic_input_helper(:text_area, :text, method, options)
|
680
727
|
end
|
681
728
|
|
@@ -810,7 +857,10 @@ module DocumentForm #:nodoc:
|
|
810
857
|
#
|
811
858
|
def select_input(method, options)
|
812
859
|
mm_key = mongomapper_key(method)
|
860
|
+
options[:include_blank] ||= mm_key.options[:allow_blank]
|
813
861
|
options[:include_blank] = false if mm_key && mm_key.options[:required] && !options[:include_blank].present?
|
862
|
+
options[:collection] ||= mm_key.options[:in]
|
863
|
+
options[:collection] ||= mm_key.options[:collection]
|
814
864
|
|
815
865
|
html_options = options.delete(:input_html) || {}
|
816
866
|
options = set_include_blank(options)
|
@@ -974,10 +1024,10 @@ module DocumentForm #:nodoc:
|
|
974
1024
|
)
|
975
1025
|
|
976
1026
|
li_options = value_as_class ? { :class => [method.to_s.singularize, value.to_s.downcase].join('_') } : {}
|
977
|
-
template.content_tag(:li, li_content, li_options)
|
1027
|
+
template.content_tag(:li, li_content.html_safe, li_options).html_safe
|
978
1028
|
end
|
979
1029
|
|
980
|
-
field_set_and_list_wrapping_for_method(method, options.merge(:label_for => input_ids.first), list_item_content)
|
1030
|
+
field_set_and_list_wrapping_for_method(method, options.merge(:label_for => input_ids.first), list_item_content).html_safe
|
981
1031
|
end
|
982
1032
|
alias :boolean_radio_input :radio_input
|
983
1033
|
|
@@ -1073,6 +1123,11 @@ module DocumentForm #:nodoc:
|
|
1073
1123
|
# This is an absolute abomination, but so is the official Rails select_date().
|
1074
1124
|
#
|
1075
1125
|
def date_or_datetime_input(method, options)
|
1126
|
+
|
1127
|
+
field_options = resource_fields[method].options
|
1128
|
+
options ||= {}
|
1129
|
+
options[:start_year] ||= field_options[:start_year]
|
1130
|
+
|
1076
1131
|
position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
|
1077
1132
|
i18n_date_order = ::I18n.t(:order, :scope => [:date])
|
1078
1133
|
i18n_date_order = nil unless i18n_date_order.is_a?(Array)
|
@@ -1086,8 +1141,11 @@ module DocumentForm #:nodoc:
|
|
1086
1141
|
|
1087
1142
|
default_time = ::Time.now
|
1088
1143
|
|
1144
|
+
datetime_obj = @object.send(method) if @object
|
1145
|
+
|
1089
1146
|
# Gets the datetime object. It can be a Fixnum, Date or Time, or nil.
|
1090
|
-
datetime = options[:selected] ||
|
1147
|
+
datetime = options[:selected] || datetime_obj || default_time
|
1148
|
+
# datetime = datetime.in_time_zone(Time.zone) if (datetime && datetime.respond_to?(:in_time_zone))
|
1091
1149
|
|
1092
1150
|
html_options = options.delete(:input_html) || {}
|
1093
1151
|
input_ids = []
|
@@ -1227,29 +1285,31 @@ module DocumentForm #:nodoc:
|
|
1227
1285
|
#
|
1228
1286
|
#
|
1229
1287
|
def array_input(method, options)
|
1230
|
-
|
1231
|
-
|
1232
|
-
if assoc.
|
1233
|
-
|
1234
|
-
|
1288
|
+
m = method.to_s
|
1289
|
+
|
1290
|
+
if (m =~ /_ids/) && (assoc = resource_class.associations[m.gsub(/_ids$/, "").pluralize]) && assoc.association == Mongoid::Associations::ReferencesManyAsArray
|
1291
|
+
f = resource_fields[m]
|
1292
|
+
klass = f.options[:inverse_class_name].constantize
|
1235
1293
|
|
1236
|
-
collection =
|
1294
|
+
collection = klass.all
|
1237
1295
|
checked = @object.send(:"#{method}") if @object
|
1238
1296
|
checked ||= []
|
1239
1297
|
|
1240
1298
|
|
1241
1299
|
checkboxes = collection.map { |elem|
|
1242
1300
|
name = "#{self.model_name.tableize.singularize}[#{method.to_s}][]"
|
1243
|
-
ckb = if checked.include? elem.
|
1301
|
+
ckb = if checked.include? elem.id
|
1244
1302
|
template.check_box_tag(name, elem._id, {}, :checked => "checked")
|
1245
1303
|
else
|
1246
1304
|
template.check_box_tag(name, elem._id)
|
1247
1305
|
end
|
1248
|
-
label =
|
1306
|
+
label = format_object(elem)
|
1249
1307
|
[ckb, label].join(" ")
|
1250
1308
|
}.map{|checkbox| "<li>#{checkbox}</li>"}.join
|
1251
1309
|
|
1252
|
-
|
1310
|
+
method = m.gsub(/_ids$/, "").pluralize.to_sym if !options[:label].present?
|
1311
|
+
|
1312
|
+
field_set_and_list_wrapping_for_method(method, options, checkboxes.html_safe)
|
1253
1313
|
end
|
1254
1314
|
end
|
1255
1315
|
# Outputs a country select input, wrapping around a regular country_select helper.
|
@@ -1267,7 +1327,7 @@ module DocumentForm #:nodoc:
|
|
1267
1327
|
# f.input :location, :as => :country, :priority_countries => /Australia/ # set your own
|
1268
1328
|
#
|
1269
1329
|
def country_input(method, options)
|
1270
|
-
|
1330
|
+
return basic_input_helper(:text_field, :string, method, options) unless self.respond_to?(:country_select)
|
1271
1331
|
|
1272
1332
|
html_options = options.delete(:input_html) || {}
|
1273
1333
|
priority_countries = options.delete(:priority_countries) || @@priority_countries
|
@@ -1451,8 +1511,8 @@ module DocumentForm #:nodoc:
|
|
1451
1511
|
if column = resource_fields[method]
|
1452
1512
|
|
1453
1513
|
# Special cases where the column type doesn't map to an input method.
|
1454
|
-
type = column.type.name.underscore.to_sym
|
1455
|
-
|
1514
|
+
type = column.type.name.split("::").last.underscore.to_sym
|
1515
|
+
type = :string if type == :object
|
1456
1516
|
|
1457
1517
|
case type
|
1458
1518
|
when :string
|
@@ -1517,55 +1577,84 @@ module DocumentForm #:nodoc:
|
|
1517
1577
|
end
|
1518
1578
|
end
|
1519
1579
|
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1580
|
+
# def fields_method(doc)
|
1581
|
+
# if (defined? MongoMapper) && (doc.include? MongoMapper::Document)
|
1582
|
+
# :keys
|
1583
|
+
# elsif (defined? Mongoid) && (doc.include? Mongoid::Document)
|
1584
|
+
# :fields
|
1585
|
+
# end
|
1586
|
+
# end
|
1587
|
+
|
1588
|
+
# def label_key(doc)
|
1589
|
+
# if doc.send(fields_method(doc)).has_key? :name
|
1590
|
+
# :name
|
1591
|
+
# elsif doc.send(fields_method(doc)).has_key? :title
|
1592
|
+
# :title
|
1593
|
+
# end
|
1594
|
+
# end
|
1595
|
+
|
1596
|
+
# def to_label(obj)
|
1597
|
+
# lcol = label_key(obj.class)
|
1598
|
+
# if obj.respond_to? :to_label
|
1599
|
+
# obj.to_label
|
1600
|
+
# elsif lcol
|
1601
|
+
# obj.send :"#{lcol}"
|
1602
|
+
# else
|
1603
|
+
# ""
|
1604
|
+
# end
|
1605
|
+
# end
|
1539
1606
|
|
1540
1607
|
def format_object(object)
|
1541
|
-
if
|
1542
|
-
to_label
|
1608
|
+
if object.respond_to? :to_label
|
1609
|
+
object.to_label
|
1543
1610
|
elsif object.is_a? DateTime
|
1544
1611
|
I18n.l(object)
|
1545
1612
|
elsif object.is_a? Symbol
|
1546
1613
|
t(object)
|
1614
|
+
elsif object.respond_to? :name
|
1615
|
+
object.name
|
1616
|
+
elsif object.respond_to? :title
|
1617
|
+
object.title
|
1547
1618
|
else
|
1548
1619
|
object
|
1549
1620
|
end
|
1550
1621
|
end
|
1551
1622
|
|
1552
1623
|
|
1624
|
+
def referenced_in_input(method, options)
|
1625
|
+
|
1626
|
+
field = resource_fields[method]
|
1627
|
+
association_class = field.name.to_s.singularize.camelize.constantize
|
1553
1628
|
|
1629
|
+
options[:collection] = association_class.all.map {|obj| [format_object(obj), obj.id]}
|
1630
|
+
|
1631
|
+
if field.options[:allow_blank] == false || field.options[:required] == true
|
1632
|
+
options[:include_blank] = false
|
1633
|
+
end
|
1634
|
+
|
1635
|
+
select_input(method, options)
|
1636
|
+
end
|
1554
1637
|
|
1555
1638
|
def object_id_input(method, options)
|
1639
|
+
field = resource_fields[method]
|
1556
1640
|
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1641
|
+
if options[:collection].nil?
|
1642
|
+
if options[:class_name].present?
|
1643
|
+
association_class = options[:class_name].camelize.constantize
|
1644
|
+
else
|
1645
|
+
association_class = field.name.to_s.gsub(/_id$/, "").singularize.camelize.constantize
|
1646
|
+
end
|
1647
|
+
options[:collection] = association_class.all.map {|obj| [format_object(obj), obj.id]}
|
1648
|
+
end
|
1561
1649
|
|
1562
|
-
options[:collection] = association_class.all.map {|obj| [format_object(obj), obj.id]}
|
1563
1650
|
|
1564
|
-
if
|
1651
|
+
if field.options[:allow_blank] == false || field.options[:required] == true
|
1565
1652
|
options[:include_blank] = false
|
1566
1653
|
end
|
1567
1654
|
|
1568
1655
|
select_input(method, options)
|
1656
|
+
|
1657
|
+
|
1569
1658
|
end
|
1570
1659
|
|
1571
1660
|
# Used by select and radio inputs. The collection can be retrieved by
|
@@ -1911,6 +2000,8 @@ module DocumentForm #:nodoc:
|
|
1911
2000
|
options[:html][:class] = class_names.join(" ")
|
1912
2001
|
|
1913
2002
|
doctype = class_names.last.camelize.constantize
|
2003
|
+
|
2004
|
+
|
1914
2005
|
has_attachments = false
|
1915
2006
|
rfields = if doctype.respond_to?("fields")
|
1916
2007
|
doctype.fields
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: document_form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
version: 0.1.0
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.2
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Maurizio Casimirri
|
@@ -14,8 +10,7 @@ autorequire:
|
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
12
|
|
17
|
-
date:
|
18
|
-
default_executable:
|
13
|
+
date: 2011-12-04 00:00:00 Z
|
19
14
|
dependencies: []
|
20
15
|
|
21
16
|
description: Form Builder for Rails3 and MongoID or MongoMapper
|
@@ -25,23 +20,18 @@ executables: []
|
|
25
20
|
extensions: []
|
26
21
|
|
27
22
|
extra_rdoc_files:
|
28
|
-
- README
|
23
|
+
- README.textile
|
29
24
|
- lib/document_form.rb
|
30
25
|
- lib/document_form/i18n.rb
|
31
|
-
- lib/mongo_mapper/plugins/multi_parameter_attributes.rb
|
32
|
-
- lib/mongoid/multi_parameter_attributes.rb
|
33
26
|
files:
|
34
27
|
- MIT-LICENSE
|
35
|
-
- README
|
28
|
+
- README.textile
|
36
29
|
- Rakefile
|
37
30
|
- init.rb
|
38
31
|
- lib/document_form.rb
|
39
32
|
- lib/document_form/i18n.rb
|
40
|
-
- lib/mongo_mapper/plugins/multi_parameter_attributes.rb
|
41
|
-
- lib/mongoid/multi_parameter_attributes.rb
|
42
33
|
- Manifest
|
43
34
|
- document_form.gemspec
|
44
|
-
has_rdoc: true
|
45
35
|
homepage: http://github.com/mcasimir/document_form
|
46
36
|
licenses: []
|
47
37
|
|
@@ -52,7 +42,7 @@ rdoc_options:
|
|
52
42
|
- --title
|
53
43
|
- Document_form
|
54
44
|
- --main
|
55
|
-
- README
|
45
|
+
- README.textile
|
56
46
|
require_paths:
|
57
47
|
- lib
|
58
48
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -60,22 +50,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
50
|
requirements:
|
61
51
|
- - ">="
|
62
52
|
- !ruby/object:Gem::Version
|
63
|
-
segments:
|
64
|
-
- 0
|
65
53
|
version: "0"
|
66
54
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
55
|
none: false
|
68
56
|
requirements:
|
69
57
|
- - ">="
|
70
58
|
- !ruby/object:Gem::Version
|
71
|
-
segments:
|
72
|
-
- 1
|
73
|
-
- 2
|
74
59
|
version: "1.2"
|
75
60
|
requirements: []
|
76
61
|
|
77
62
|
rubyforge_project: document_form
|
78
|
-
rubygems_version: 1.
|
63
|
+
rubygems_version: 1.8.5
|
79
64
|
signing_key:
|
80
65
|
specification_version: 3
|
81
66
|
summary: Form Builder for Rails3 and MongoID or MongoMapper
|
data/README
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
if defined? MongoMapper
|
2
|
-
|
3
|
-
module MongoMapper
|
4
|
-
module Plugins
|
5
|
-
module MultiParameterAttributes
|
6
|
-
def self.included(model)
|
7
|
-
model.plugin self
|
8
|
-
end
|
9
|
-
|
10
|
-
module InstanceMethods
|
11
|
-
def attributes=(new_attributes)
|
12
|
-
return if new_attributes.nil?
|
13
|
-
|
14
|
-
multi_parameter_attributes = []
|
15
|
-
normal_attributes = {}
|
16
|
-
|
17
|
-
new_attributes.each do |k, v|
|
18
|
-
if k.to_s.include?("(")
|
19
|
-
multi_parameter_attributes << [ k.to_s, v ]
|
20
|
-
else
|
21
|
-
normal_attributes[k] = v
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
assign_multiparameter_attributes(multi_parameter_attributes)
|
26
|
-
|
27
|
-
super(normal_attributes)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
31
|
-
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
32
|
-
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
33
|
-
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
34
|
-
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum, f for Float,
|
35
|
-
# s for String, and a for Array. If all the values for a given attribute are empty, the attribute will be set to nil.
|
36
|
-
def assign_multiparameter_attributes(pairs)
|
37
|
-
execute_callstack_for_multiparameter_attributes(
|
38
|
-
extract_callstack_for_multiparameter_attributes(pairs)
|
39
|
-
)
|
40
|
-
end
|
41
|
-
|
42
|
-
def execute_callstack_for_multiparameter_attributes(callstack)
|
43
|
-
callstack.each do |name, values_with_empty_parameters|
|
44
|
-
# in order to allow a date to be set without a year, we must keep the empty values.
|
45
|
-
# Otherwise, we wouldn't be able to distinguish it from a date with an empty day.
|
46
|
-
values = values_with_empty_parameters.reject(&:nil?)
|
47
|
-
|
48
|
-
if !values.reject{|x| x.blank? }.empty?
|
49
|
-
key = self.class.keys[name]
|
50
|
-
raise ArgumentError, "Unknown key #{name}" if key.nil?
|
51
|
-
klass = key.type
|
52
|
-
|
53
|
-
value = if Time == klass
|
54
|
-
Time.zone.local(*values.map(&:to_i))
|
55
|
-
elsif Date == klass
|
56
|
-
begin
|
57
|
-
values = values_with_empty_parameters.map{|v| v.blank? ? 1 : v.to_i}
|
58
|
-
Date.new(*values)
|
59
|
-
rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
|
60
|
-
Time.zone.local(*values.map(&:to_i)).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
61
|
-
end
|
62
|
-
else
|
63
|
-
klass.new(*values)
|
64
|
-
end
|
65
|
-
writer_method = "#{name}="
|
66
|
-
if respond_to?(writer_method)
|
67
|
-
self.send(writer_method, value)
|
68
|
-
else
|
69
|
-
self[name.to_s] = value
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def extract_callstack_for_multiparameter_attributes(pairs)
|
76
|
-
attributes = { }
|
77
|
-
|
78
|
-
for pair in pairs
|
79
|
-
multiparameter_name, value = pair
|
80
|
-
attribute_name = multiparameter_name.split("(").first
|
81
|
-
attributes[attribute_name] = [] unless attributes.include?(attribute_name)
|
82
|
-
|
83
|
-
attributes[attribute_name] << [ find_parameter_position(multiparameter_name), value ]
|
84
|
-
end
|
85
|
-
|
86
|
-
attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
|
87
|
-
end
|
88
|
-
|
89
|
-
def find_parameter_position(multiparameter_name)
|
90
|
-
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
|
@@ -1,95 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module MultiParameterAttributes
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
self.before_validation :handle_multiparameter_attributes
|
7
|
-
end
|
8
|
-
|
9
|
-
module InstanceMethods
|
10
|
-
protected
|
11
|
-
|
12
|
-
def handle_multiparameter_attributes
|
13
|
-
multiparameter_attributes = []
|
14
|
-
self.attributes.each_pair do |attr_name, value|
|
15
|
-
multiparameter_attributes << [attr_name, value] if attr_name.include?("(")
|
16
|
-
end
|
17
|
-
|
18
|
-
assign_multiparameter_attributes(multiparameter_attributes) if multiparameter_attributes.any?
|
19
|
-
end
|
20
|
-
|
21
|
-
def assign_multiparameter_attributes(pairs)
|
22
|
-
execute_callstack_for_multiparameter_attributes(
|
23
|
-
extract_callstack_for_multiparameter_attributes(pairs)
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
def execute_callstack_for_multiparameter_attributes(callstack)
|
28
|
-
errors = []
|
29
|
-
callstack.each do |name, values_with_empty_parameters|
|
30
|
-
begin
|
31
|
-
klass = self.class.fields[name].type
|
32
|
-
|
33
|
-
puts "Class is #{klass.to_s}"
|
34
|
-
# in order to allow a date to be set without a year, we must keep the empty values.
|
35
|
-
# Otherwise, we wouldn't be able to distinguish it from a date with an empty day.
|
36
|
-
values = values_with_empty_parameters.reject(&:nil?)
|
37
|
-
|
38
|
-
if values.empty?
|
39
|
-
send(name + "=", nil)
|
40
|
-
else
|
41
|
-
|
42
|
-
value = if Time == klass
|
43
|
-
instantiate_time_object(name, values)
|
44
|
-
elsif Date == klass
|
45
|
-
begin
|
46
|
-
values = values_with_empty_parameters.collect do |v| v.nil? ? 1 : v end
|
47
|
-
Date.new(*values)
|
48
|
-
rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
|
49
|
-
instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
50
|
-
end
|
51
|
-
else
|
52
|
-
klass.new(*values)
|
53
|
-
end
|
54
|
-
|
55
|
-
send(name + "=", value)
|
56
|
-
end
|
57
|
-
rescue => ex
|
58
|
-
errors << AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
unless errors.empty?
|
62
|
-
raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def extract_callstack_for_multiparameter_attributes(pairs)
|
67
|
-
attributes = { }
|
68
|
-
|
69
|
-
for pair in pairs
|
70
|
-
multiparameter_name, value = pair
|
71
|
-
attribute_name = multiparameter_name.split("(").first
|
72
|
-
attributes[attribute_name] = [] unless attributes.include?(attribute_name)
|
73
|
-
|
74
|
-
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
75
|
-
attributes[attribute_name] << [ find_parameter_position(multiparameter_name), parameter_value ]
|
76
|
-
end
|
77
|
-
|
78
|
-
attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
|
79
|
-
end
|
80
|
-
|
81
|
-
def type_cast_attribute_value(multiparameter_name, value)
|
82
|
-
multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
|
83
|
-
end
|
84
|
-
|
85
|
-
def find_parameter_position(multiparameter_name)
|
86
|
-
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first
|
87
|
-
end
|
88
|
-
|
89
|
-
def instantiate_time_object(name, values)
|
90
|
-
Time.zone.local(*values)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|