document_form 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|