formtastic 2.0.2 → 2.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/.gitignore +4 -1
  2. data/Appraisals +11 -0
  3. data/CHANGELOG +2 -2
  4. data/Gemfile +0 -2
  5. data/README.textile +183 -151
  6. data/Rakefile +9 -5
  7. data/app/assets/stylesheets/formtastic.css +16 -3
  8. data/formtastic.gemspec +6 -2
  9. data/gemfiles/rails-3.0.gemfile +7 -0
  10. data/gemfiles/rails-3.1.gemfile +7 -0
  11. data/gemfiles/rails-3.2.gemfile +7 -0
  12. data/lib/formtastic.rb +10 -2
  13. data/lib/formtastic/actions.rb +11 -0
  14. data/lib/formtastic/actions/base.rb +156 -0
  15. data/lib/formtastic/actions/button_action.rb +72 -0
  16. data/lib/formtastic/actions/buttonish.rb +17 -0
  17. data/lib/formtastic/actions/input_action.rb +68 -0
  18. data/lib/formtastic/actions/link_action.rb +87 -0
  19. data/lib/formtastic/engine.rb +5 -1
  20. data/lib/formtastic/form_builder.rb +3 -0
  21. data/lib/formtastic/helpers.rb +2 -1
  22. data/lib/formtastic/helpers/action_helper.rb +109 -0
  23. data/lib/formtastic/helpers/actions_helper.rb +168 -0
  24. data/lib/formtastic/helpers/buttons_helper.rb +22 -9
  25. data/lib/formtastic/helpers/errors_helper.rb +0 -54
  26. data/lib/formtastic/helpers/fieldset_wrapper.rb +10 -5
  27. data/lib/formtastic/helpers/form_helper.rb +2 -2
  28. data/lib/formtastic/helpers/input_helper.rb +1 -10
  29. data/lib/formtastic/helpers/inputs_helper.rb +6 -3
  30. data/lib/formtastic/i18n.rb +3 -2
  31. data/lib/formtastic/inputs/base.rb +11 -3
  32. data/lib/formtastic/inputs/base/choices.rb +6 -1
  33. data/lib/formtastic/inputs/base/collections.rb +36 -13
  34. data/lib/formtastic/inputs/base/grouped_collections.rb +1 -1
  35. data/lib/formtastic/inputs/base/numeric.rb +50 -0
  36. data/lib/formtastic/inputs/base/options.rb +1 -1
  37. data/lib/formtastic/inputs/base/placeholder.rb +17 -0
  38. data/lib/formtastic/inputs/base/stringish.rb +2 -7
  39. data/lib/formtastic/inputs/base/timeish.rb +21 -5
  40. data/lib/formtastic/inputs/base/validations.rb +1 -1
  41. data/lib/formtastic/inputs/base/wrapping.rb +10 -3
  42. data/lib/formtastic/inputs/boolean_input.rb +10 -2
  43. data/lib/formtastic/inputs/check_boxes_input.rb +18 -9
  44. data/lib/formtastic/inputs/country_input.rb +2 -2
  45. data/lib/formtastic/inputs/date_input.rb +19 -1
  46. data/lib/formtastic/inputs/datetime_input.rb +1 -1
  47. data/lib/formtastic/inputs/email_input.rb +2 -1
  48. data/lib/formtastic/inputs/file_input.rb +1 -1
  49. data/lib/formtastic/inputs/hidden_input.rb +1 -1
  50. data/lib/formtastic/inputs/number_input.rb +6 -36
  51. data/lib/formtastic/inputs/password_input.rb +2 -1
  52. data/lib/formtastic/inputs/phone_input.rb +3 -2
  53. data/lib/formtastic/inputs/radio_input.rb +1 -1
  54. data/lib/formtastic/inputs/range_input.rb +8 -32
  55. data/lib/formtastic/inputs/search_input.rb +2 -1
  56. data/lib/formtastic/inputs/select_input.rb +56 -28
  57. data/lib/formtastic/inputs/string_input.rb +3 -1
  58. data/lib/formtastic/inputs/text_input.rb +5 -4
  59. data/lib/formtastic/inputs/time_input.rb +4 -8
  60. data/lib/formtastic/inputs/time_zone_input.rb +1 -1
  61. data/lib/formtastic/inputs/url_input.rb +2 -1
  62. data/lib/formtastic/localized_string.rb +6 -94
  63. data/lib/formtastic/localizer.rb +110 -0
  64. data/lib/formtastic/version.rb +1 -1
  65. data/lib/generators/formtastic/form/form_generator.rb +105 -0
  66. data/lib/generators/templates/_form.html.erb +2 -2
  67. data/lib/generators/templates/_form.html.haml +4 -4
  68. data/lib/generators/templates/_form.html.slim +2 -2
  69. data/lib/generators/templates/formtastic.rb +4 -0
  70. data/lib/locale/en.yml +2 -0
  71. data/sample/basic_inputs.html +22 -0
  72. data/spec/actions/button_action_spec.rb +63 -0
  73. data/spec/actions/generic_action_spec.rb +484 -0
  74. data/spec/actions/input_action_spec.rb +59 -0
  75. data/spec/actions/link_action_spec.rb +92 -0
  76. data/spec/builder/semantic_fields_for_spec.rb +14 -0
  77. data/spec/generators/formtastic/form/form_generator_spec.rb +118 -0
  78. data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
  79. data/spec/helpers/action_helper_spec.rb +365 -0
  80. data/spec/helpers/actions_helper_spec.rb +143 -0
  81. data/spec/helpers/buttons_helper_spec.rb +39 -23
  82. data/spec/helpers/commit_button_helper_spec.rb +153 -93
  83. data/spec/helpers/inputs_helper_spec.rb +14 -0
  84. data/spec/i18n_spec.rb +11 -0
  85. data/spec/inputs/boolean_input_spec.rb +31 -2
  86. data/spec/inputs/check_boxes_input_spec.rb +29 -1
  87. data/spec/inputs/date_input_spec.rb +95 -0
  88. data/spec/inputs/datetime_input_spec.rb +49 -0
  89. data/spec/inputs/email_input_spec.rb +28 -0
  90. data/spec/inputs/file_input_spec.rb +28 -0
  91. data/spec/inputs/hidden_input_spec.rb +28 -0
  92. data/spec/inputs/include_blank_spec.rb +53 -45
  93. data/spec/inputs/number_input_spec.rb +34 -4
  94. data/spec/inputs/password_input_spec.rb +28 -0
  95. data/spec/inputs/phone_input_spec.rb +28 -0
  96. data/spec/inputs/placeholder_spec.rb +10 -10
  97. data/spec/inputs/radio_input_spec.rb +51 -6
  98. data/spec/inputs/range_input_spec.rb +30 -2
  99. data/spec/inputs/search_input_spec.rb +27 -0
  100. data/spec/inputs/select_input_spec.rb +52 -6
  101. data/spec/inputs/string_input_spec.rb +28 -0
  102. data/spec/inputs/text_input_spec.rb +27 -0
  103. data/spec/inputs/time_input_spec.rb +67 -1
  104. data/spec/inputs/time_zone_input_spec.rb +28 -0
  105. data/spec/inputs/url_input_spec.rb +28 -0
  106. data/spec/inputs/with_options_spec.rb +43 -0
  107. data/spec/spec_helper.rb +22 -6
  108. data/spec/support/custom_macros.rb +6 -134
  109. data/spec/support/test_environment.rb +0 -1
  110. metadata +104 -17
  111. data/lib/formtastic/helpers/semantic_form_helper.rb +0 -11
  112. data/lib/formtastic/inputs/numeric_input.rb +0 -21
  113. data/lib/formtastic/railtie.rb +0 -12
  114. data/lib/formtastic/semantic_form_builder.rb +0 -11
  115. data/spec/builder/errors_spec.rb +0 -203
  116. data/spec/inputs/numeric_input_spec.rb +0 -41
