diff --git a/lib/action_view/helpers/dynamic_form.rb b/lib/action_view/helpers/dynamic_form.rb
index ecc171a..243d78a 100644
--- a/lib/action_view/helpers/dynamic_form.rb
+++ b/lib/action_view/helpers/dynamic_form.rb
@@ -15,10 +15,12 @@ module DynamicForm
# has an attribute +title+ mapped to a +VARCHAR+ column that holds "Hello World":
#
# input("post", "title")
- # # =>
- def input(record_name, method, options = {})
- raise_broken_code_error
- InstanceTag.new(record_name, method, self).to_tag(options)
+ # # =>
+ #
+ # input("post", "title", "maxlength" => 10)
+ # # =>
+ def input(object_name, method, options = {})
+ InputBuilder.new(object_name, method, self, options).to_tag
end
# Returns an entire form with all needed input tags for a specified Active Record object. For example, if @post
@@ -262,29 +264,55 @@ def default_input_block
Proc.new { |record, column| %(
#{input(record, column.name)}
) }
end
- module InstanceTagMethods
- def to_tag(options = {})
+
+ module InputBuilderMethods
+ DEFAULT_MAXLENGTH = 30
+
+ def initialize(object_name, method, context, options)
+ @object_name = object_name
+ @context = context
+ @method = method
+ @options = options
+ end
+
+ def to_tag
case column_type
- when :string
- field_type = @method_name.include?("password") ? "password" : "text"
- to_input_field_tag(field_type, options)
- when :text
- to_text_area_tag(options)
- when :integer, :float, :decimal
- to_input_field_tag("text", options)
- when :date
- to_date_select_tag(options)
- when :datetime, :timestamp
- to_datetime_select_tag(options)
- when :time
- to_time_select_tag(options)
- when :boolean
- to_boolean_select_tag(options).html_safe
+ when :string
+ @options["type"] = @method.include?("password") ? "password" : "text"
+ Tags::TextField.new(*generic_args).render
+ when :text
+ Tags::TextArea.new(*generic_args).render
+ when :integer, :float, :decimal
+ Tags::TextField.new(*generic_args).render
+ when :date
+ Tags::DateField.new(*generic_args).render
+ when :datetime, :timestamp
+ Tags::DatetimeLocalField.new(*generic_args).render
+ when :time
+ Tags::TimeField.new(*generic_args).render
+ when :boolean
+ Tags::CheckBox.new(@object_name, @method, @context, "1", "0", @options).render
+ end
+ end
+
+ private
+
+ def options_with_default
+ @options.tap do |options|
+ options["maxlength"] = DEFAULT_MAXLENGTH unless @options.key?("maxlength")
end
end
+ def generic_args
+ [ @object_name, @method, @context, options_with_default ]
+ end
+
+ def object
+ @context.instance_variable_get("@#{@object_name}")
+ end
+
def column_type
- object.send(:column_for_attribute, @method_name).type
+ object.send(:column_for_attribute, @method).type
end
end
@@ -299,8 +327,8 @@ def error_messages(options = {})
end
end
- class InstanceTag
- include DynamicForm::InstanceTagMethods
+ class InputBuilder
+ include DynamicForm::InputBuilderMethods
end
class FormBuilder
diff --git a/test/dynamic_form_test.rb b/test/dynamic_form_test.rb
index 0a5ec72..1cf1925 100644
--- a/test/dynamic_form_test.rb
+++ b/test/dynamic_form_test.rb
@@ -10,12 +10,12 @@ def form_for(*)
end
silence_warnings do
- class Post < Struct.new(:title, :author_name, :body, :secret, :written_on)
+ class Post < Struct.new(:title, :author_name, :body, :secret, :written_on, :published_on, :started_at, :published)
extend ActiveModel::Naming
include ActiveModel::Conversion
end
- class User < Struct.new(:email)
+ class User < Struct.new(:email, :password)
extend ActiveModel::Naming
include ActiveModel::Conversion
end
@@ -78,14 +78,27 @@ def @post.column_for_attribute(attr_name)
end
silence_warnings do
- def Post.content_columns() [ Column.new(:string, "title", "Title"), Column.new(:text, "body", "Body") ] end
+ def Post.content_columns()
+ [
+ Column.new(:string, "title", "Title"),
+ Column.new(:text, "body", "Body"),
+ Column.new(:integer, "secret", "Secret"),
+ Column.new(:date, "written_on", "Written On"),
+ Column.new(:datetime, "published_on", "Published On"),
+ Column.new(:time, "started_at", "Started At"),
+ Column.new(:boolean, "published", "Published")
+ ]
+ end
end
- @post.title = "Hello World"
- @post.author_name = ""
- @post.body = "Back to the hill and over it again!"
- @post.secret = 1
- @post.written_on = Date.new(2004, 6, 15)
+ @post.title = "Hello World"
+ @post.author_name = ""
+ @post.body = "Back to the hill and over it again!"
+ @post.secret = 1
+ @post.written_on = Date.new(2004, 6, 15)
+ @post.published_on = Date.new(2005, 8, 23)
+ @post.started_at = Time.new(2024, 4, 2, 21, 44, 10)
+ @post.published = true
end
def setup_user
@@ -107,10 +120,11 @@ def @user.column_for_attribute(attr_name)
end
silence_warnings do
- def User.content_columns() [ Column.new(:string, "email", "Email") ] end
+ def User.content_columns() [ Column.new(:string, "email", "Email"), Column.new(:string, "password", "Password") ] end
end
@user.email = ""
+ @user.password = "password"
end
def protect_against_forgery?
@@ -130,11 +144,59 @@ def url_for(options)
end
def test_generic_input_tag
- assert_raise(BrokenFeatureError) do
assert_dom_equal(
- %(), input("post", "title")
+ %(), input("post", "title")
+ )
+ end
+
+ def test_input_tag_with_maxlength
+ assert_dom_equal(
+ %(), input("post", "title", "maxlength" => 10)
+ )
+ end
+
+ def test_input_for_password
+ assert_dom_equal(
+ %(), input("user", "password")
+ )
+ end
+
+ def test_input_for_text
+ def @post.errors; end
+
+ assert_dom_equal(
+ %(), input("post", "body")
+ )
+ end
+
+ def test_input_tag_for_integer
+ assert_dom_equal(
+ %(), input("post", "secret")
+ )
+ end
+
+ def test_input_tag_for_date
+ assert_dom_equal(
+ %(), input("post", "written_on")
+ )
+ end
+
+ def test_input_tag_for_datetime
+ assert_dom_equal(
+ %(), input("post", "published_on")
+ )
+ end
+
+ def test_input_tag_for_time
+ assert_dom_equal(
+ %(), input("post", "started_at")
+ )
+ end
+
+ def test_input_tag_for_boolean
+ assert_dom_equal(
+ %(), input("post", "published")
)
- end
end
def test_text_area_with_errors
@@ -225,10 +287,10 @@ def inner_test_form_with_method_option
def test_form_with_action_option
assert_raise(BrokenFeatureError) do
- output_buffer << form("post", :action => "sign")
- assert_select "form[action=sign]" do |form|
- assert_select "input[type=submit][value=Sign]"
- end
+ output_buffer << form("post", :action => "sign")
+ assert_select "form[action=sign]" do |form|
+ assert_select "input[type=submit][value=Sign]"
+ end
end
end