Rails Simpleform with non-model inputs - ruby-on-rails

I have a normal form using simpleform. Now I'd like to add an input that does not have any corresponding field in the model, it will be processed by the controller. I tried
<%= simple_form_for #obj do |f| %>
<%= f.input :name %>
<%= f.input :attr, as: :string %> <-- should just send "attr" as post data
<% end %>
but this gives a Method not found: attr_not_in_obj error. I could obviously use the standard rails helpers, but then I will miss all of the simpleform HTML around the input, and copying doesn't quite seem right.
In short:
I'm looking for something like simpleform version of rails tag helpers, without any connection to a model. How do I add inputs that do not correspond to model attributes?

Why don't you add:
attr_accessor :attr
to your model's class definition? This way your code:
<%= f.input :attr %>
should work.
OR
If this solution isn't suitable, you can always pass some value to your input method directly:
<%= f.input :attr, input_html: {value: 'something'} %>

Say you wanted to use a rails form helper but still wrap it in SimpleForm goodness? You can, by calling input with a block like so:
<%= simple_form_for #obj do |f| %>
<%= f.input :name %>
<%= f.input :attr do %>
<%= text_field_tag 'attr' %>
<% end %>
<% end %>

Yes, below are quote from simple_form 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 %>

Related

Can one simple_form create instances of multiple models?

I got simple_form for testrun model with multiple checkboxes, that save an array of testcases in a model field
app/views/testruns/_form.html.erb
<%= simple_form_for #testrun do |f| %>
<%= f.input :testcase, as: :check_boxes,
collection: [["testcase1", :testcase1], ["testcase2", :testcase2], ... ]%>
<%= f.submit %>
<% end %>
It works fine, but from now I need to create another model called testcase. After submitting form, besides creating a new testrun instance, I need to create testcase instances which depends on every flag checked.
Any idea how can I do it?
You need to use accepts_nested_attributes_for and simple_fields_for. Assuming you have has_many :testcases in Testrun and the field name of Testcase is name, the below steps should put you in the right direction.
#app/models/testrun.rb
accepts_nested_attributes_for :testcases
#app/controllers/testrun_controller.rb
def new
#testrun = Testrun.new
#testrun.testcases.build
end
private
def testrun_params
params.require(:testrun).permit(:field1, :field2.., testcases_attrubtes: [name: []])
end
#app/views/testruns/_form.html.erb
<%= simple_form_for #testrun do |f| %>
<%= f.simple_fields_for :testcases do |testcase| %>
<%= testcase.input :name, as: :check_boxes,
collection: [["testcase1", :testcase1], ["testcase2", :testcase2], ... ]%>
<% end %>
<%= f.submit %>
<% end %>

Get data attribute value from the Rails form builder without using input field