@@ -25,10 +25,12 @@ module Formtastic
25
25
  # </fieldset>
26
26
  # </form>
27
27
  #
28
- # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documetation of all possible options.
28
+ # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
29
29
  class StringInput
30
30
  include Base
31
31
  include Base::Stringish
32
+ include Base::Placeholder
33
+
32
34
  end
33
35
  end
34
36
  end
@@ -9,24 +9,25 @@ module Formtastic
9
9
  #
10
10
  # <%= semantic_form_for(@user) do |f| %>
11
11
  # <%= f.inputs do %>
12
- # <%= f.input :first_name, :as => :string %>
12
+ # <%= f.input :first_name, :as => :text %>
13
13
  # <% end %>
14
14
  # <% end %>
15
15
  #
16
16
  # <form...>
17
17
  # <fieldset>
18
18
  # <ol>
19
- # <li class="string">
19
+ # <li class="text">
20
20
  # <label for="user_first_name">First name</label>
21
- # <input type="text" id="user_first_name" name="user[first_name]">
21
+ # <textarea cols="30" id="user_first_name" name="user[first_name]" rows="20"></textarea>
22
22
  # </li>
23
23
  # </ol>
24
24
  # </fieldset>
25
25
  # </form>
26
26
  #
27
- # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documetation of all possible options.
27
+ # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
28
28
  class TextInput
