Rails nested_form gem updates wrong parent data - ruby-on-rails

I have the following in one of my forms. With this code I can dynamically add divisions, sub_divisions and sub_sub_divisions on the page. The problem is the sub_sub_divisions I add are saved to the first sub_division even though they are correctly displayed on other sub_divisions on the view. I don't know what is happening between the view and what is passed to controller to make this error. Thanks a lot.
<%= nested_form_for #division do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<table>
<tr>
<td>
<%= f.label t("name") %>
<%= f.text_field :name, class: 'form-control' %>
</td>
<td>
<%= f.label t("description") %>
<%= f.text_field :description, class: 'form-control' %>
</td>
</tr>
<tr><td><h3><%=t :sub_divisions %></h3></td></tr>
<tr>
<td colspan=4>
<table id="sub_divs" class="table table-condensed table-striped">
<tr><th><%=t :name %></th><th><%=t :description %></th></tr>
<%= f.fields_for :sub_divs, :wrapper => false do |sub_div| %>
<tr class="fields">
<td><%= sub_div.text_field :name, class: 'form-control' %></td>
<td><%= sub_div.text_field :description, class: 'form-control' %></td>
<td><%= sub_div.link_to_remove t("delete") %></td>
</tr>
<td colspan=3>
<table id="<%= 'sub_sub_divs' + sub_div.index.to_s %>">
<tr><th><%=t :name %></th><th><%=t :description %></th></tr>
<%= sub_div.fields_for :sub_sub_divs,
:wrapper => false do |sub_sub_div| %>
<tr class="fields">
<td><%= sub_sub_div.text_field :name,
class: 'form-control' %></td>
<td><%= sub_sub_div.text_field :description, class:
'form-control' %></td>
<td><%= sub_sub_div.link_to_remove t("delete") %></td>
<td><%= sub_sub_div.hidden_field :id,
value: sub_sub_div.object.sub_div_id %></td>
</tr>
<% end %>
</table>
</td>
</tr>
<tr>
<td colspan=3 class="pull-right">
<%= sub_div.link_to_add t("add") +
t("sub") + t('sub') + t('div'), :sub_sub_divs,
:data => { :target => "#"+"sub_sub_divs" +
#{sub_div.index.to_s}", id: sub_div.object.id} %>
</td>
</tr>
<% end %>
</table>
</td>
</tr>
<tr><td colspan=2 class="pull-right">
<%= f.link_to_add t("add") + t("sub") + t('div'),
:sub_divs, :data => { :target => "#sub_divs"} %></td></tr>
<tr><td><%= f.submit t("update"), class: "btn btn-primary" %></td></tr>
</table>
<% end %>

Outside of your call to
<%= f.fields_for :sub_divs, :wrapper => false do |sub_div| %>
You should iterate over the sub_divs:
<%= #division.sub_divs.each do |sub_div| %>
And then pass each one to the fields_for call as the 2nd parameter:
<%= f.fields_for :sub_divs, sub_div, :wrapper => false do |sub_div| %>
Do the same for the next nested sub_sub_div and finally:
<%= sub_sub_div.hidden_field :id,
value: sub_sub_div.object.sub_div_id %>
...will have the correct sub_div_id

Related

How to filter status with Rails Ransack's filter?

I found a description in the Ranksack tutorial (https://activerecord-hackery.github.io/ransack/getting-started/sorting) about filters. I have used Ransack to complete the search and sorting functions. I hope to add a filter to let the user select the desired state (this is one of the columns in the table) and point out the data that matches the state. But I don't know how to transform this code. Please give me some hints, thanks.
This is the code mentioned in the tutorial
<div class="filters" id="filtersSidebar">
<header class="filters-header">
<div class="filters-header-content">
<h3>Filters</h3>
</div>
</header>
<div class="filters-content">
<%= search_form_for #q,
class: 'form',
url: articles_path,
html: { autocomplete: 'off', autocapitalize: 'none' } do |f| %>
<div class="form-group">
<%= f.label :title_cont, t('Filter_by_keyword') %>
<%= f.search_field :title_cont %>
</div>
<%= render partial: 'filters/date_title_sort', locals: { f: f } %>
<div class="form-group">
<%= f.label :grade_level_gteq, t('Grade_level') %> >=
<%= f.search_field :grade_level_gteq %>
</div>
<div class="form-group">
<%= f.label :readability_gteq, t('Readability') %> >=
<%= f.search_field :readability_gteq %>
</div>
<div class="form-group">
<i><%= #articles.total_count %> articles</i>
</div>
<div class="form-group">
<hr/>
<div class="filters-header-content">
<%= link_to request.path, class: 'form-link' do %>
<i class="far fa-undo icon-l"></i><%= t('Clear_all') %>
<% end %>
<%= f.submit t('Filter'), class: 'btn btn-primary' %>
</div>
</div>
<% end %>
</div>
</div>
This is the current code of my page
<%= search_form_for(#query, url: list_tasks_path) do |f| %>
<%= f.label :name, t('search') %>
<%= f.search_field :name_or_note_cont, placeholder: t('task_name') %>
<%= f.select :status_eq, Task.statuses.map { |key, value| [t("checkpoint_status.#{key}"), value] }, prompt: t('all_status') %>
<%= f.submit %>
<% end %>
<p class="lead"><%= t('task_list') %></p>
<table class="table table-striped table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">
<%= sort_link(#query, :name) do %>
<%= t('task_name') %>
<% end %>
</th>
<th scope="col">
<%= sort_link(#query, :status) do %>
<%= t('task_status') %>
<% end %>
</th>
<th scope="col">
<%= sort_link(#query, :priority) do %>
<%= t('task_priority') %>
<% end %>
</th>
<th scope="col">
<%= sort_link(#query, :created_at) do %>
<%= t('task_created') %>
<% end %>
</th>
<th scope="col">
<%= sort_link(#query, :due_date) do %>
<%= t('task_ends') %>
<% end %>
</th>
<th scope="col"><%= t('task_actions') %></th>
<th colspan="2"></th>
<th scope="col"><%= t('task_tag') %></th>
</tr>
</thead>
<tbody>
<% #tasks.each do |task| %>
<tr>
<th scope="row"><%= task.id %></th>
<td>
<%= task.name %>
</td>
<td>
<%= t("checkpoint_status.#{task.status}") %>
</td>
<td>
<%= t("checkpoint_priority.#{task.priority}") %>
</td>
<td>
<%= task.created_at.strftime("%b %d %R") %>
</td>
<td>
<%= task.due_date.strftime("%b %d %R") %>
</td>
<td>
<%= link_to t('task_cont') , task_path(task) %>
</td>
<td>
<%= link_to t('task_do_edit') , edit_task_path(task) %>
</td>
<td>
<%= link_to t('task_do_kill') , task_path(task), method: :delete, data:{ confirm: t('task_do_sure') } %>
</td>
<td>
<%= task.tag_list %>
</td>
</tr>
<% end %>
</tbody>
</table>

Trix - undefined method `to_key'

I have a CategoryForm obejct for which I render a form and I installed Trix editor (gem 'trix') to let my users format the text. After installing Trix I am getting undefined method 'to_key'. Here's my current setup.
app/assets/javascripts/admins/categories/categories.js
//= require trix
app/assets/stylesheets/admins/categories/categories.css
*= require trix
CategoryForm
class CategoryForm
attr_accessor :short_desc_pl, :short_desc_en, :short_desc_de,
:long_desc_pl, :long_desc_en, :long_desc_de,
:resource
def initialize(params = {})
#resource = Category.find(params[:id])
generate_fields
end
private
def generate_fields
#short_desc_pl = #resource.short_description['pl']
#short_desc_en = #resource.short_description['en']
#short_desc_de = #resource.short_description['de']
#long_desc_pl = #resource.long_description['pl']
#long_desc_en = #resource.long_description['en']
#long_desc_de = #resource.long_description['de']
end
end
Form
<%= form_for category_form, as: 'category', url: admins_category_path(category_form.resource), method: :patch do |form| %>
<table class="table">
<col>
<colgroup span="2"></colgroup>
<colgroup span="2"></colgroup>
<tr>
<td rowspan="2"></td>
</tr>
<tr>
<th scope="col">PL</th>
<th scope="col">EN</th>
<th scope="col">DE</th>
</tr>
<tr>
<th scope="row">Krótki opis</th>
<td><%= form.text_field :short_desc_pl, class: 'form-control' %></td>
<td><%= form.text_field :short_desc_en, class: 'form-control', required: true %></td>
<td><%= form.text_field :short_desc_de, class: 'form-control', required: true %></td>
</tr>
<tr>
<th scope="row">Długi opis</th>
<td><%= form.trix_editor :long_desc_pl, size: "20x20", class: 'form-control', required: true %></td>
<td><%= form.text_area :long_desc_en, size: "20x20", class: 'form-control', required: true %></td>
<td><%= form.text_area :long_desc_de, size: "20x20", class: 'form-control', required: true %></td>
</tr>
</table>
<div class="actions">
<%= form.submit 'Zapisz' %>
</div>
<% end %>
What am I doing wrong?
UPDATE
I even changed my form to use #category
<%= form_for category, as: 'category', url: admins_category_path(category), method: :patch do |form| %>
...
and I am not getting any error but the editor simply does not render. I am using Webpacker, Rails 5.1.

How can I access to nested fields attributes using nested_forms gem

I am using nested_forms gem in my project, nested_forms uses a partial view to render the line with my nested object attributes, here is my partial view code:
<tr class="fields">
<td>
<%= f.text_field :nombre, class: 'form-control craf' %>
</td>
<td>
<%
concat f.select :idtipodocumento, CrTipoDocumento.all.collect {|p| [ p.nombre, p.id ] }, {prompt: 'Seleccione el tipo de documento'}, :class=>'form-control'
%>
</td>
<td>
<%= f.text_field :documento, class: 'form-control', maxlength: '50' %>
</td>
<% if current_user.email.include? '#cifco.gob.sv' %>
<td>
<%= f.check_box :activo %>
</td>
<td>
<%= f.check_box :impresa %>
</td>
<td>
<%= f.check_box :extra %>
</td>
<% end %>
<td>
<%= f.link_to_remove raw('<i class="fa fa-minus-circle" aria-hidden="true"></i>'), :class =>'btn btn-danger hidden-print' %>
</td>
And here is the code block of the view where this partial is rendering:
<tbody>
<fieldset id="acreditados">
<%= f.fields_for :cr_acreditados, :wrapper => false %>
</fieldset>
</tbody>
So, what I want to do is evaluate if 'impresa' == false and only then render it, but if try f.impresa it says the method 'impresa' doesnt exist for f
Here is the form full code:
<%= nested_form_for(#cr_acreditacion_cliente, :validate => true) do |f| %>
<% if #cr_acreditacion_cliente.acreditaciones == nil %>
<% else %>
<table class="table table-striped table-bordered table-hover" id="AC">
<thead>
<tr>
<th>Evento</th>
<th>Cliente</th>
<th>Stand</th>
<th>Acreditaciones</th>
<th>Acreditaciones Disponibles</th>
<th>Tipo de Acreditacion</th>
</tr>
</thead>
<tbody>
<td><%= #cr_acreditacion_cliente.cr_evento.nombre %></td>
<td><%= #cr_acreditacion_cliente.cr_cliente.nombre %></td>
<td><%= #cr_acreditacion_cliente.cr_stand.codigo %></td>
<td><%= #cr_acreditacion_cliente.acreditaciones %></td>
<td>
<p hidden id="cnt"><%= #cr_acreditacion_cliente.acreditaciones %></p>
<p id="acd">
<%= #counter = #cr_acreditacion_cliente.acreditaciones - #cr_acreditacion_cliente.cr_acreditados.count %>
</p>
</td>
<td><%= #cr_acreditacion_cliente.cr_tipocre.tipo %></td>
</tbody>
</table>
<table class="table table-striped table-bordered table-hover" id="DAC">
<thead>
<tr>
<th>Nombre</th>
<th>Tipo de Documento</th>
<th>Documento</th>
<% if current_user.email.include? '#cifco.gob.sv' %>
<th>Activo</th>
<th>Impresa</th>
<th>Extra</th>
<% end %>
<th class="hidden-print">Acciones</th>
</tr>
</thead>
<tbody>
<fieldset id="acreditados">
<%= f.fields_for :cr_acreditados, :wrapper => false %>
</fieldset>
</tbody>
</table>
<div id="addBtn">
<% if #counter >= 1 %>
<p><%= f.link_to_add raw('<i class="fa fa-plus-circle" aria-hidden="true"></i>'), :cr_acreditados, id: 'btna', :class => 'btn btn-primary lta hidden-print', "data-target" => "#DAC" %></p>
<% else %>
<p class="text-center"><h3>No dispone de mas acreditaciones</h3></p>
<% end %>
</div>
<div class="actions text-center">
<%= f.submit "Guardar Credenciales", :class => 'btn btn-success hidden-print', data: { confirm: 'Favor verifique los datos antes de almacenarlos' }%>
</div>
<% end %>
<% end %>

Form_tag do not add check_box_tag value into parameters

I have Pieces model, which is store item's parts. When I need, I'm asking to users, check pieces is ok or nok with generated forms.
I am creating reports model to store the forms which I asked from users.
So, when I generate the forms check_box and and text_field works fine. But when I submit the form, I can't get check_box values as a parameter.
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"5OmdXCDixwxru2yBtB3YmT3YF/ZqOByoAJ3J29TyJikxJdA+RXAvGjwu8MBIPlJCROFx4V7AUcA7IIqIgthD9g==",
"notes"=>{"79"=>"asdasda","84"=>""},
"commit"=>"Submit",
"id"=>"5"}
here is my edit.html.erb
<%- model_class = Report -%>
<div class="page-header">
<h1><%=t '.title', :default => [:'helpers.titles.edit', 'Edit %{model}'], :model => model_class.model_name.human.titleize %></h1>
</div>
<% if #report.errors.any? %>
<div id="error_expl" class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title"><%= pluralize(#report.errors.count, "error") %> prohibited this report from being saved:</h3>
</div>
<div class="panel-body">
<ul>
<% #report.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
<table class="table table-striped">
<thead>
<tr>
<th><%= model_class.human_attribute_name(:status) %></th>
<th><%= model_class.human_attribute_name(:serial_no) %></th>
<th><%= model_class.human_attribute_name(:category) %></th>
<th><%= model_class.human_attribute_name(:name) %></th>
<th><%= model_class.human_attribute_name(:brand) %></th>
<th><%= model_class.human_attribute_name(:model) %></th>
<th><%= model_class.human_attribute_name(:quantity) %></th>
</tr>
</thead>
<tbody>
<%= form_tag(report_path(#report), :method => :patch) do %>
<% #pieces.each do |piece| %>
<tr>
<td><div class="form-group">
<%= check_box_tag(:status, name: "status["+piece.id.to_s+"]", class: 'form-control') %>
</div></td>
<td><%= piece.try(:serial_no) %></td>
<td><%= piece.item.category.name %></td>
<td><%= piece.item.name %></td>
<td><%= piece.item.brand %></td>
<td><%= piece.item.model %></td>
<% if piece.serial_no.start_with?("D") %>
<td><%= piece.item.pieces.count %> <%= piece.item.unit.name %></td>
<% else %>
<td><%= piece.item.pieces.sum(:quantity) %> <%= piece.item.unit.name %></td>
<% end %>
</tr>
<tr>
<td colspan=7 class="hidden" id="hebele">
<%= text_field_tag(:note,"", placeholder: "Note ", name: "notes["+piece.id.to_s+"]",class: "form-control ") %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<%= submit_tag("Submit",:class => 'btn btn-primary') %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")), reports_path, :class => 'btn btn-default' %>
</div>
</div>
<% end %>
<script type="text/javascript">
$("[id='status']").bootstrapSwitch({
size: 'mini',
onColor: 'success',
offColor: 'danger',
indeterminate: true,
onSwitchChange: function(event, state) {
if (state == false){
$("#hebele").removeClass('hidden');
}else if(state == true){
$("#hebele").addClass('hidden');
}
}
});
</script>
controller:
def edit
#pieces = #report.pieces.joins(:item).group(:item_id)
#report = Report.find(params[:id])
end
You need to define the value of the check_box_tag:
<%= check_box_tag :status, piece.id, class: 'form-control' %>
If you're editing a #report, you'll be best using form_for:
<table>
<tbody>
<%= form_for #report do |f| %>
<% #pieces.each do |piece| %>
<tr>
<td>
<div class="form-group">
<%= f.check_box :status, class: 'form-control', price.id %>
</div>
</td>
<td><%= piece.try(:serial_no) %></td>
<td><%= piece.item.category.name %></td>
<td><%= piece.item.name %></td>
<td><%= piece.item.brand %></td>
<td><%= piece.item.model %></td>
<% if piece.serial_no.start_with?("D") %>
<td><%= piece.item.pieces.count %> <%= piece.item.unit.name %></td>
<% else %>
<td><%= piece.item.pieces.sum(:quantity) %> <%= piece.item.unit.name %></td>
<% end %>
</tr>
<tr>
<td colspan=7 class="hidden" id="hebele">
<%= f.text_field :note, placeholder: "Note", class: "form-control" %>
</td>
</tr>
<% end %>
<tr><td colspan="7"><%= f.submit, class: "btn btn-primary" %></td></tr>
<% end %>
</tbody>
</table>

How to change values which get from check box into SQL condition?

I use check_box_tag to get selected beacon, and i to use collection_select to define a value. when user press the button, I want to all selected beacons change value into what collection_select choose, but I don't know how to use ids[] to set my condition like "where...in ..."
here is my action, I want params[:ids] change in to just like [1,2,3]
#beacons = Beacon.where(:id => params[:ids]).update_all(:installer_id => params[:account][:installer_id])
here is my table:
<table class="col-md-12 table-bordered table-striped table-condensed cf">
<thead class="cf">
<th>Check</th>
<th>BeaconUUID</th>
<th>BeaconCategory</th>
<th>BeaconLocate</th>
<th>BeaconName</th>
<th>BeaconAddress</th>
<th>Assign</th>
</thead>
<tbody>
<% #beacons.each do |beacon| %>
<tr>
<td><%= check_box_tag "ids[]", beacon.id %></td>
<td><%= beacon.beacon_uuid %></td>
<td><%= beacon.cid %></td>
<td><%= beacon.lid %></td>
<td><%= beacon.beacon_name %></td>
<td><%= beacon.beacon_address %></td>
<% if beacon.installer_id.nil? %>
<td>not assign</td>
<% else %>
<td>assigned:<%= beacon.installer_id %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= form_tag assigned_beacons_path, :method => 'post' do %>
<td><%= collection_select(:account, :installer_id, Account.where('manager_id = ?',session[:user_id]), :id, :email, {:prompt => 'choose!'}, :style => "width: 100px;") %></td>
<td><p data-placement="top" data-toggle="tooltip" title="Edit"><%= submit_tag 'assign', class: "btn btn-info btn-xs"%></p></td>
<% end %>
As was pointed out in comments, check_box_tag should be moved inside of form_tag block:
<%= form_tag assigned_beacons_path, :method => 'post' do %>
<table class="col-md-12 table-bordered table-striped table-condensed cf">
<thead class="cf">
<th>Check</th>
<th>BeaconUUID</th>
<th>BeaconCategory</th>
<th>BeaconLocate</th>
<th>BeaconName</th>
<th>BeaconAddress</th>
<th>Assign</th>
</thead>
<tbody>
<% #beacons.each do |beacon| %>
<tr>
<td><%= check_box_tag "ids[]", beacon.id %></td>
<td><%= beacon.beacon_uuid %></td>
<td><%= beacon.cid %></td>
<td><%= beacon.lid %></td>
<td><%= beacon.beacon_name %></td>
<td><%= beacon.beacon_address %></td>
<% if beacon.installer_id.nil? %>
<td>not assign</td>
<% else %>
<td>assigned:<%= beacon.installer_id %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<td><%= collection_select(:account, :installer_id, Account.where('manager_id = ?',session[:user_id]), :id, :email, {:prompt => 'choose!'}, :style => "width: 100px;") %></td>
<td><p data-placement="top" data-toggle="tooltip" title="Edit"><%= submit_tag 'assign', class: "btn btn-info btn-xs"%></p></td>
<% end %>
Also, dangling <td> blocks don't look good, you should move them into this or another <table> as well.

Resources