Is it possible to use Simple Form (by: Plataformatec) without a model?
-
Maybe [my answer to the other question][1] helps you. [1]: http://stackoverflow.com/a/14659270/157816 – baxang Feb 02 '13 at 06:32
-
Check out http://stackoverflow.com/questions/12146466/rails-simple-form-fields-not-related-to-the-model – netwire Aug 13 '13 at 02:11
6 Answers
You can use :symbol
as the first argument.
<%= simple_form_for :user, url: users_path do |f| %>
<%= f.input :name, as: :string %>
...
<% end %>
It will output something like this:
<form novalidate="novalidate" class="simple_form user" action="/users" accept-charset="UTF-8" method="post">
...
<div class="input string required user_name">
<label class="string required" for="user_name">
<abbr title="required">*</abbr> Name
</label>
<input class="string required" type="text" name="user[name]" id="user_name" />
</div>
...
</form>

- 36,666
- 8
- 50
- 57
-
Kind of pointless though isn't it? You don't get any of the benefits of simple_form_for when you're using the fallback textfield generators. – toxaq Jul 20 '12 at 23:23
-
4@toxaq Maybe that's not a good example. You can use `f.input :name, :as => :string` and generate your usual form with label, hints, etc. – htanata Jul 20 '12 at 23:48
-
9Oddly that's exactly what I'm trying to do and having no success. Your example gives an `undefined method 'name?' for nil:NilClass` for me at least. – toxaq Jul 21 '12 at 00:11
-
11This option still uses a model under the covers. The symbol should match a model name, it will resolve to a model and create a new one and use it on every field, so the properties used in the form fields should actually exists in the model. – Miguel Madero Jul 02 '13 at 19:32
-
22I don't understand why this is the accepted answer, because the answer is just wrong. – Phillipp Sep 16 '14 at 14:27
-
Well, I won't say the answer is wrong, but it seems to miss the whole point of the question. Unless I'm missing it? – codenoob Nov 09 '14 at 17:11
-
1Yeah, I think I missed the point previously, and I've written a better answer as [comment](http://stackoverflow.com/questions/5181143/simple-form-without-for-non-model-form/5181627?noredirect=1#comment15335055_5181627). I've updated the answer so it does what simple_form is supposed to do. – htanata Nov 10 '14 at 17:37
-
Still problem is how to autofill those inputs, if form is used for report generation for example. Tried to used hash instead of ActiveRecord object with no luck. – nazar kuliyev Nov 24 '15 at 08:21
-
This worked for me, but had to include `input_html: { value: nil }` to avoid `undefined method 'name'` error – AlexGuti Mar 21 '16 at 11:49
Unfortunately simple_form relies on using a model. Essentially it would be nice to have something like simple_form_tag and input_tag methods equivalent to their rails *_tag helpers. Until then, there's an easy work around.
Use a symbol instead of the class in the form and pass the value explicitly to prevent simple_form from trying to access the model properties.
<%= simple_form_for :user, :url => '/users' do |f| %>
<%= f.text_field :name, input_html: { value: nil } %>
<% end %>
This will avoid the undefined method 'name' for User
error.

- 1,948
- 13
- 21
-
2This worked for me: <%= f.input :create_key, input_html: {value: nil}, required: true, hint: "by invite only, see email for key" %> – codenoob Nov 09 '14 at 17:44
-
1If working with a collection, use `selected` instead of `value` in order to avoid the `undefined method 'name' for Model` error – fkoessler Nov 02 '15 at 10:17
-
" simple_form relies on using a model" thanks this is exactly what I was looking for :) – Olivier Girardot Aug 14 '21 at 14:45
You can also use fields outside the model within a form model, with simple_fields_for like this:
<%= simple_form_for @user do |f| %>
<%= f.input :name %>
<%= simple_fields_for :no_model_fields do |n| %>
<%= n.input :other_field %>
<% end %>
<% end %>
This is simple and practical solution, because you can create different kind of fields from different models or without using models

- 1,250
- 2
- 14
- 23
You could also pass a :symbol
instead of @object
as argument for simple_form_for
.
<%= simple_form_for :email, :url => '/post_email' do |f| %>
<%= f.input :subject, :as => :string %>
<% end %>
Which would output:
<form method="post" class="simple_form email" action="/post_email" accept-charset="UTF-8">
...
<input type="text" size="30" name="email[subject]" id="email_subject">
</form>
Please be aware of following draw-backs:
- You won't be able to take advantage of automatic model validation
- Need to explicitly define
:url
and the type of eachinput

- 5,188
- 5
- 27
- 26
-
3This option still uses a model under the covers. The symbol should match a model name, it will resolve to a model and create a new one and use it on every field, so the properties used in the form fields should actually exists in the model. – Miguel Madero Jul 02 '13 at 19:33
All of the methods above still leave you with form data nested inside of "user" or whatever symbol that you pass as the first argument. That's annoying.
To mimic simple_form's style/benefits, but remove the object/symbol dependency and the forced data nesting, you can create a partial.
HAML
examples:
form view:
= form_tag("path/to/action", method: "POST") do
= render "path/to/partial/field", type: "string", required: true, item: "first_name"
field
partial:
- required_string = required ? "required" : ""
%div{class: "input #{type} #{required_string} #{item}"}
%label{class: "#{type} #{required_string}", for: "#{item}"}
- if required
%abbr{title: "required"}
*
= t("application.#{item}")
%input{name: "#{item}", |
placeholder: t("application.#{item}"), |
type: "#{type}", |
required: required, |
"aria-required" => "#{required}" }

- 4,770
- 2
- 18
- 15
In the case that you want to add a field that is not part of your model in your form, so that you don't want to read attributes, simple_form
propose to use what they call a fake input in their wiki.
String Input
app/inputs/fake_input.rb
:
class FakeInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
template.text_field_tag(attribute_name, nil, merged_input_options)
end
end
Then you can do <%= f.input :thing, as: :fake %>
Boolean Input
app/inputs/fake_checkbox_input.rb
:
class FakeCheckboxInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
tag_name = "#{@builder.object_name}[#{attribute_name}]"
template.check_box_tag(tag_name, options['value'] || 1, options['checked'], merged_input_options)
end
end
Then you can do <%= form.input :remove_avatar, as: :fake_checkbox, wrapper: :vertical_boolean %>
Select
app/inputs/fake_select_input.rb
:
class FakeSelectInput < SimpleForm::Inputs::CollectionSelectInput
def input(wrapper_options = nil)
label_method, value_method = detect_collection_methods
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options).merge(input_options.slice(:multiple, :include_blank, :disabled, :prompt))
template.select_tag(
attribute_name,
template.options_from_collection_for_select(collection, value_method, label_method, selected: input_options[:selected], disabled: input_options[:disabled]),
merged_input_options
)
end
end
Then you can do <%= f.input :thing, as: :fake_select, collection: my_collection, selected: params[:thing] %>

- 428
- 4
- 10