form_for, fields_for and two models - ruby-on-rails

I have form that create two objects and save them to database.
I want to do next things:
save data in database (booth objects)
validate fields (I have validation in model)
and if validation fail, I want to populate fields with entered data
edit action for this form
Problems:
If I use #report I get:
Called id for nil, which would
mistakenly be 4 error
(can't find object). I have in controller, in encreate action #report = ReportMain.new and in action that render that view.
When I use :report_main (model name) it works, it save data to database, but I can't get fields populated when validation fails.
Questions:
What to do with this two models to make this to work (validation, populating fields, edit)?
Can you give me some advice if approach is wrong?
My view looks like this:
<%= form_for(#report, :url => {:action => 'encreate'}) do |f| %>
<%= render "shared/error_messages", :target => #report %>
<%= f.text_field(:amount) %>
<% fields_for #reporte do |r| %>
<%= r.check_box(:q_pripadnost) %>Pripadnost Q listi
<%= select_tag('nacinpakovanja',options_for_select([['Drveno bure', 'Drveno bure'], ['Kanister', 'Kanister'], ['Sanduk', 'Sanduk'], ['Kese', 'Kese'], ['Posude pod pritiskom', 'Posude pod pritiskom'], ['Kompozitno pakovanje', 'Kompozitno pakovanje'], ['Rasuto', 'Rasuto'], ['Ostalo', 'Ostalo']])) %>
<%= r.text_field(:ispitivanjebroj) %>
<%= r.text_field(:datumispitivanja) %>
<% end %>
<input id="datenow" name="datenow" size="30" type="text" value="<%= #date %>">
<div class="form-buttons">
<%= submit_tag("Unesi izvestaj") %>
</div>
<% end %>
encreate actin in ReportController:
def encreate
#report = ReportMain.new
#reporte = ReportE.new
#reportparam = params[:report_main]
#report.waste_id = params[:waste][:code]
#report.warehouse_id = Warehouse.find_by_user_id(current_user.id).id
#report.user_id = current_user.id
#report.company_id = current_user.company_id
#report.amount = #reportparam[:amount]
#report.isimport = false
#report.isfinished = false
#report.reportnumber = ReportMain.where(:company_id => current_user.company_id, :isimport => false).count.to_i+1
if #report.save
#reporte.report_main_id = #report.id
else
redirect_to(:action => 'exportnew')
return
end
#reporte.vrstaotpada = params[:vrstaotpada]
#reporte.nacinpakovanja = params[:nacinpakovanja]
#reporte.ispitivanjebroj = #reportparam[:ispitivanjebroj]
#reporte.datumispitivanja = #reportparam[:datumispitivanja]
#reporte.q_pripadnost = #reportparam[:q_pripadnost]
#reporte.datumpredaje = #date
if #reporte.save
redirect_to(:action => 'show', :id => #reporte.id)
else
redirect_to(:action => 'exportnew')
end
end

I think your problem in this case is that you use redirect_to instead of render. When you use redirect_to then you lose all the variables from your current action. I would probably do something like this in your encreate action:
if #reporte.save
render :show
else
render :exportnew
end
When you use render then it will use the variables from the current action but the view from the action you send to the render method. So when form_for is called with the #report variable, it is already populated with the values that was sent to encreate. Just make sure that you use the same variable names in the different actions but it looks like you do that already.

Related

Rails partial rendering twice on changing the URL

I m new to RoR and i recently figured out that if I change the part of URL from the address bar it is just rendering the partial twice below I m illustrating the same.
So my url is localhost:3000/admin/exp_app/10 so if i refresh this page it gets rendered one time but if i change the url to localhost:3000/admin/exp_app/11 the same request gets twice to controller and it is rendering the partial two times .
Can someone help me?
Below i m attaching the part of code.
exp_controller.rb
def show
authorize! :sales, current_user
#filter = params[:filter] || 'all'
#filter_by = params[:filter_by] || 'all'
#analytics_filter = params[:analytics_filter] || 'all'
#uw = params[:uw_id]
#entity = params[:entity]
#leo_no_brc = params[:leo_no_brc].present?
#exporter_application = User.exp_leads_applications.find(params[:id]) rescue nil
user = User.find(params[:id]) if #exporter_application.nil? || can?(:mexico_sales, current_user)
#total_ltm = #exporter_application.shipment_volume_last_year(nil, false).to_i
#exp_clients = #exporter_application.clients
#exp_applications_clients = #exp_clients.where(status: Client::CLIENT_STATUS_ORDER).group_by(&:status)
#exp_task_instances = #exporter_application.task_instances.where(client_id: nil)
#exporter_application = User.exp_leads_applications.includes(:iec, :contacts,
interactions: [:replies],
task_instances: { interactions: [:replies] },
application: { exporter_user: [:iec] })
end
show.html.erb
<% if params[:_tpl] %>
<div class="admin-section tabpanel row">
<%= render partial: params[:_tpl], locals: { instance: #exporter_application } %>
</div>
<% else %>
<%= render 'admin/header' %>
<%= render partial: 'admin/exporter_applications/show' %>
<%= render 'admin/footer' %>
<% end %>
It is guranteed that this url is not called in partial again admin/exporter_applications/show
Thanks in advance!

Rails update_attribute not found

i need update a single record attribute but i canĀ“t. alumno_id is foreign key of model 'alumno'. the code show the records and if submit 'Aceptar' in one record, need a change the attribute estado to 1
in Model
class Postulacion < ActiveRecord::Base
attr_accessible :ramo, :estado, :alumno_id
belongs_to :alumno
end
in View
<h1>Lista de Postulaciones</h1>
<% #postulaciones.each do |p| %>
<% #id = p.id %>
<%= #id %>
<p>
<td><%= Alumno.find(p.alumno_id).full_name%></td>
<td><%='=> '+ p.ramo %></td>
<td><% if p.estado == 0 %>
<%= 'Pendiente =>' %>
<%= form_tag :action => 'aceptar' do %>
<%= submit_tag 'Aceptar' %></p>
<%end%>
<%else%>
<%='=> Aceptado' %>
<%end%>
</td>
</p>
<% end %>
in controller
class ListadoController < ApplicationController
def listar
#postulaciones = Postulacion.all
respond_to do |format|
format.html
format.json { render json: #postulaciones }
end
end
def aceptar
#postulacion = Postulacion.where(id: #id).first #Edit
#postulacion.estado = 1 #Edit
#postulacion.save #Edit
redirect_to "/"
end
end
Error "undefined method `update_attribute' for []:ActiveRecord::Relation"
Thanks
With this code:
#postulacion = Postulacion.where(alumno_id: #id )
You are declaring #postulacion as a collection, not as a single instance. You can fix this by calling .first:
#postulacion = Postulacion.where(alumno_id: #id ).first
Or by using find_by instead of where:
#postulacion = Postulacion.find_by(alumno_id: #id )
One other thing - this code isn't checking for the possibility that the Postulacion instance might not exist. You should add some logic to handle this...
Your #postulacion variable holds ActiveRecord::Relation instead of single ActiveRecord object. Try:
def acceptar
#postulacion = Postulacion.find_by_alumino_id(#id)
# ...
end
or, if you'd be using Rails 4:
#postulacion = Postulacion.find_by(alumino_id: #id)

Getting data out of a select box and passing it into params

I am doing this for a school project and it is not working. :(
How do I get out the selected[petowner_id] from the view and make it usable in a ruby controller?
How do I make the #selected_pet = params([petowner_id]) in the controller that comes in from the view to function? Currently it renders an error message when I try to set it. :(
I am getting very tired of it not working.
The controller from Pets controller
class PetsController < ApplicationController
# GET /pets
# GET /pets.json
def monsters
#Finds the current user
if current_user
#user = current_user
#pets_kept = [] #why?
##petowner = Petowner.find(params[:petowner][:id])
#if(params[:commit])
#end
#monster = "Eeeep"
#mypets=[]
#all_my_pets = #user.petowners
#options value = 2
#params { selected_petowner[petowner_id]}
#selectpet = params{[selected][petowner_id]}
#petowner = Petowner.find_by_id(params[:id])
#pet = Pet.find_by_id(params[:pet_id])
#Find the petowners that the user currently has
##mypets = #user.petowners
#This is my way of doing things in a C++ fashion, I don't get all ruby things
#user.petowners.each do |pet|
##selected_pet = pet.find(params[:selected])
# if pet.hp != 0
# #pets_kept << pet #Dont recall seeing the << before in ruby but for C++ statement used for cout statements
#if pet.select
# #selected_pet = pet.select
#end
end
##selected_pet = Petowner.find(params[:petowner][:selected])
#end
#selected_pet = 1 ##user.petowners.find(params[:id])
#mypets = current_user.petowners.select{|pet| pet.hp !=0}
#raise "I am here"
##selected_pet = #mypets.find(params[:id][:selected])
##mypets = #pets_kept
end
The code from the view that doesn't go back to the controller variable and set it. :(
<select id="petowner_id" name="selected[petowner_id]">
<%= #all_my_pets.each do |pet| %>
<option value="<%= pet.id %>"><%= pet.pet_name %></option>
<% end %>
</select>
Previous step from pets/monsters view that doesn't work at all from previous collection. :(
<%= form_for :petowner, :url => petowner_fights_path(#selected_pet, #pet) do |f| %>
<p>Select a pet <%#= f.collection_select(:petowner, :petowner_id, #user.petowners, :petowner_id, :pet_name) %></p>
<%= render 'monsterinfo' %>
<div class="outer"></div>
<%= f.submit "Fight Selected Monster" %>
<% end %>
You probably want params[:petowner][:petowner_id]. Definitely don't construct the select with html in a view.
By the way, it's really helpful to see all of the params passed in to a controller action. I tend to raise params.to_yaml when I need to do that.

Rails form params changing in controller

I have a form:
<%= form_for(:report_main, :url => {:action => 'exporttoxiccreate'}) do |f| %>
<%= collection_select(:waste, :code, Waste.find_all_by_istoxic(false), :id, :code, :include_blank => '') %>
<%= f.check_box(:q_pripadnost) %>
<%= f.text_field(:amount) %>
<% end %>
and this code in controller:
def exporttoxiccreate
#report = ReportMain.new
#reportexport = ReportExport.new
#reportparam = params[:report_main]
#report.waste_id = #reportparam.waste.code
#report.amount = #reportparam.amount
if #report.save
#reportexport.report_main_id = #report.id
else
redirect_to(:action => 'exporttoxicnew')
end
#reportexport.q_pripadnost = #reportparam.q_pripadnost
if #reportexport.save
redirect_to(:action => 'show', :id => #reportexport.id)
else
redirect_to(:action => 'exporttoxicnew')
end
end
I want to save in two tables, in two objects data from this form, and I need to separate params to manipulate with. I tried with this:
#reportexport.q_pripadnost = #reportparam.q_pripadnost
I want to set q_pripadnost field in #reportexport with some value from param.
Where I make mistake?
When you get params from a form in Rails, it comes in the form of a hash. For example:
params[:report_main][:waste]
params[:report_main][:amount]
So when you call #reportparam = params[:report_main], you are setting #reportparam to a hash, but then you are trying to use it later like an object. For example, instead of #reportparam.q_pripadnost, use #reportparam[:q_pripadnost].
You can take a closer look at your variable by temporarily changing your action to show a text version of the variable, for example:
def exporttoxiccreate
#reportparam = params[:report_main]
render :text => #reportparam.to_yaml
end

Rails problem display attribute key along with attributes value

I have the following problem. I have a form which takes input for a "Chart" object. But after processing the form, i wish to display one of the values, and it adds the key of this value.
Class model
class Chart
attr_accessor :title, :series
def initialize(title = nil, series = [])
#title, #series = title, series
end
end
View of form:
<% form_for :chart , :url => { :action => "show" } do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>...
<% end %>
Chart controller, show method:
def show
#chart = Chart.new(params[:chart])
end
View of show:
<h2><%=h #chart.title %></h2>
Which displays: "title"input_forms_title""
for example: writing in the input form: Economy, prints in the show view: "titleEconomy"
Any ideas?
I have just figured it out. The problem was in the constructor or initialize method. By changing the initialize method to:
def initialize( options = {} )
#title = options[:title]
#series = []
end
It now accepts all params perfectly!

Resources