save a record on rails - ruby-on-rails

as you know from my previous questions I'm getting used to rails, currently I have a problem with a create function because it isn't save a record that is in a combobox from the database, like this:
but it saves the rest of the records in the data base, for check it I type this:
rails console
TankingLog.all
TankingLog Load (0.7ms) SELECT "tanking_logs".* FROM "tanking_logs"
[#<TankingLog id: 7, car_id: 28, cost: 3000.0, date: "2012-07-30 00:00:00", gallon: 2.0, gas_station_id: nil, km: 5000, created_at: "2012-07-30 22:00:40", updated_at: "2012-07-30 22:00:40">]
As you see the gas_station_id field is nil but it must be the id of the station selected
I appreciate any help and sorry if it's a silly question
here is the form:
<div class="container">
<h2>new tanking log</h2>
<%= form_for ([#user,#car,#tankinglog]) do |f| %>
<div><%= f.label :cost %><br />
<%= f.text_field :cost %></div>
<div><%= f.label :gallon %><br />
<%= f.text_field :gallon %></div>
<div><%= f.label :km %><br />
<%= f.text_field :km %></div>
<div><%= f.label :date %> <i>( format yyyy-mm-dd )</i> <br />
<%= f.text_field :date %></div>
<div><%= f.label :Station %><br />
<%= select("gas_station", "name", GasStation.all.collect {|gs| [ gs.name, gs.id ] }, { :include_blank => true })%></div>
<p>
if you don't see the station that you want, you can <%= link_to "create it", new_gas_station_path%>
</p>
<div><%= f.submit "create tanking",:class => "btn btn-primary" %></div>
<% end %>
<br />
<%= link_to "Back", user_car_tanking_logs_path(#user, #car),:class => "btn btn-primary"%>
</div>
and the tankinglogcontroller
class TankingLogsController < ApplicationController
def new
#user = User.find(params[:user_id])
#car = #user.cars.find(params[:car_id])
#tankinglog = #car.tanking_logs.build
end
def create
#user = User.find(params[:user_id])
#car = #user.cars.find(params[:car_id])
#tankinglog = #car.tanking_logs.build(params[:tanking_log])
if #tankinglog.save
redirect_to user_car_tanking_logs_path(#user, #car), :flash => { :notice => " new tanking created!" }
else
redirect_to new_user_car_tanking_log_path ,:flash => { :notice => " sorry try again :(" }
end
end
def index
#user = User.find(params[:user_id])
#car = #user.cars.find(params[:car_id])
#tankinglog = #car.tanking_logs.all
end
end
if you wanna see the models...
class TankingLog < ActiveRecord::Base
belongs_to :gas_station
belongs_to :car
attr_accessible :car_id, :cost, :date, :gallon, :gas_station_id, :km
validates_presence_of :cost, :date,:gallon,:km
validates_numericality_of :cost, :gallon
validates_numericality_of :km #:only_integer
end
class GasStation < ActiveRecord::Base
has_many :tanking_logs
attr_accessible :name
validates_presence_of :name
end

Edit this :
<%= f.select("gas_station_id", GasStation.all.collect {|gs| [ gs.name, gs.id ] }, { :include_blank => true })%></div>

Related

Ruby On Rails: Parameters - Permitted: false

I'm having issues with a form in my Rails 6 application.
I have a remote form which enters new data into the database via a JSON request, which works but only with one parameter. This is the form:
<%= form_with(method: :post, remote: true, model: Meal.new, url: meals_path, class: "editMealsForm", data: { type: "json" }) do |f| %>
<div class="field">
<%= f.label :description, 'Beschreibung' %><br>
<%= f.text_area :description, rows: "4", placeholder: "Noch keine Mahlzeit für diesen Tag vorhanden, bitte eintragen!", class: "form-control" %>
</div>
<div class="field">
<%= f.label :allergene_ids_add, 'Allergene auswählen', class: "card-text" %><br>
<%= select_tag :allergene_ids_add, options_from_collection_for_select(#allergenes, :id, :name), multiple: true, class: "selectpicker", data: { style: "btn-success", width: "fit", live_search: "true", size: "5", title: "Allergien wählen" } %>
</div>
<% f.hidden_field :day, :value => local_assigns[:mealDay] %>
<% f.hidden_field :tip, :value => "Vollkost" %>
<%= f.submit "Speichern", class: "btn btn-primary mt-2 btn-block" %>
<% end %>
And these are my permitted parameters:
def meal_params
params.require(:meal).permit(:day, :tip, :description, allergene_ids_add: [])
end
And this is my controller action:
def create
#meal = Meal.new(meal_params)
byebug
if #meal.save
if params[:allergene_ids_add].present?
#allergenes_to_add = Allergene.find(params[:allergene_ids_add])
#allergenes_to_add.each do |allergene|
#meal.allergenes << allergene
end
end
respond_to do |format|
format.html { redirect_to meals_path }
format.json { render json: #meal }
end
end
end
The problem is, that if I hit the create action, just the description parameter is permitted, the other ones are just "ignored", so if I fire the submit button I get the following output in the console if I hit my byebug breakpoint:
And if I look at the params:
<ActionController::Parameters {"authenticity_token"=>"derBZeirq0bwr/FWoYRr97qUZ5p66vQc+uT+UMf5xjXXTSFEp+XOepJtGrckguGh+skWXTZ9ibHWfFTt3p80Cg==", "meal"=><ActionController::Parameters {"description"=>"test"} permitted: false>, "commit"=>"Speichern", "controller"=>"meals", "action"=>"create"} permitted: false>
Or just at the meal params:
<ActionController::Parameters {"description"=>"test"} permitted: true>
If I run #meal.valid? it returns true, so I don't see where the issue is.
Also if I check the values for the hidden fields in the form, they are filled and not nil.
So why does this one parameter work, but the rest just isn't permitted even if I got them in my meal_params method?
Okay, I am dumb.
I just forgot the = for the hidden fields.
So instead of:
<% f.hidden_field :day, :value => local_assigns[:mealDay] %>
<% f.hidden_field :tip, :value => "Vollkost" %>
it should be:
<%= f.hidden_field :day, :value => local_assigns[:mealDay] %>
<%= f.hidden_field :tip, :value => "Vollkost" %>
Then everything is working.

Getting an "undefined method `permit' for "create"" error when submitting form

When I try to create an "Action" I get this error.
My Actions controller:
class ActionsController < ApplicationController
def new
#match_set = MatchSet.find(params[:match_set_id])
#fixture = #match_set.fixture
#teams = Team.where("id = " + #fixture.home_team_id.to_s + " OR id = " + #fixture.away_team_id.to_s)
#players = Player.where("team_id = " + #teams.ids.first.to_s + " OR id = " + #teams.ids.last.to_s)
#action = #match_set.actions.new
end
def create
#match_set = MatchSet.find(params[:match_set_id])
#action = #match_set.actions.new(action_params)
if #action.save
redirect_to match_set(#match_set)
else
render "actions/new"
end
end
private
def action_params
params.require(:action).permit(:team_id, :player_id, :position, :action_type, :action_result)
end
end
It is submitted from this form in views/actions/new.html.erb:
<%= form_for [#match_set, #action] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<!-- Team -->
<%= f.label :team_id %>
<%= f.collection_select :team_id, #teams,:id, :name, {include_blank: "Select team..."}, {class: "form-control"} %>
<!-- Player -->
<%= f.label :player_id %>
<%= f.collection_select :player_id, #players,:id, :last_name, {include_blank: "Select player..."}, {class: "form-control"} %>
<!-- Position -->
<%= f.label :position %>
<%= f.select :position, options_for_select(['1', '2', '3', '4', '5', '6']), {include_blank: "Select position on court..."}, class: "form-control" %>
<!-- Action Type -->
<%= f.label :action_type %>
<%= f.select :action_type, options_for_select(['Attack', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Action Result -->
<%= f.label :action_result %>
<%= f.select :action_result, options_for_select(['Score', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Submit Button -->
<%= f.submit "Add Action", class: "btn btn-primary" %>
<% end %>
Also the relevant routes:
resources :fixtures, shallow: true do
resources :match_sets, shallow: true do
resources :actions
end
end
I'm getting an error on this line in the controller:
params.require(:action).permit(:team_id,:player_id,
:position,:action_type,:action_result)
I have also noticed that my parameters seem to be disappearing but again have no clue as to the cause.
Parameters:
{"utf8"=>"✓", "authenticity_token"=>"BqbEOfL7hEA8XSMXDvMW2qQ2uR74Egp5
jJvtQlsuyV2TikZJ+6hTIEMH05gy8TM6r3ZglFDRUFBl7ScZD1czCQ==",
"commit"=>"Add Action", "match_set_id"=>"15"}
Any help is appreciated.
action is a reserved word in rails. You will need to change your model name.
Rails provides a few params on each request such as:
params[:controller] # maps to your controller name
params[:action] # maps to an action with your controllers
http://api.rubyonrails.org/classes/ActionDispatch/Routing.html

Error "param is missing or the value is empty: personas_x_tipos_persona"

I'm starting in rails and I have this error that I'm not able to solve..
Error - param is missing or the value is empty:
personas_x_tipos_persona
Controller
class PersonasController < ApplicationController
def create_cliente
#cliente = Persona.new(persona_params)
#personas_x_tipos_personas = Persona.new(tipos_personas_params)
if #cliente.save
redirect_to show_clientes_path
else
render :new_cliente
end
end
private
def persona_params
params.require(:persona).permit(:nombre, :apellido, :direccion, :ruc, :contacto, :email)
end
def tipos_personas_params
params.require(:personas_x_tipos_persona).permit(:linea_credito)
end
end
view
<div>
<%= form_for :persona ,:url => add_cliente_path, :html => {:method => :post} do |f|%>
<% #cliente.errors.full_messages.each do |message| %>
<div class="alert alert-danger" margin-top:10px">
* <%=message%>
</div>
<% end %>
<%= f.text_field :nombre, placeholder: "Nombre del Cliente"%>
<%= f.text_field :apellido, placeholder: "Apellido del Cliente"%>
<%= f.text_field :direccion, placeholder: "Direccion del Cliente"%>
<%= f.text_field :ruc, placeholder: "RUC del Cliente"%>
<%= f.text_field :contacto, placeholder: "Contacto del Cliente"%>
<%= f.email_field :email, placeholder: "Email del Cliente""%>
<%= f.fields_for :personas_x_tipos_persona do |pxp|%>
<%= pxp.number_field :linea_credito, placeholder: "Linea de Credito del Cliente"%>
<% end %>
<%= f.submit 'Guardar'%>
<% end %>
</div>
param is missing or the value is empty: personas_x_tipos_persona
The problem is with this line #personas_x_tipos_personas = Persona.new(tipos_personas_params)(actually this is not needed) which is calling tipos_personas_params.
From the docs of require(key),
When passed a single key, if it exists and its associated value is
either present or the singleton false, returns said value
Otherwise raises ActionController::ParameterMissing
So, in your case the require is expecting :personas_x_tipos_persona, while this is missing in the params, so is the error.
Actually, the form object is :persona not :personas_x_tipos_persona. Also as I can see that you are using fields_for, so you need to whitelist :personas_x_tipos_persona_attributes inside persona_params and the tipos_personas_params method is not needed. The below code should get you going.
class PersonasController < ApplicationController
def create_cliente
#cliente = Persona.new(persona_params)
#this is not needed
##personas_x_tipos_personas = Persona.new(tipos_personas_params)
if #cliente.save
redirect_to show_clientes_path
else
render :new_cliente
end
end
private
def persona_params
params.require(:persona).permit(:nombre, :apellido, :direccion, :ruc, :contacto, :email, personas_x_tipos_persona_attributes: [:id, :linea_credito])
end
end

Value not getting stored in rails instance variable

I have a simple form which records Payments received :
<label>Client Name*</label>
<%= f.collection_select :client_id, Client.all, :id, :name, {prompt:"Select Client"},{ class: "form-control"} %>
<label>Service Name</label>
<%= f.collection_select :service_id, Service.all, :id, :name, {prompt: "Select Service"},{ class: "form-control"}%><label>Payment Amount</label>
<%= f.text_field :amount, placeholder: "Enter the amount received",class: "form-control" %>
<label>Payment Date</label> <br/>
<%= f.date_select :recieved_date, placeholder: "Enter the payment date",class: "form-control" %><br/>
<br/>
<%= f.submit "Submit", class: "btn btn-success" %>
<% end %>
The values are then passed on the controller:
def create
#payment = Payment.new(payment_params)
order = Order.where("client_id = ? and service_id = ?", payment_params[:client_id], payment_params[:service_id]).pluck(:id)
#payment.order_id = order[0]
if #payment.save
redirect_to new_payment_path, notice: "Successfully created Payment!"
else
render action: 'new'
end
end
As you can observe, the line
order = Order.where("client_id = ? and service_id = ?", payment_params[:client_id], payment_params[:service_id]).pluck(:id) attempts to store the order_id based on the client_id and service_id. However this is not working and the order object is getting saved with a nil value when being saved (when the validation to check for order_id is removed that is)
Why is this ? any hints please

Rails 3 - undefined method `map' for nil:NilClass for my own validation

I met very strange problem. I have Timetable model and try to write my custom validation. So, now i'm just trying to add test error for field to make sure that everything is ok. But it doesn't work. So, i try to update object of Timetable model but when i don't use my test custom validation everything works perfect. Otherwise i get such error:
NoMethodError in Timetables#update
undefined method `map' for nil:NilClass
32:
33: <div class="controls">
34: <%= f.select( :curriculum_id,
35: options_for_select( #subjects_with_curriculums,
36: #tt.curriculum_id ),
37: { :include_blank => true }) %>
38: </div>
Here is my model:
# == Schema Information
#
# Table name: timetables
#
# id :integer not null, primary key
# curriculum_id :integer
# school_class_id :integer
# tt_day_of_week :string(255)
# tt_number_of_lesson :integer
# tt_room :string(255)
# tt_type :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class Timetable < ActiveRecord::Base
belongs_to :curriculum
belongs_to :school_class
has_many :lessons
validates :school_class_id, :presence => { :message => "should exist" }
validates :tt_day_of_week,
:presence => true,
:inclusion => { :in => %w(Mon Tue Wed Thu Fri) }
validates :tt_number_of_lesson,
:presence => true,
:inclusion => {
:in => 1..9,
:message => "should have 1..9 symbols"
}
validates :tt_room,
:length => {
:maximum => 3,
:message => "should have 3 symbols"
},
:allow_blank => true
validates :tt_type,
:inclusion => { :in => ["Primary lesson", "Extra"] },
:allow_blank => true
validate :test
def test
errors.add(:tt_number_of_lesson, "test")
end
end
My controller:
# encoding: UTF-8
class TimetablesController < ApplicationController
...
def edit
#types_of_lesson = collect_types_of_lesson
#tt = Timetable.find( params[:id] )
#subjects_with_curriculums = collect_subjects_with_curriculums( #tt.school_class )
end
def update
#tt = Timetable.find( params[:id] )
if #tt.update_attributes( params[:timetable] )
flash[:success] = "Расписание успешно обновлено!"
redirect_to timetables_path
else
flash.now[:error] = #tt.errors.full_messages.to_sentence :last_word_connector => ", ",
:two_words_connector => ", "
render 'edit'
end
end
private
# Collecting subjects names for school class and curriculum_id for each subject.
def collect_subjects_with_curriculums( school_class )
subjects = school_class.curriculums.collect do |c|
[ c.qualification.subject.subject_name, c.id ]
end
end
def timetable_for_class_with_existance_data( school_class )
return [] if Timetable.all.empty?
Timetable.select do |t|
( t.school_class.class_code == school_class.class_code ) and
not ( t.tt_room.blank? ) and not ( t.tt_type.blank? ) and
not ( t.curriculum_id.nil? )
end.to_a
end
# Return for school class it's timetable.
def timetable_for_class( school_class )
Timetable.select{|t| t.school_class.class_code == school_class.class_code }.to_a
end
def subjects_of_class( school_class )
subjects = school_class.curriculums.collect do |c|
c.qualification.subject.subject_name
end
end
# Return sorted by number of lesson tometable for one day.
def sorted_timetable_for_day( timetable, day )
timetable.select{ |t| t.tt_day_of_week == day }
.sort_by{ |e| e[:tt_number_of_lesson] }
end
# Return russian name for type of lesson.
def collect_types_of_lesson
[ ["Обязательно занятие", "Primary lesson"], ["Электив", "Extra"] ]
end
# Check if timetable already has been created for school class.
def timetable_exists?( school_class )
not timetable_for_class( school_class ).empty?
end
end
My view
<%= form_for #tt, :html => {:class => "form-horizontal"} do |f| %>
<%= field_set_tag do %>
<%= f.hidden_field :tt_number_of_lesson %>
<%= f.hidden_field :tt_day_of_week %>
<%= f.hidden_field :school_class_id %>
<div class="control-group">
<%= f.label :tt_day_of_week, "Day of the week", :class => "control-label" %>
<div class="controls">
<%= content_tag( :span, translate_day_of_week( #tt.tt_day_of_week ),
:class =>"input-xlarge uneditable-input span2" ) %>
</div>
</div>
<div class="control-group">
<%= f.label :tt_number_of_lesson, "Number of lesson", :class => "control-label" %>
<div class="controls">
<%= content_tag( :span, #tt.tt_number_of_lesson,
:class =>"input-xlarge uneditable-input span1" ) %>
</div>
</div>
<hr/>
<div class="control-group">
<%= f.label :curriculum_id, "Type of subject", :class => "control-label" %>
<div class="controls">
<%= f.select( :curriculum_id,
options_for_select( #subjects_with_curriculums,
#tt.curriculum_id ),
{ :include_blank => true }) %>
</div>
</div>
<div class="control-group">
<%= f.label :tt_room, "Code of the room", :class => "control-label" %>
<div class="controls">
<%= f.text_field :tt_room, :class => "span2", :maxlength => 3 %>
</div>
</div>
<div class="control-group">
<%= f.label :tt_type, "Type of the lesson", :class => "control-label" %>
<div class="controls">
<%= f.select( :tt_type,
options_for_select( #types_of_lesson,
#tt.tt_type ),
{ :include_blank => true }) %>
</div>
</div>
<%= f.submit "Update", :class => "btn btn-large btn-warning" %>
<% end %>
<% end %>
When i remove:
<div class="control-group">
<%= f.label :curriculum_id, "Type of subject", :class => "control-label" %>
<div class="controls">
<%= f.select( :curriculum_id,
options_for_select( #subjects_with_curriculums,
#tt.curriculum_id ),
{ :include_blank => true }) %>
</div>
</div>
<div class="control-group">
<%= f.label :tt_type, "Type of the lesson", :class => "control-label" %>
<div class="controls">
<%= f.select( :tt_type,
options_for_select( #types_of_lesson,
#tt.tt_type ),
{ :include_blank => true }) %>
</div>
</div>
I can view my test error. I can't figure what is going on.
You say this in your update controller:
render 'edit'
That simply tells Rails to render the edit template, it doesn't run any of the code associated with the edit controller, it simply renders edit.html.erb in the current context.
From the Layouts and Rendering in Rails Guide:
2.2.2 Rendering an Action’s View
[some stuff about render 'x', render :x, and render :action => :x being the same...]
Using render with :action is a frequent source of confusion for Rails newcomers. The specified action is used to determine which view to render, but Rails does not run any of the code for that action in the controller. Any instance variables that you require in the view must be set up in the current action before calling render.
Pay particular attention to the last sentence:
Any instance variables that you require in the view must be set up in the current action before calling render.
You're setting #subjects_with_curriculums in the edit controller but using the edit view from the update controller. The result is that #subjects_with_curriculums is nil when edit.html.erb tries to use it when update tries to render the edit view.
You'll need to set #subjects_with_curriculums in your update controller, you might need #types_of_lesson as well.

Resources