I've just started a new app where I want to take a postcode in a form and save it to the database. My problem is that the create action doesn't seem to be being called no matter what I try.
Routes:
root 'postcodes#new'
resources :postcodes, only: [:new ,:create]
Controller: postcodes_controller.rb
class PostcodesController < ApplicationController
def new
#postcode = Postcode.new
end
def create
#postcode = Postcode.new(postcode_params)
if #postcode.save
flash[:success] = 'Success'
else
flash[:error] = 'Error'
end
end
private
def postcode_params
params.require(:postcode).permit(:code)
end
end
Model: postcode.rb
class Postcode < ApplicationRecord
validates :code, presence: true, uniqueness: true
end
View: postcodes/new.haml
.container
%form
%fieldset.form-group
= form_for #postcode do |f|
= f.label :postcode
= f.text_field :code, placeholder: 'Example Postcode', class: 'form-control'
= f.submit 'Submit', class: 'btn btn-primary'
I've attempted to pass more options in the form_for such as the method and action and now I have a feeling it's a routing error.
Any help will be appreciated.
Thanks.
I believe the problem you are experiencing is a result of your HAML.
You do not need to use, nor should you use, a form HTML element outside the form_for method call.
The form_for method will handle generating this HTML element/tag for you.
You have:
.container
%form
%fieldset.form-group
= form_for #postcode do |f|
= f.label :postcode
= f.text_field :code, placeholder: 'Example Postcode', class: 'form-control'
= f.submit 'Submit', class: 'btn ban-primary'
Which outputs an empty <form> element.
You should have:
.container
= form_for #postcode do |f|
%fieldset.form-group
= f.label :postcode
= f.text_field :code, placeholder: 'Example Postcode', class: 'form-control'
= f.submit 'Submit', class: 'btn ban-primary'
That should generate a proper <form> tag with the required action and method attributes populated with the right URL and 'post' so that your create action is called.
Related
I have a form that I am using for new and edit, and the functionality for index and clicking for a new form and edit works, but when I go to create or update the form returns a load error to another controller.
The controller is PathCreationsController in system and it wants to use the creations controller in another place and it wants to use it to define it..which is weird because I don't have anything set to do that.
I tried adding a url to the form and setting the method to put but when I do that to try and force the controller to work correctly it sets all the params to null in the database so I assumed thats not a valid way to fix this.
Here is the controller:
class System::PathCreationsController < ApplicationController
def index
#paths = Path::Account.all
end
def new
#paths = Path::Account.new
end
def edit
#paths = Path::Account.friendly.find(params[:id])
end
def create
#paths = Path::Account.new
if #paths.save
redirect_to system_path_creations_path(#paths)
end
end
def update
#path = Path::Account.find_by(slug: params[:id])
if #path.update
redirect_to system_path_creations_path(#path)
end
end
end
Here is the form:
= form_for #paths do |f|
%br
.form-group
= f.label :name, class: 'control-label'
= f.text_field :name, class: 'form-control'
.form-group
= f.label :slug, class: 'control-label'
= f.text_field :slug, maxlength: 28, class: 'form-control'
.form-group
%p.text-muted Click to upload new icon.
.fileinput.fileinput-new{"data-provides" => "fileinput"}
%div
.fileinput-thumbnail.thumbnail{style: 'max-width: 100%;'}
.fileinput-preview{data: {trigger: "fileinput"}, style: 'max-width: 100%;'}
= image_tag #firms.try(:logo).try(:present?) ? #life_event.try(:logo).try(:url) : asset_path('/path.svg')
%div
%span.btn.btn-default.btn-file.btn-sm{style: 'display: none;'}
= f.file_field :logo, class: 'file'
= f.hidden_field :logo_cache
.form-group
= f.label :user_id
= f.select :user_id, User.all.collect {|u| [#{u.email}", u.id] }
= f.submit class: 'btn btn-primary btn-sm'
In the create action you never set update the parameters on the model
def create
#paths = Path::Account.new(path_params)
if #paths.save
redirect_to system_path_creations_path(#paths)
end
end
you will also need to add
def path_params
params.require(:path_account).permit(:name, :slug, :other, :params, :to, :permit)
end
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
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
There is the following form code:
= form_for #task, html: { class: 'form-horizontal' } do |f|
.form-group
.col-sm-9.col-sm-offset-3
= render partial: 'shared/form_errors', locals: { subject: #task }
.form-group
label.col-sm-3.control-label for='title' Title
.col-sm-9
= f.text_field :title, class: 'form-control', placeholder: 'Title'
.form-group
label.col-sm-3.control-label for='description' Description
.col-sm-9
= f.text_area :description, class: 'form-control', placeholder: 'Description'
.form-group
label.col-sm-3.control-label Teams
.col-sm-9
ul
- Team.all.each do |t|
li
= check_box_tag "team_ids", t.id, #task.teams.include?(t), name: 'task[team_ids][]'
= t.name
.form-group
.col-sm-9.col-sm-offset-3
= f.submit 'Save', class: 'btn btn-success'
As you can see I can select team for my task through checkboxes. My controller:
def update
#task = Task.find(params[:id])
if #task.update(task_params)
redirect_to tasks_path, flash: { alert: TASK_UPDATING_MESSAGE }
else
render 'edit'
end
end
private
def task_params
params.require(:task).permit(:title, :description, team_ids: [])
end
It works good if I update task with some checked teams; but also I want to have ability to check no teams and update taks with empty array of teams. But in this case tasks_params doesn't have team_ids array, and updating doesn't work. How can I fix it? Thanks!
My understanding is that when you submit your form with nothing checked, you have params[:task][:team_ids] = nil.
You can try something like:
def task_params
params[:task][:team_ids] = [] if params[:task][:team_ids].nil?
params.require(:task).permit(:title, :description, team_ids: [])
end
You can do it using collection_check_boxes, just replace the list of teams with:
ul
= f.collection_check_boxes :team_ids ,Team.all, :id, :name do |b|
= content_tag :li, raw("#{b.label { b.check_box } }" + b.object.name)
And this will do the trick.
Note: With this Rails add a hidden field, which fix your issue, also you will fix it only with this:
<input type="hidden" name="task[team_ids][]" value="" autocomplete="off">
The project which I am working in, is developed on Rails using haml markup to views. There is a view with a simple form like this:
= simple_form_for #message, url: [:admin, #request, #message], html: { class: 'form vertical-form} do |f|
= f.input :text, as: :text, input_html: { class: 'form-control', rows: 5 }
%br
= f.input :link_url, input_html: { class: 'form-control'}
%br
- if #message.has_picture_image?
= f.label :image
=link_to #message.picture_image, target: "_blank" do
= image_tag #message.picture_image(:thumb)
= f.file_field :image, class:'imagen-button'
= f.input_field :remove_picture, as: :boolean, inline_label: 'Remove'
%br
.form-actions
= f.submit(t('accept'), class: 'btn btn-large btn-primary')
= link_to(t('cancel'), [:admin, #message.request, #message], class: 'btn btn-large btn-danger')
and in Message model there is the bellow method:
def remove_picture
self.picture.destroy
end
The input_field is used to check if I want to remove the message image if it exists. I understood that input_filed gives me the option to check it so that when I click on accept button, it call the method remove_picture in the Message model. But, before the browser deploys the form, it rise the next error:
undefined method `to_i' for #<Picture:0x007f7675162b58>
Extracted source (around line #39):
37: = image_tag #message.picture_image(:thumb)
38: = f.file_field :image, class:'imagen-button'
39: = f.input_field :remove_picture, as: :boolean, inline_label: 'Remove'
40: %br
41: .form-actions
42: = f.submit(t('accept'), class: 'btn btn-large btn-primary')
and if I reload the page, this time the form is deployed. I guess this is because in the first time, as the picture exists then immediatly the remove_picture is called and the picture removed, and when I reload the form, as the picture already does not exist, the form is shown.
Obviously I am undestanding wrongly the input_field usage.
SimpleForms input_field is a helper which binds an input to a model attribute. It does not create a box which calls your method when the box is ticked! But rather it will call your remove_picture method when it rendering the form.
In some cases like checkboxes you will want to bind inputs to attributes that are not saved in the database. We call these virtual attributes. They are just like any old Ruby attributes:
class Message < ActiveRecord::Base
attr_accessor :remove_picture
# since this method is destructive it should have a bang (!)
def remove_picture!
self.picture.destroy
end
end
You could use it like this:
class MessagesController < ApplicationController
def update
#message.update(update_params)
#message.remove_picture! if message.remove_picture
# ...
end
def update_params
params.require(:message).allow(:remove_picture)
end
end
But there is a better way:
class Message < ActiveRecord::Base
has_one :picture_image
accepts_nested_attributes_for :picture_image, allow_destroy: true
end
accepts_nested_attributes_for lets us create an image with picture_image_attributes and destroy an image with:
#picture.update(picture_image_attributes: { _destroy: true })
This is how we would set up the form:
= simple_form_for #message, url: [:admin, #request, #message], html: { class: 'form vertical-form} do |f|
= f.input :text, as: :text, input_html: { class: 'form-control', rows: 5 }
%br
= f.input :link_url, input_html: { class: 'form-control'}
%br
- if #message.has_picture_image?
f.simple_fields_for :picture_image do |pif|
= pif.label :image
= link_to #message.picture_image, target: "_blank" do
= image_tag #message.picture_image(:thumb)
= pif.file_field :image, class:'imagen-button'
= pif.input_field :_destroy, as: :boolean, inline_label: 'Remove'
%br
.form-actions
= f.submit(t('accept'), class: 'btn btn-large btn-primary')
= link_to(t('cancel'), [:admin, #message.request, #message], class: 'btn btn-large btn-danger')
And your strong parameters whitelist:
def update_attributes
params.require(:message).allow(
:text,
:link_url,
picture_image_attributes: [:image, :_destroy]
)
end