Here is my tournaments_controller file:
class TournamentsController < ApplicationController
before_action :authenticate_user!, only: [:new, :create, :destroy]
def index
end
def show
end
def new
render action: 'new'
end
def create
self.tournament = Tournament.new(tournament_params)
if tournament.save
flash[:info] = "Tournament created successfully!"
redirect_to root_url
else
render action: 'new'
end
end
def destroy
Tournament.find(params[:id]).destroy
flash[:success] = "Tournament deleted!"
redirect_to root_url
end
private
def tournament_params
params.require(:tournament).permit(:name, :maxplayers)
end
end
This is my form file:
= form_for tournament do |f|
- if tournament.errors.any?
#error_explanation
%h2= "#{pluralize(tournament.errors.count, "error")} prohibited this tournament from being saved:"
%ul
- tournament.errors.full_messages.each do |msg|
%li= msg
.form-group
= f.label :name
= f.text_field :name, class: 'form-control'
= f.submit 'Save', class: 'btn btn-primary'
When my app runs, console display this error:
undefined local variable or method `tournament' for #<#<Class:0x007f0e414fa2d0>:0x007f0e418d9a90>
I'm using simple-form and Haml if it's important.
Can anyone explain to me why I am getting this error?
You have to use an instance variable:
def new
#tournament = Tournament.new
render action: 'new'
end
def create
#tournament = Tournament.new(tournament_params)
if #tournament.save
flash[:info] = "Tournament created successfully!"
redirect_to root_url
else
render action: 'new'
end
end
and
= form_for #tournament do |f|
- if #tournament.errors.any?
#error_explanation
%h2= "#{pluralize(#tournament.errors.count, "error")} prohibited this tournament from being saved:"
%ul
- #tournament.errors.full_messages.each do |msg|
%li= msg
.form-group
= f.label :name
= f.text_field :name, class: 'form-control'
= f.submit 'Save', class: 'btn btn-primary'
= link_to 'Back', categories_path, class: 'btn btn-default'
Related
hope your having a wonderful day drinking some coffee and responding to some forms.
Problem:
As my title states, I am trying to create 2 forms on one view. I am new to ruby on rails.
My controller functions:
Controller name is border_rotation:
def create
if params[:export_submit]
#border_rotation_export = BorderRotationExport.new(border_rotation_export_params)
respond_to do |format|
if #border_rotation_export.save
flash[:success] = "Export successfully created"
format.html { render :new }
else
flash[:error] = "Export was not created."
end
end
else
#border_rotation_import = BorderRotationImport.new(border_rotation_import_params)
respond_to do |format|
if #border_rotation_import.save
flash[:success] = "Export successfully created"
format.html { render :new }
else
flash[:error] = "Export was not created."
end
end
end
end
def new
#border_rotation_export = BorderRotationExport.new
#border_rotation_import = BorderRotationImport.new
end
private
def border_rotation_export_params
params.require(:border_rotation_export).permit(:exporter_name,:vehicle_color,:rot_num,:current_date,:current_time,:goods_description,:license_num,:entry)
end
def border_rotation_import_params
params.require(:border_rotation_import).permit(:importer_name,:vehicle_color,:rot_num,:current_date,:current_time,:goods_description,:license_num,:entry)
end
My new View form:
It has 2 forms and is enclosed in bootstrap tabs
<%= form_for #border_rotation_export, url: rotation_create_path, method: :post do |f|%>
<lable>Importer Name: </lable><%= f.text_field :importer_name, class: "form-control", placeholder: "Importer Name"%>
<lable>Vehicle Color: </lable><%= f.text_field :vehicle_color, class: "form-control", placeholder: "Vehicle Color"%>
**its fields**
<% end %>
and
<%= form_for #border_rotation_import, url: rotation_create_path, method: :post do |f|%>
<lable>Exporter Name: </lable><%= f.text_field :exporter_name, class: "form-control", placeholder: "Exporter Name"%>
<lable>Vehicle Color: </lable><%= f.text_field :vehicle_color, class: "form-control", placeholder: "Vehicle Color"%>
**its fields**
<% end %>
The error in my new.html.rb
First argument in form cannot contain nil or be empty
Displays this in red highlighted
<%= form_for #border_rotation_export, url: rotation_create_path, method: :post do |f|%>
My guess is that it submits both forms but only has the parameters for one form with the input data. Once I submit, it saves to the database but it gives me the error
**Routes **
get 'rotation/create', to: 'border_rotation#create'
post 'rotation/create', to: 'border_rotation#create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"Cu52CIDgrY0b7Yk6edkd7+RTl5yR4qSEqPPrqWtM0nIQVDvw7eYDF36zduJPLjI+vVNqCfgtLcMDUEkW6qDOdQ==",
"border_rotation_import"=>
{"importer_name"=>"john",
"vehicle_color"=>"red",
"rot_num"=>"11sssfeeea",
"current_date"=>"2021-09-22",
"current_time"=>"09:37",
"goods_description"=>"yogurt",
"license_num"=>"c-11223",
"entry"=>"c1223"},
"import_submit"=>"Submit"}
Thank you in advance
You can setup the controller with a lot less redundancy:
# config/routes.rb
resources :rotations, only: [:new, :create]
class BorderRotationsController < ApplicationController
# GET /rotations/new
def new
populate_forms
end
# POST /rotations
def create
resource = model_class.new(create_params)
set_ivar(resource) # sets #border_rotation_export or #border_rotation_import
if resource.save
flash[:success] = "#{humanized} successfully created"
redirect_to action: :new
else
populate_forms
flash[:error] = "#{humanized} could not be created - please try again."
render :new
end
end
private
# gets the model class via params[:subtype]
def model_class
#model_class ||= begin do
if params[:border_rotation_export].present?
BorderRotationExport
else
BorderRotationImport
end
end
end
def humanized
model_class == BorderRotationExport ? 'Export' : 'Import'
end
def set_ivar(value)
instance_variable_set(
"##{param_key}",
value
)
end
# just sets up the instance variables for the form
def populate_forms
#border_rotation_export ||= BorderRotationExport.new
#border_rotation_import ||= BorderRotationImport.new
end
# border_rotation_export or border_rotation_import
def param_key
model_class.model_name.param_key
end
def create_params
require(param_key).permit(
:exporter_name, :vehicle_color, :rot_num,
:current_date,:current_time, :goods_description,
:license_num, :entry
)
end
And then use partials so that you can resuse the same form:
# app/views/border_rotations/new.html.erb
<%= render partial: 'form',
locals: { border_rotation: #border_rotation_export } %>
<%= render partial: 'form',
locals: { border_rotation: #border_rotation_import } %>
# app/views/border_rotations/new.html.erb
<%= form_with model: border_rotation, url: rotations_path do |f| %>
<div class="field">
<%= f.label :importer_name %>
<%= f.text_field :importer_name, class: "form-control" %>
</div>
<div class="field">
<%= f.label :importer_name %>
<%= f.text_field :importer_name, class: "form-control" %>
</div>
# ...
<% end %>
If the requirements diverge use two separate routes/controllers and inheritance instead of blooming out in tons of new code paths.
I am currently working on an recipe box application, using ruby on rails. When I want to create a new recipe It says
undefined method `title'
for
= f.input :title, input_html: { class: 'form-control' }
This is my form.html.haml
= simple_form_for #recipe, html: { multipart: true } do |f|
- if #recipe.errors.any?
#errors
%p
= #recipe.errors.count
Prevented this recipe from saving
%ul
- #recipe.errors.full_messages.each do |msg|
%li= msg
.panel-body
= f.input :title, input_html: { class: 'form-control' }
= f.input :description, input_html: { class: 'form-control' }
= f.button :submit, class: "btn btn-primary"
And this my recipes_controller.rb
class RecipesController < ApplicationController
before_action :find_recipe, only: [:show, :edit, :update, :destroy]
def index
end
def show
end
def new
#recipe = Recipe.new
end
def create
#recipe = Recipe.new(recipe_params)
if #recipe.save
redirect_to #recipe, notice: "Toll! Neues Rezept erfolgreich erstellt."
else
render 'new'
end
end
private
def recipe_params
params.require(:recipe).permit(:title, :description)
end
def find_recipe
#recipe = Recipe.find(params[:id])
end
end
You have to render form in 'new' view
You have to have column 'title' in your DB
Show us what 'debug #recipe' prints, is there 'title' attribute?
I need help with allowing users to click "Follow/Unfollow" link and have the action take place on the user show page. Currently I have the action sitting inside a popup and I don't know how I can set it inside a link action so there would be no need for a popup.
I tried rendering the forms on the show page but that does not show as I expected.
show.html.slim:
- if current_user.following?(#user)
= link_to follow_popup_user_path(#user), class: 'profile_btn save_btn', :'data-mfp-src'=>'#follow_div', remote: true do
= image_tag 'start_icon.png'
span Unfollow
- else
= link_to follow_popup_user_path(#user), class: 'profile_btn save_btn', :'data-mfp-src'=>'#follow_div', remote: true do
= image_tag 'start_icon.png'
_follow.html.slim:
= form_for(current_user.relationships.build(followed_id: #user.id)) do |f|
div
= f.hidden_field :followed_id
= f.submit "Follow", class: "btn btn-large btn-primary"
_unfollow.html.slim:
= form_for(current_user.relationships.find_by(followed_id: #user),
html: { method: :delete }) do |f|
= f.submit "Unfollow", class: "btn btn-large"
Relationships controller:
def create
#user = User.find(params[:relationship] [:followed_id] )
current_user.follow!(#user)
redirect_to #user
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
redirect_to #user
end
end
You shouldn't need a form for this, just pass the correct params to a nested route for relationships, then handle the specifics in the user model follow and unfollow methods. Try something like this:
users/show.slim
- if current_user.following?(#user)
= link_to new_user_relationship_path(id: current_user.id, followed_id: #user.id), class: 'profile_btn save_btn' do
= image_tag 'start_icon.png'
span Unfollow
- else
= link_to user_relationship_path(id: current_user.id, followed_id: #user.id), method: delete, class: 'profile_btn save_btn' do
= image_tag 'start_icon.png'
routes
resources :users do
resources :relationships
relationships_controller
def create
#user = User.find(user_params(:id))
#followed_user = User.find(user_params(:followed_id))
#user.follow #followed_user
redirect_to #user
end
def destroy
#user = User.find(user_params(:id))
#followed_user = User.find(user_params(:followed_id))
#user.unfollow #followed_user
redirect_to #user
end
private
def user_params
params.require(:user).permit(:followed_id, )
end
I am making a form in my rails application where people have the option of adding images and I am using 'carrierwave' but I am getting an undefined method error on the edit page. Here is the code for the form:
<%= title "Add Item to #{#todo_list.title}" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<%= form.file_field :picture %>
<% end %>
Here I can see the upload button and it is working fine but on the edit page I get the above stated error. Code for my edit page:
<%= title "Editing Todo Item" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<% end %>
<div class="row">
<div class="small-12 columns">
<%= link_to "Delete", todo_list_todo_item_path(#todo_list, #todo_item), method: :delete, data: { confirm: "Are you sure?" }, class: "button radius expand alert" %>
</div>
<%= #todo_item.picture %>
</div>
Why is this showing an undefined method error. I tried creating a method in my todo_item model but its still showing the above error.
Controller for todo_item:
class TodoItemsController < ApplicationController
before_action :require_user
before_action :find_todo_list
before_action :set_back_link, except: [:index]
def index
go_back_link_to todo_lists_path
end
def new
#todo_item = #todo_list.todo_items.new
end
def create
#todo_item = #todo_list.todo_items.new(todo_item_params)
if #todo_item.save
flash[:success] = "Added todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "There was a problem adding that todo list item."
render action: :new
end
end
def edit
#todo_item = #todo_list.todo_items.find(params[:id])
end
def update
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.update_attributes(todo_item_params)
flash[:success] = "Saved todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "That todo item could not be saved."
render action: :edit
end
end
def destroy
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.destroy
flash[:success] = "Todo list item was deleted."
else
flash[:error] = "Todo list item could not be deleted."
end
redirect_to todo_list_todo_items_path
end
def complete
#todo_item = #todo_list.todo_items.find(params[:id])
#todo_item.toggle_completion!
redirect_to todo_list_todo_items_path, notice: "Todo item updated."
end
def url_options
{ todo_list_id: params[:todo_list_id] }.merge(super)
end
private
def set_back_link
go_back_link_to todo_list_todo_items_path(#todo_list)
end
def find_todo_list
#todo_list = current_user.todo_lists.find(params[:todo_list_id])
end
def todo_item_params
params[:todo_item].permit(:content)
end
end
To display your image you should change
<%= #todo_item.picture %>
to
<%= image_tag(#todo_item.picture_url) %>
I want to show errors when they are in form and can not understand why this code does not work.
hotel.rb
class Hotel < ActiveRecord::Base
...
has_many :comments
...
end
comment.rb
class Comment < ActiveRecord::Base
belongs_to :hotel
belongs_to :user
delegate :email, to: :user, prefix: true
validates :body, presence: true, length: { minimum: 5, maximum:200 }
end
hotels/show.
...
%h2 Comments
#comments
.ui.piled.blue.segment
.ui.header
%i.icon.inverted.circular.blue.comment
Comments
.ui.comments
= render :partial => #hotel.comments
= render 'comments/form', comment: #hotel.comments
...
_form
-if user_signed_in?
= simple_form_for [#hotel, Comment.new] do |f|
=f.error_notification
%br
.ui.reply.form
.field
=f.label :body, "New comment"
=f.input :body, as: :text, label: false
=f.submit 'Add comment', class: "ui fluid blue labeled submit icon button"
-else
=link_to 'Sign in to add comment', new_user_session_path, class: 'ui blue button'
_comment
= div_for comment do
.comment
.content
%span.author= comment.user_email
.metadata
%span.date Posted #{time_ago_in_words(comment.created_at)} ago
.text
= comment.body
If you add too_short and too_long model that does not correct the.
UPDATE
comments_controller
class CommentsController < ApplicationController
def create
#hotel = Hotel.find(params[:hotel_id])
#comment = #hotel.comments.new(comment_params)
#comment.user_id = current_user.id
#comment.save
redirect_to #hotel
end
private
def comment_params
params.require(:comment).permit(:user_id, :body, :hotel_id)
end
end
I solved this problem.
comments_controller
def create
#hotel = Hotel.find(params[:hotel_id])
#comment = #hotel.comments.new(comment_params)
#comment.user_id = current_user.id
#comment.save
respond_to do |format|
if #comment.save
format.html { redirect_to #hotel }
else
format.html { render partial: 'comments/form' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
_form
-if user_signed_in?
= simple_form_for [#hotel, #comment] do |f|
- if #comment.errors.any?
#error_explanation
%h2
= pluralize(#comment.errors.count, "error")
prohibited this comment from being saved:
%ul
- #comment.errors.full_messages.each do |msg|
%li= msg
%br
.ui.reply.form
=f.error_notification
.inputs
=f.label :body, "New comment"
=f.input :body, as: :text, label: false
.actions
=f.button :submit, 'Add comment', class: "ui fluid blue labeled submit icon button"
-else
=link_to 'Sign in to add comment', new_user_session_path, class: 'ui blue button'
%br
This code render comment form when the comment doesn't save, and write the errors.
Your issue is in your controller. Error's won't populate until you try and save the record. Well in your instance you don't have any flow control to see if it saved, you just have #comment.save. If it doesn't save or if it does save, you do the same redirect.
Try this:
if #comment.save
redirect_to #hotel, notice: 'Comment was successfully created.'
else
redirect_to #hotel, notice: 'There was an issue trying to save your comment.'
end
Now with render :new, #comment.errors will be populated (assuming you tried an invalid length) and now you should see the error messages displayed!