document_form 0.1.0

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.
@@ -0,0 +1,33 @@
1
+ module DocumentForm
2
+ module I18n
3
+
4
+ DEFAULT_SCOPE = [:document_form].freeze
5
+ DEFAULT_VALUES = {
6
+ :required => 'required',
7
+ :yes => 'Yes',
8
+ :no => 'No',
9
+ :create => 'Create {{model}}',
10
+ :update => 'Update {{model}}'
11
+ }.freeze
12
+ SCOPES = [
13
+ '{{model}}.{{action}}.{{attribute}}',
14
+ '{{model}}.{{attribute}}',
15
+ '{{attribute}}'
16
+ ]
17
+
18
+ class << self
19
+
20
+ def translate(*args)
21
+ key = args.shift.to_sym
22
+ options = args.extract_options!
23
+ options.reverse_merge!(:default => DEFAULT_VALUES[key])
24
+ options[:scope] = [DEFAULT_SCOPE, options[:scope]].flatten.compact
25
+ ::I18n.translate(key, *(args << options))
26
+ end
27
+ alias :t :translate
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+
@@ -0,0 +1,98 @@
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
+
@@ -0,0 +1,95 @@
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
+
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: document_form
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Maurizio Casimirri
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-05 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Form Builder for Rails3 and MongoID or MongoMapper
22
+ email: maurizio.cas@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README
29
+ - lib/document_form.rb
30
+ - lib/document_form/i18n.rb
31
+ - lib/mongo_mapper/plugins/multi_parameter_attributes.rb
32
+ - lib/mongoid/multi_parameter_attributes.rb
33
+ files:
34
+ - MIT-LICENSE
35
+ - README
36
+ - Rakefile
37
+ - init.rb
38
+ - lib/document_form.rb
39
+ - lib/document_form/i18n.rb
40
+ - lib/mongo_mapper/plugins/multi_parameter_attributes.rb
41
+ - lib/mongoid/multi_parameter_attributes.rb
42
+ - Manifest
43
+ - document_form.gemspec
44
+ has_rdoc: true
45
+ homepage: http://github.com/mcasimir/document_form
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --line-numbers
51
+ - --inline-source
52
+ - --title
53
+ - Document_form
54
+ - --main
55
+ - README
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 1
73
+ - 2
74
+ version: "1.2"
75
+ requirements: []
76
+
77
+ rubyforge_project: document_form
78
+ rubygems_version: 1.3.7
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Form Builder for Rails3 and MongoID or MongoMapper
82
+ test_files: []
83
+