Rails Form form_for Objects Reverse Order of Array

This is pretty simple, but I couldn’t figure out how to do it.  Basically I had a view that went through each object in the nested table array, and rendered it.  However, instead of rendering them all in the order they were created from top to bottom on the page, I wanted to render them in reverse order, so the most recent one was at the top of the page.  There might be several ways of doing this, but here is how I finally did it, and its pretty simple. (probably shouldn’t have taken me this long to figure it out, but hopefully you can read this and save some time!)

Here is the original code in the view:

  
<%= simple_form_for(@lot) do |f| %>
  <strong>Lot Number:</strong> <%= @lot.number %>
  <strong>Item</strong> <%= Item.find(@lot.item_id).number_rev_name %>
  <strong>Inventory Quantity:</strong> <%= @lot.inventory_qty %>

  <-- Here is where I render a partial for each build_lot, which is a 
         has_many, :through join_table -->
  <%= f.simple_fields_for :build_lots,  do |build_lot| %>
    <%= render 'build_lot_fields', :f => build_lot %>
  <% end %>
  <%= f.button :submit, class: 'btn btn-primary' %>
<% end %>

And here is the code from the partial for each build_lot, _build_lot_fields.html.erb

<div class='nested-fields build-lot-fields'>
  <div class='well'>
    <%= f.input :my_build_id, collection: MyBuild.order(:start_date), label_method: :description, value_method: :id, :prompt => 'Choose a Build', selected: MyBuild.where(current: true), input_html: { id: 'build_select'} %>
    <%= f.input :pull_quantity, label: 'Pull Quantity', as: :string %>
    <%= f.label 'Date' %><%= Date.today %><br>
    <%= f.input :employee_id, collection: Employee.order(:first_name), label_method: :first_name, value_method: :id, prompt: "Choose your name" %>
  </div>
</div>

So this simple trick to reverse the order of the build_lots array that is iterated through to render each partial, is to simply add another parameter to the fields_for call (in this case simple_fields_for from the simple_form gem). This second parameter that we add will be the build_lots array reversed. You can find more about the usage of the fields_for method on its documentation page.

But first we need to create this reversed array in the controller. So in the controller (in the function for the view where I want to show the reversed build_lots) I added this line:

@reverseBuildLots = @lot.build_lots.reverse

Then back in the view, I simply change the form_for line like this:

<%= f.simple_fields_for :build_lots, @reverseBuildLots do |build_lot| %>

passing in the @reverseBuildLots parameter, which is an array of build_lots in reverse order that we created in the controller.

Pretty simple, but took me a while to figure out. Hopefully this will save you some time!

credit here

Advertisements

Custom id for input using simple form in Rails

Simple_form  provides a lot of handy html tags for forms. However, the autocreation of classes and id’s was giving me trouble because I couldn’t figure out how to give an element the id I wanted. It’s actually very simple.

input_html: { id: 'my_id'}

is used to give an id to the specific element. This can be a bit tricky when using collection_select, as it takes a bunch of inputs. I typically put the input_html: {} as the last input.

<%= f.input :item_id, collection: Supplier.order(:name), as: :grouped_select, group_method: :items, group_label_method: :name, label_method: :name, value_method: :id, :prompt => 'Choose an existing Item', input_html: { id: 'quantity_item_select'} %>

Check the documentation for collection_select and grouped_collection_select to be sure you put the inputs in the correct order.

You can also use wrapper_html to input custom html for the wrapper div’s that simple_form creates.

wrapper_html: { id: 'my_id'}

I hope this is useful for you, as even though its simple, it took me a while of searching to find it.

Form Horizontal with Bootstrap 3 and Simple Form 2 on Rails 4

I don’t know why this was so difficult, but I had lots of trouble getting the `form-horizontal` class to work in my rails app was quite a chore when I upgraded to bootstrap 3.  After lots of searching and hours of agony, this finally worked for me.  Credit goes to this blog post.

After you have bootstrap 3 (I use the bootstrap-sass gem) and simple_form 2, run the simple_form generator:

rails generate simple_form:install --bootstrap

So the way I understand it, this hack basically overrides the div classes in simple_form to match them up with bootstrap. So first edit the config/initializers/simple_form.rb

config.label_class = 'col-lg-2 control-label'
config.form_class = "simple_form form-horizontal"

In the config/initializers/simple_form_bootstrap.rb replace the classes “control-group” with “form-group” and replace “control” with “col-lg-10”

Now create a new initializer file, for example config/initializers/remove-this-sf_bs3_inputs.rb

inputs = %w[
CollectionSelectInput
DateTimeInput
FileInput
GroupedCollectionSelectInput
NumericInput
PasswordInput
RangeInput
StringInput
TextInput
]

inputs.each do |input_type|
superclass = “SimpleForm::Inputs::#{input_type}”.constantize

new_class = Class.new(superclass) do
def input_html_classes
super.push(‘form-control’)
end
end

Object.const_set(input_type, new_class)
end

Hopefully there will be some official support in the near future that won’t require this workaround. Let me know if you know of an easier way to get form-horizontal to work.

Here’s the Stack Overflow question that I asked regarding this problem.