Rails: form_for with field for Hash - ruby-on-rails

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.

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 %>

Display Errors For Nested Form

I have a nested form in my view;
<%= simple_form_for #form, url: url do |f| %>
<%= f.input :name %>
<%= f.input :description, as: :text %>
<%= f.fields_for :account, { :class => 'field' } do |ff| %>
<%= ff.collection_radio_buttons(:account_type_id, AccountType.all, :id, :name, selected: ff.object.account_type_id) { |b| radio_button_builder(b) } %>
<% end %>
Here is my Form object (extending Reform);
class ProgrammeForm < ApplicationForm
properties :name, :description, validates: {presence: true}
property :account do
property :account_type_id
validates :account_type_id, presence: true
end
end
If I submit the form without filling in any fields, then my <% if #form.errors.any? %> partial will print out three errors;
3 Errors prohibited this from being saved:
Name can't be blank
Description can't be blank
Account account type can't be blank
But there is no "error-looking" HTML on my nested form (the account_type stuff). Name and description are fine (as those are fairly straight forward). But;
fields_for doesn't put a div wrapper around the radio buttons collection to begin with.
There is no other indication that there was an error on this field (like with name and description).
How can I address these two points?

Given a Model enum, how to create a radio button group

I have a model like:
class User < ActiveRecord::Base
enum :status [:banned, :registered, :trial, :pending]
end
On my edit page, I want to show a list of 4 radio buttons and pre-select the radio button that is currently set for a user.
How can I do this?
<%= form_for #user do |f| %>
<%= f.collection_radio_buttons :status, User.statuses, :first, :first %>
<%= f.submit %>
<% end %>
Ref
Rails creates a class method using the pluralized attribute name when you use enum. The method returns a key value pair of strings you've defined and what integers they map to. So, you could do something like this:
<% User.status.keys.each do |status| %>
<%= f.radio_button :status, status %>
<%= f.label status.to_sym %>
<% end %>

In Rails with Globalize, update seems to ignore empty string fields

I am very new to Rails and I am facing a somehow weird problem, and my googling didn't helped me so far...
I have implemented a classical CRUD ressource following the Getting Started with Rails guide and I am blocking on the "update" part:
http://guides.rubyonrails.org/getting_started.html#updating-articles
This is part of my model "Devwork":
class Devwork < ActiveRecord::Base
validates :short_title, presence: true, uniqueness: true
validates :title_fr, presence: true, allow_blank: false
translates :title, :summary, :description
globalize_accessors
end
I am using the Globalize gem to persist localized data, and Globalize-accessor for the helpers.
Here is the controller's update action:
class DevworksController < ApplicationController
def update
#devwork = Devwork.find(params[:id])
if #devwork.update(devwork_params)
redirect_to #devwork
else
render :edit
end
end
private
def devwork_params
params.require(:devwork)
.permit!
end
end
And part of the form:
<%= form_for #devwork do |f| %>
<p>
<%= f.label :short_title %>
<%= f.text_field :short_title %>
</p>
<p>
<%= f.label :title_fr %>
<%= f.text_field :title_fr %>
<%= f.label :title_en %>
<%= f.text_field :title_en %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
short_title and title_fr are mandatory, while there exist another field title_en which is not. I want the update form to be shown again if the update fails (typically because of empty title_fr).
But it doesn't work. The update never fails (never entering render :edit) even if title_fr is empty. In fact, the update does nothing if one of the field is empty, it only updates non-empty fields.
I surely missed something somewhere, but I can't figure it out... perhaps a missuses of Globalize ?
Thanks for your help !

Rails Simpleform with non-model inputs

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 %>

Resources