29
29
  include Base
30
+ include Base::Placeholder
30
31
 
31
32
  def input_html_options
32
33
  {
@@ -5,7 +5,7 @@ module Formtastic
5
5
  # well, defaulting to `Time.current` if the form object doesn't have a value, much like Rails'
6
6
  # own `time_select`.
7
7
  #
8
- # @see Formtastic::Inputs::Timeish Timeish module for documetation of date, time and datetime input options.
8
+ # @see Formtastic::Inputs::Base::Timeish Timeish module for documentation of date, time and datetime input options.
9
9
  class TimeInput
10
10
  include Base
11
11
  include Base::Timeish
@@ -15,18 +15,14 @@ module Formtastic
15
15
  time_fragments
16
16
  end
17
17
 
18
- def value_or_default_value
19
- value ? value : Time.current
20
- end
21
-
22
18
  def fragment_value(fragment)
23
- value_or_default_value.send(fragment)
19
+ value ? value.send(fragment) : ""
24
20
  end
25
21
 
26
22
  def hidden_fragments
27
23
  if !options[:ignore_date]
28
24
  date_fragments.map do |fragment|
29
- template.hidden_field_tag("#{object_name}[#{fragment_name(fragment)}]", fragment_value(fragment), :id => fragment_id(fragment), :disabled => input_html_options[:disabled] )
25
+ template.hidden_field_tag(hidden_field_name(fragment), fragment_value(fragment), :id => fragment_id(fragment), :disabled => input_html_options[:disabled] )
30
26
  end.join.html_safe
31
27
  else
32
28
  super
@@ -35,4 +31,4 @@ module Formtastic
35
31
 
36
32
  end
37
33
  end
38
- end
34
+ end
@@ -26,7 +26,7 @@ module Formtastic
26
26
  # </fieldset>
27
27
  # </form>
28
28
  #
29
- # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documetation of all possible options.
29
+ # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
30
30
  #
31
31
  # @todo document :priority_zones option
32
32
  # @todo configurable default :priority_zones?
@@ -24,10 +24,11 @@ module Formtastic
24
24
  # </fieldset>
25
25
  # </form>
26
26
  #
27
- # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documetation of all possible options.
27
+ # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
28
28
  class UrlInput
29
29
  include Base
30
30
  include Base::Stringish
31
+ include Base::Placeholder
31
32
 
32
33
  def to_html
33
34
  input_wrapping do
@@ -1,105 +1,17 @@
1
1
  module Formtastic
2
- # @private
3
2
  module LocalizedString
4
3
 
5
- protected
6
-
7
- # Internal generic method for looking up localized values within Formtastic
8
- # using I18n, if no explicit value is set and I18n-lookups are enabled.
9
- #
10
- # Enabled/Disable this by setting:
11
- #
12
- # Formtastic::FormBuilder.i18n_lookups_by_default = true/false
13
- #
14
- # Lookup priority:
15
- #
16
- # 'formtastic.%{type}.%{model}.%{action}.%{attribute}'
17
- # 'formtastic.%{type}.%{model}.%{attribute}'
18
- # 'formtastic.%{type}.%{attribute}'
19
- #
20
- # Example:
21
- #
22
- # 'formtastic.labels.post.edit.title'
23
- # 'formtastic.labels.post.title'
24
- # 'formtastic.labels.title'
25
- #
26
- # NOTE: Generic, but only used for form input titles/labels/hints/actions (titles = legends, actions = buttons).
27
- #
28
- def localized_string(key, value, type, options = {}) #:nodoc:
29
- key = value if value.is_a?(::Symbol)
30
-
31
- if value.is_a?(::String)
32
- escape_html_entities(value)
33
- else
34
- use_i18n = value.nil? ? i18n_lookups_by_default : (value != false)
35
-
36
- if use_i18n
37
- model_name, nested_model_name = normalize_model_name(self.model_name.underscore)
38
-
39
- action_name = template.params[:action].to_s rescue ''
40
- attribute_name = key.to_s
41
-
42
- defaults = Formtastic::I18n::SCOPES.reject do |i18n_scope|
43
- nested_model_name.nil? && i18n_scope.match(/nested_model/)
44
- end.collect do |i18n_scope|
45
- i18n_path = i18n_scope.dup
46
- i18n_path.gsub!('%{action}', action_name)
47
- i18n_path.gsub!('%{model}', model_name)
48
- i18n_path.gsub!('%{nested_model}', nested_model_name) unless nested_model_name.nil?
49
- i18n_path.gsub!('%{attribute}', attribute_name)
50
- i18n_path.gsub!('..', '.')
51
- i18n_path.to_sym
52
- end
53
- defaults << ''
54
-
55
- defaults.uniq!
56
-
57
- default_key = defaults.shift
58
- i18n_value = Formtastic::I18n.t(default_key,
59
- options.merge(:default => defaults, :scope => type.to_s.pluralize.to_sym))
60
- i18n_value = i18n_value.is_a?(::String) ? i18n_value : nil
61
- if i18n_value.blank? && type == :label
62
- # This is effectively what Rails label helper does for i18n lookup
63
- options[:scope] = [:helpers, type]
64
- options[:default] = defaults
65
- i18n_value = ::I18n.t(default_key, options)
66
- end
67
- (i18n_value.is_a?(::String) && i18n_value.present?) ? escape_html_entities(i18n_value) : nil
68
- end
69
- end
70
- end
71
-
72
4
  def model_name
73
5
  @object.present? ? @object.class.name : @object_name.to_s.classify
74
6
  end
75
7
 
76
- def normalize_model_name(name)
77
- if !name =~ /\[/ && self.respond_to?(:builder) && builder.respond_to?(:parent_builder) && builder.parent_builder.object_name
78
- # Rails 3.1 nested builder case
79
- [builder.parent_builder.object_name.to_s, name]
80
- elsif name =~ /(.+)\[(.+)\]/
81
- # Rails 3 (and 3.1?) nested builder case with :post rather than @post
82
- [$1, $2]
83
- elsif self.respond_to?(:builder) && builder.respond_to?(:options) && builder.options.key?(:parent_builder)
84
- # Rails 3.0 nested builder work-around case, where :parent_builder is provided by f.semantic_form_for
85
- [builder.options[:parent_builder].object_name.to_s, name]
86
- else
87
- # Non-nested case
88
- [name]
89
- end
90
- end
91
-
92
- def escape_html_entities(string) #:nodoc:
93
- if (respond_to?(:builder) && builder.escape_html_entities_in_hints_and_labels) ||
94
- (self.respond_to?(:escape_html_entities_in_hints_and_labels) && escape_html_entities_in_hints_and_labels)
95
- string = template.escape_once(string) unless string.respond_to?(:html_safe?) && string.html_safe? == true # Acceppt html_safe flag as indicator to skip escaping
96
- end
97
- string
98
- end
8
+ protected
99
9
 
100
- def i18n_lookups_by_default
101
- respond_to?(:builder) ? builder.i18n_lookups_by_default : i18n_lookups_by_default
10
+ def localized_string(key, value, type, options = {}) #:nodoc:
11
+ current_builder = respond_to?(:builder) ? builder : self
12
+ localizer = Formtastic::FormBuilder.i18n_localizer.new(current_builder)
13
+ localizer.localize(key, value, type, options)
102
14
  end
103
15
 
104
16
  end
105
- end
17
+ end
@@ -0,0 +1,110 @@
1
+ module Formtastic
2
+ # Implementation for looking up localized values within Formtastic using I18n, if no
3
+ # explicit value (like the `:label` option) is set and I18n-lookups are enabled in the
4
+ # configuration.
5
+ #
6
+ # You can subclass this to implement your own Localizer, and configure Formtastic to use this
7
+ # localizer with:
8
+ #
9
+ # Formtastic::FormBuilder.i18n_localizer
10
+ #
11
+ # Enabled/disable i18n lookups completely with:
12
+ #
13
+ # Formtastic::FormBuilder.i18n_lookups_by_default = true/false
14
+ #
15
+ # Lookup priority:
16
+ #
17
+ # 'formtastic.%{type}.%{model}.%{action}.%{attribute}'
18
+ # 'formtastic.%{type}.%{model}.%{attribute}'
19
+ # 'formtastic.%{type}.%{attribute}'
20
+ #
21
+ # Example:
22
+ #
23
+ # 'formtastic.labels.post.edit.title'
24
+ # 'formtastic.labels.post.title'
25
+ # 'formtastic.labels.title'
26
+ class Localizer
27
+
28
+ attr_accessor :builder
29
+
30
+ def initialize(current_builder)
31
+ self.builder = current_builder
32
+ end
33
+
34
+ def localize(key, value, type, options = {}) #:nodoc:
35
+ key = value if value.is_a?(::Symbol)
36
+
37
+ if value.is_a?(::String)
38
+ escape_html_entities(value)
39
+ else
40
+ use_i18n = value.nil? ? i18n_lookups_by_default : (value != false)
41
+
42
+ if use_i18n
43
+ model_name, nested_model_name = normalize_model_name(builder.model_name.underscore)
44
+
45
+ action_name = builder.template.params[:action].to_s rescue ''
46
+ attribute_name = key.to_s
47
+
48
+
49
+ defaults = Formtastic::I18n::SCOPES.reject do |i18n_scope|
50
+ nested_model_name.nil? && i18n_scope.match(/nested_model/)
51
+ end.collect do |i18n_scope|
52
+ i18n_path = i18n_scope.dup
53
+ i18n_path.gsub!('%{action}', action_name)
54
+ i18n_path.gsub!('%{model}', model_name)
55
+ i18n_path.gsub!('%{nested_model}', nested_model_name) unless nested_model_name.nil?
56
+ i18n_path.gsub!('%{attribute}', attribute_name)
57
+ i18n_path.gsub!('..', '.')
58
+ i18n_path.to_sym
59
+ end
60
+ defaults << ''
61
+
62
+ defaults.uniq!
63
+
64
+ default_key = defaults.shift
65
+ i18n_value = Formtastic::I18n.t(default_key,
66
+ options.merge(:default => defaults, :scope => type.to_s.pluralize.to_sym))
67
+ i18n_value = i18n_value.is_a?(::String) ? i18n_value : nil
68
+ if i18n_value.blank? && type == :label
69
+ # This is effectively what Rails label helper does for i18n lookup
70
+ options[:scope] = [:helpers, type]
71
+ options[:default] = defaults
72
+ i18n_value = ::I18n.t(default_key, options)
73
+ end
74
+ (i18n_value.is_a?(::String) && i18n_value.present?) ? escape_html_entities(i18n_value) : nil
75
+ end
76
+ end
77
+ end
78
+
79
+ protected
80
+
81
+ def normalize_model_name(name)
82
+ if !name =~ /\[/ && builder.respond_to?(:parent_builder) && builder.parent_builder.object_name
83
+ # Rails 3.1 nested builder case
84
+ [builder.parent_builder.object_name.to_s, name]
85
+ elsif name =~ /(.+)\[(.+)\]/
86
+ # Rails 3 (and 3.1?) nested builder case with :post rather than @post
87
+ [$1, $2]
88
+ elsif builder.respond_to?(:options) && builder.options.key?(:parent_builder)
89
+ # Rails 3.0 nested builder work-around case, where :parent_builder is provided by f.semantic_form_for
90
+ [builder.options[:parent_builder].object_name.to_s, name]
91
+ else
92
+ # Non-nested case
93
+ [name]
94
+ end
95
+ end
96
+
97
+ def escape_html_entities(string) #:nodoc:
98
+ if (builder.escape_html_entities_in_hints_and_labels) ||
99
+ (self.respond_to?(:escape_html_entities_in_hints_and_labels) && escape_html_entities_in_hints_and_labels)
100
+ string = builder.template.escape_once(string) unless string.respond_to?(:html_safe?) && string.html_safe? == true # Accept html_safe flag as indicator to skip escaping
101
+ end
102
+ string
103
+ end
104
+
105
+ def i18n_lookups_by_default
106
+ builder.i18n_lookups_by_default
107
+ end
108
+
109
+ end
110
+ end
@@ -1,3 +1,3 @@
1
1
  module Formtastic
2
- VERSION = "2.0.2"
2
+ VERSION = "2.1.0.beta1"
3
3
  end
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+ module Formtastic
3
+ # Generates a Formtastic form partial based on an existing model. It will not overwrite existing
4
+ # files without confirmation.
5
+ #
6
+ # @example
7
+ # $ rails generate formtastic:form Post
8
+ # @example Copy the partial code to the pasteboard rather than generating a partial
9
+ # $ rails generate formtastic:form Post --copy
10
+ # @example Return HAML output instead of default template engine
11
+ # $ rails generate formtastic:form Post --haml
12
+ # @example Generate a form for specific model attributes
13
+ # $ rails generate formtastic:form Post title:string body:text
14
+ # @example Generate a form for a specific controller
15
+ # $ rails generate formtastic:form Post --controller admin/posts
16
+ class FormGenerator < Rails::Generators::NamedBase
17
+ desc "Generates a Formtastic form partial based on an existing model."
18
+
19
+ argument :name, :type => :string, :required => true, :banner => 'MODEL_NAME'
20
+ argument :attributes, :type => :array, :default => [], :banner => 'attribute attribute'
21
+
22
+ source_root File.expand_path('../../../templates', __FILE__)
23
+
24
+ class_option :template_engine
25
+
26
+ class_option :copy, :type => :boolean, :default => false, :group => :formtastic,
27
+ :desc => 'Copy the generated code the clipboard instead of generating a partial file."'
28
+
29
+ class_option :controller, :type => :string, :default => false, :group => :formtastic,
30
+ :desc => 'Generate for custom controller/view path - in case model and controller namespace is different, i.e. "admin/posts"'
31
+
32
+ def create_or_show
33
+ @attributes = reflected_attributes if @attributes.empty?
34
+
35
+ engine = options[:template_engine]
36
+
37
+ if options[:copy]
38
+ template = File.read("#{self.class.source_root}/_form.html.#{engine}")
39
+ erb = ERB.new(template, nil, '-')
40
+ generated_code = erb.result(binding).strip rescue nil
41
+ puts "The following code has been copied to the clipboard, just paste it in your views:" if save_to_clipboard(generated_code)
42
+ puts generated_code || "Error: Nothing generated. Does the model exist?"
43
+ else
44
+ empty_directory "app/views/#{controller_path}"
45
+ template "_form.html.#{engine}", "app/views/#{controller_path}/_form.html.#{engine}"
46
+ end
47
+ end
48
+
49
+ protected
50
+
51
+ def controller_path
52
+ @controller_path ||= if options[:controller]
53
+ options[:controller].underscore
54
+ else
55
+ name.underscore.pluralize
56
+ end
57
+ end
58
+
59
+ def reflected_attributes
60
+ columns = content_columns
61
+ columns += association_columns
62
+ end
63
+
64
+ def model
65
+ @model ||= name.camelize.constantize
66
+ end
67
+
68
+ # Collects content columns (non-relation columns) for the current class.
69
+ # Skips Active Record Timestamps.
70
+ def content_columns
71
+ model.content_columns.select do |column|
72
+ !Formtastic::Helpers::InputsHelper::SKIPPED_COLUMNS.include? column.name.to_sym
73
+ end
74
+ end
75
+
76
+ # Collects association columns (relation columns) for the current class. Skips polymorphic
77
+ # associations because we can't guess which class to use for an automatically generated input.
78
+ def association_columns
79
+ model.reflect_on_all_associations(:belongs_to).select do |association_reflection|
80
+ association_reflection.options[:polymorphic] != true
81
+ end
82
+ end
83
+
84
+ def save_to_clipboard(data)
85
+ return unless data
86
+
87
+ begin
88
+ case RUBY_PLATFORM
89
+ when /win32/
90
+ require 'win32/clipboard'
91
+ ::Win32::Clipboard.data = data
92
+ when /darwin/ # mac
93
+ `echo "#{data}" | pbcopy`
94
+ else # linux/unix
95
+ `echo "#{data}" | xsel --clipboard` || `echo "#{data}" | xclip`
96
+ end
97
+ rescue LoadError
98
+ false
99
+ else
100
+ true
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -5,7 +5,7 @@
5
5
  <%- end -%>
6
6
  <%% end %>
7
7
 
8
- <%%= f.buttons do %>
9
- <%%= f.commit_button %>
8
+ <%%= f.actions do %>
9
+ <%%= f.action(:submit, :as => :input) %>
10
10
  <%% end %>
11
11
  <%% end %>