I have what I hope to be a simple question. I need to display the value for an attribute on the Edit page, while keeping the input field for the same attribute. How might this be accomplished?
Well generally you can just use the original object, like you'll have an #foo that you'll have used in your form_for statement, so you can just use that directly: = #foo.the_attribute
If you're within a partial, or elsewhere where you have only the form builder instance, then you can refer to the underlying object with the .object method, eg.:
= form_for #foo do |f|
# in here, f.object == #foo
In my case, I'm working with accepts_nested_attributes_for in two models. Event accept nested objects from Speaker. And Speaker has a perfil_id attribute which could be ['Maker', 'Developer', 'Entrepreneur', ...].
The Speaker's form is a partial rendered from the principal form, Event's form:
<%= form_for(event) do |f| %>
<%= f.text_field :title %>
<%= f.label :title, 'Event name' %>
<%= f.fields_for :speakers do |builder| %>
<%= render 'events/partials/speaker_fields', f: builder %>
<% end %>
<%= f.submit %>
<% end %>
Partial
<%= builder.number_field :name %>
<%= builder.label :name %>
<% options = options_from_collection_for_select(#profiles, 'id', 'name', f.object.member_profile_id ) %>
<%= select_tag "event[speakers_attributes][profile_id]", options, prompt: 'Select a Profile' %>
When editing Event's Speakers I wanted a select_tag to select the profile name for the actual Speaker.
I could not use an input field for this. So I need to get the correct values from the builder object and I get what I need by doing this:
f.object.profile_id
Passing it as a fourth param to the select options I get this working:
<% options = options_from_collection_for_select(#profiles, 'id', 'name', f.object.profile_id ) %>
I hope it could be useful for you too!

Rails how to get query string from get action in post action?

I have a url like this http://example.com/myController?key=12345
In my controller myController, i can access the key value with params[:key], but when i submit a form, i want to get that same key in the create method, but the params[:key] is null.
How can i access params[:key] in my post action create?
You might indeed add a hidden field.
If you find yourself adding many of those because you need to have the value available in more and more actions, consider setting it within the session as (e.g.) session[:current_key]
You can pass the info along by a hidden_field_tag. So your code would be like:
<%= form_for #model do |f| %>
<%= hidden_field_tag 'key', params[:key]
# other form code
<%= f.submit %>
<% end %>
You can add a hidden field to your form and set its value to params[:key]. Then it will be available in the params you get from the form.
If you're using Simple Form:
<%= simple_form_for #model do |f| %>
...
<%= f.input :field_name, :as => :hidden, :input_html => { :value => params[:key] } %>
<%= f.button :submit %>
<% end %>
Add a new hidden field to pass via params, when you submit the form your action is changed or called again params hash is recreated; what you can do is pass the value via hidden field in the form as follow,
<%= simple_form_for #model do |f| %>
# your remaining form fields
<%= f.input :field_name, as: :hidden, :input_html: { value: params[:key] } %>
<%= f.button :submit %>
<% end %>

Rails: form_for with field for Hash

i've got model with:
class Product < ActiveRecord::Base
attr_accessible :category, :description, :img_url, :name, :price, :quantity, :tags
serialize :tags, Hash
end
and try to make form for it
<%= form_for #product do |f| %>
<%= f.label :"tags[:condition]_new", "new" %>
<%= f.radio_button :"tags[:condition]", "New", checked: true %>
<%= f.radio_button :"tags[:condition]", "Used" %>
<% end %>
unfortunately it rails raise
undefined method `tags[:condition]' for #Product:0x007fd26d965810>
<%= f.radio_button :"tags[:condition]", "Used" %> <-- ONLY FOR 2ND LINE. first is okey. WHY?!
and I can't figure out why its trying to put method on it. Has anyone idea how to make proper field for hash value?
+ Why it fails only on 2nd f.radio_button and i passes first one?
This is because you are not setting any value for 2nd radio button, try this and it will work fine.
<%= f.radio_button :"tags[:condition]", "Used", checked: false %>
As if you will not pass any value, then FormHelper class will call 'name[:condition]' method on #product to get its corresponding value, though there is no method defined in the model it raises exception.

virtual model and form_for (or formtastic)

Sometimes we need form without model creation - for example search field or email, where should be send some instructions. What is the best way to create this forms? Can i create virtual model or something like this? I'd like to use formtastic, but not form_tag.
Firstly, Formtastic doesn't need a model in all cases, although it certainly works best and requires less code with a model.
Just like Rails' own built-in form_for, you can pass in a symbol instead of an object as the first argument, and Formtastic will build the form and post the params based on the symbol. Eg:
<% semantic_form_for(:session) do |f| %>
...
<% end %>
This will make the form values available to your controller as params[:session].
Secondly, a model doesn't mean an ActiveRecord model. What I mean is, Formtastic will work with any instance of a class that quacks like an ActiveRecord model.
A classic example of this that many people are using Authlogic for authentication with Formtastic. Part of Authlogic is the idea of a UserSession model, which works fine:
Controller:
def index
#user_session = UserSession.new
end
Form:
<% semantic_form_for(#user_session) do |f| %>
<%= f.input :login %>
<%= f.input :password %>
<% end %>
This will make your form data available in your controller as params[:user_session].
It's really not that hard to create a model instance to wrap up the concerns of your model. Just keep implementing the methods Formtastic is expecting until you get it working!
default_language.rb
class DefaultLanguage
attr_accessor :language_id
end
foo_controller.rb
def index
#default_language = params[:default_language] || Language.find_by_name("English")
end
index.erb
<% semantic_form_for #default_language do |form| %>
<% form.inputs :id => 'default_language' do %>
<%= form.input :id,
:as => :select,
:collection => #languages,
:required => false,
:label => "Primary Language:",
:include_blank => false %>
<% end %>
<% end %>
I used AJAX to post the form when the value changed.
Or you simply create a form with form_for and leave the model reference blank.
for example
<% form_for "", :url=>some_url do |f| %>
<%= f.text_field "some_attribute" %>
<%= submit_tag "submit" %>
You can fetch the values by simply saying params[:some_attribute] in your controller.

Resources