ActiveRecord::RecordNotFound - ruby-on-rails

I am trying to submit a form and getting this error: Couldn't find Event without an ID
Here is the controller:
def create
#event = Event.find(params[:event_id])
#event_sponsorship = EventSponsorship.new(params[:event_sponsorship])
#event_sponsorship.sponsor_id = current_user.id
#event_sponsorship.event_id = #event
respond_to do |format|
if #event_sponsorship.save
format.html { redirect_to #event_sponsorship, notice: 'Event sponsorship was successfully created.' }
format.json { render json: #event_sponsorship, status: :created, location: #event_sponsorship }
else
format.html { render action: "new" }
format.json { render json: #event_sponsorship.errors, status: :unprocessable_entity }
end
end
end
Here is the form:
<%= simple_form_for(#event_sponsorship) do |f| %>
<%= f.error_notification %>
<div class="signin">
<%= f.hidden_field :event_id, value: #event %>
<%= f.hidden_field :sponsor_id, value: current_user.id %>
<%= f.button :submit, :class => "btn btn-success btn-block", value: "Yes" %>
</div>
<% end %>
In the create method the event_id should be found from the URL. Where am I going wrong?

Post your error as seen in your server console, you'll see that your param 'event_id' is a sub key of (I guess) 'event_sponsorship'
Try this:
#event = Event.find(params[:event_sponsorship][:event_id])
And it's even possible that you'll need to use this code:
#event = Event.find(params[:event_sponsorship].delete(:event_id))
That would remove the 'event_id' fron your params, and allow EventSponsorship.new to work without error

Related

Call create action from different controller

I would like to create a booking from bookings#new and rooms#show. When I try to create it from bookings#new it works, but when try to create it from rooms#show it shows me the error:
1 error prohibited this booking from being saved, room must exist.
Here is the code I'm using:
BookingsController:
def create
if #room
#room = Room.find(params[:room_id])
#booking = #room.bookings.create(booking_params)
if #booking.save
redirect_to room_path(#room)
else
render :new
end
else
#booking = Booking.new(booking_params)
respond_to do |format|
if #booking.save
format.html { redirect_to #booking, notice: 'Booking was successfully created.' }
format.json { render :show, status: :created, location: #booking }
else
format.html { render :new }
format.json { render json: #booking.errors, status: :unprocessable_entity }
end
end
end
end
views/rooms/show.html.erb
<h2>book this room:</h2>
<%= form_with(model: [ #room, #room.bookings.build ], local: true) do |form| %>
<p>
<%= form.label :traveller %>
<%= form.text_field :traveller %>
</p>
<p>
<%= form.label :startfrom %>
<%= form.datetime_select :startfrom %>
</p>
<p>
<%= form.label :endsat %>
<%= form.datetime_select :endsat %>
</p>
<p>
<%= form.label :bookingref %>
<%= form.text_field :bookingref %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Your mistake is inside if-else in the controller. You're checking #room before you define it, so it is always nil. It should be:
def create
# use find_by here, otherwise you get RecordNotFound error
#room = Room.find_by(id: params[:room_id])
if #room
# use build, because create saves the instance
#booking = #room.bookings.build(booking_params)
if #booking.save
redirect_to room_path(#room)
else
# I suppose you don't want render bookings/new view here
render 'books/show'
end
else
#booking = Booking.new(booking_params)
respond_to do |format|
# redirect and render logic goes here. BTW, do you really need json response format?
end
end
end
end
Also, define in rooms#show action
#booking = #room.bookings.build
and use the instance in the form to correctly display validation errors
form_with(model: [#room, #booking], local: true) do |form|

Rails artifact when changing the arrangement of elements in the form of

When you change the items in the form of an artifact appears , help me to understand what is the reason ?
view project#show:
<div class="container">
<h3><%= #project.name %></h3>
<h2>Tasks</h2>
<table class="table table-striped" id="tasks_list">
<%= render #project.tasks %>
</table>
<h2>Add a task:</h2>
<%= render 'tasks/form' %>
<%= link_to 'Back', projects_path %>
</div>
screenshot#1
If you change tasks list and add from:
<div class="container">
<h3><%= #project.name %></h3>
<h2>Add a task:</h2>
<%= render 'tasks/form' %>
<h2>Tasks</h2>
<table class="table table-striped" id="tasks_list">
<%= render #project.tasks %>
</table>
<%= link_to 'Back', projects_path %>
</div>
screenshot#2
Task list size has not changed - but there was a strange artifact.
Update
view task#_form.html.erb:
<%= form_for([#project, #project.tasks.build], remote: true) do |f| %>
<div class="input-group">
<div aria-describedby="add_project">
<%= f.text_field :name, class: 'form-control ' %>
</div>
<span class="input-group-btn">
<%= f.submit 'Добавить', class: 'btn btn-success btn-secondary', id: "add_project" %>
</span>
</div>
<% end %>
Task Controller:
def create
#project = Project.find(params[:project_id])
#task = #project.tasks.create(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #project, notice: 'Task was successfully created.' }
format.js {}
format.json { render json: #task, status: :created, location: #task }
else
format.html { render action: "new" }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to do |format|
format.html { redirect_to products_path, success: 'Task destroyed successfully' }
format.js {}
end
end
private
def task_params
params.require(:task).permit(:name)
end
Project Controller:
def index
#projects = Project.all
#project = Project.new
end
def show
#project = Project.find(params[:id])
end
def edit
#article = Project.find(params[:id])
end
def create
#project = Project.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.js {}
format.json { render json: #project, status: :created, location: #project }
else
format.html { render action: 'new' }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
Added to the form: <%= form_for([#project, #project.tasks.klass.build], remote: true) do |f| %>
Now error:
NoMethodError in Projects#show
Showing /Users/alexandr.dmitrenko/todolist/app/views/tasks/_form.html.erb where line #1 raised:
undefined method `build' for #<Class:0x007ffde19efea8>
Extracted source (around line #1):
1<%= form_for([#project, #project.tasks.klass.build], remote: true) do |f| %>
The reason is this bit:
#project.tasks.build
in your form. What it does it builds a new, non-saved Task record and stores it within association. Every further call to #project.tasks will return the usual results (from database) + this new record. What you need to do is to replace it with:
#project.tasks.scope.build
scope method will return new instance of the association, so it is safe to call build on it as it will not be stored anywhere and won't affect your original association object.

Rails trying to save form with collection_select that is empty gives undefined method `map' for nil:NilClass

I have a form with a drop down generated from a collection_select. The collection_select starts off blank and then when the user selects a date from the date field, the collection_select is updated with values for the date that is chosen.
I'm trying to show a nice error message if the form is submitted without a value chosen in my dropdown. Currently i'm getting this error: undefined methodmap' for nil:NilClass`
How can i make it so that if the user doesn't select a value in the dropdown, I can show them a nice error message?
View
<%= form_for(#arrangement) do |f| %>
<div class="control-group">
<%= f.label :date, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :date, :class => 'input-large datepicker' %>
</div>
</div>
<div class="control-group">
<%= f.label :timeslot, :class => 'control-label' %>
<div class="controls">
<%= collection_select(:arrangement, :timeslot_id, #available_timeslots, :id, :timeslot_spelled) %>
</div>
</div>
<% end %>
Controller
# GET /arrangements/new
# GET /arrangements/new.json
def new
date = Time.now.to_date.to_s(:db)
#arrangement = Arrangement.new
#available_timeslots = Timeslot.where("location_id = ? AND date(timeslot) = ? AND arrangement_id is null", current_user.user_details.location_id, date).order('timeslot ASC')
respond_to do |format|
format.html # new.html.erb
format.json { render json: #arrangement }
end
end
# POST /arrangements
# POST /arrangements.json
def create
#arrangement = Arrangement.new(params[:arrangement])
respond_to do |format|
if #arrangement.save
# update the timslot record with the arrangement id
if #timeslot = Timeslot.update(#arrangement.timeslot_id, :arrangement_id => #arrangement.id)
format.html { redirect_to #arrangement, notice: 'Arrangement was successfully created.' }
format.json { render json: #arrangement, status: :created, location: #arrangement }
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
end
end
The error given is referring to #available_timeslots being empty when trying to save the form
I would try something like this.
def new
#available_timeslots = ...
if #available_timeslots.count > 0
flash.now[:error] = "nil errrraaarrr"
end
...
end
In view
<div class="controls">
<%- if #available_timeslots.count > 0 %>
<%= collection_select(:arrangement, :timeslot_id, #available_timeslots, :id, :timeslot_spelled) %>
<% else %>
<%= flash.now[:error] %>
<% end %>
</div>
#available_timeslots is nil. Make sure it's set with an array of available timeslots to avoid this error message.
The trick was to add #available_timeslots = [] in the else clause
def create
#arrangement = Arrangement.new(params[:arrangement])
respond_to do |format|
if #arrangement.save
# update the timslot record with the arrangement id
if #timeslot = Timeslot.update(#arrangement.timeslot_id, :arrangement_id => #arrangement.id)
format.html { redirect_to #arrangement, notice: 'Arrangement was successfully created.' }
format.json { render json: #arrangement, status: :created, location: #arrangement }
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
end
end

Rails create form for model with many to many relation

I have two models, Recipe and Tag, with a has_and_belongs_to_many relation. For this relation I have a simple join table, RecipesTags.
Recipe:
has_and_belongs_to_many :tags
Tag:
has_and_belongs_to_many :recipes
Now upon creating a new recipe, the user gets to fill in which category the recipe belongs to in forms of checkboxes, like "Meat", "Fish", and so on. These categories are in fact just tags in the database.
Problem: the recipes doesn't get any tags saved to it.
Recipe new and create controller methods:
def new
#recipe = Recipe.new
#ingredients = Ingredient.all
#tags = Tag.all
respond_to do |format|
format.html # new.html.erb
format.json { render json: #recipe }
end
end
# POST /recipes
# POST /recipes.json
def create
#recipe = Recipe.new(params[:recipe])
if (params[:tags])
#recipe.tags << params[:tags]
end
respond_to do |format|
if #recipe.save
format.html { redirect_to #recipe, notice: 'Recipe was successfully created.' }
format.json { render json: #recipe, status: :created, location: #recipe }
else
format.html { render action: "new" }
format.json { render json: #recipe.errors, status: :unprocessable_entity }
end
end
end
The view:
<%= form_for(#recipe, :html => {:multipart => true}) do |f| %>
<% if #recipe.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
# [ fields that get's saved for the recipe and works fine ]
<% #tags.each do |t| %>
<%= f.label t.name %>
<%= f.check_box :tags, t.name %>
<br />
<% end %>
<%= f.submit 'Submit recipe', :class => 'btn btn-primary' %>
<% end %>
At the moment, I get an error message saying:
undefined method `merge' for "Meat":String
"Meat" is the tag name.
So, what am I doing wrong here?
I think the issue is this line #recipe.tags << params[:tags].
The association method you're calling with << takes an object (in this case expecting a tag object), but in this case it seems you might be passing it a string.
For more info this link may be helpful http://guides.rubyonrails.org/association_basics.html#has_and_belongs_to_many-association-reference, in particular where it refers to collection<<(object, …).
In your controller you'll want to do something like #recipe.tags << tag where tag is a specific tag object.
So, try this:
In your controller
params[:tags].each do |k,v|
#recipe.tags << Tag.find(k)
end
In your view
<% #tags.each do |t| %>
<%= f.label t.name %>
<%= f.check_box "tags[#{t.id}]" %>
<br />
<% end %>
Try this:
def create
#recipe = Recipe.new(params[:recipe])
params[:tags].each do |tag|
#recipe.tags << Tag.find_by_name(tag)
end
respond_to do |format|
if #recipe.save
format.html { redirect_to #recipe, notice: 'Recipe was successfully created.' }
format.json { render json: #recipe, status: :created, location: #recipe }
else
format.html { render action: "new" }
format.json { render json: #recipe.errors, status: :unprocessable_entity }
end
end
end
In view:
<% #tags.each do |t| %>
<%= label_tag t.name %>
<%= check_box_tag "tags[#{t.name}]", t.name %>
<br />
<% end %>

Rails 3.2 - Nested Resource Passing ID

Okay so my associations are:
Outlet -> has_many :monitorings
Monitoring -> belongs_to :outlet
My Routes:
resources :outlets do
resources :monitorings
end
View:
<%= link_to new_outlet_monitoring_path(#outlet) %>
When I click the link, the logs show that the outlet_id is passed as a parameter to the new page correctly.
But when saving the monitoring record, the outlet_id becomes nil.
Any help?
UPDATE:
# views/monitorings/_form.html.erb
<%= form_for(#monitoring) do |f| %>
<h2>Type of Monitoring</h2>
<fieldset data-role="controlgroup" >
<div class="radio-group">
<%= f.radio_button :mtype, "Full" %><%= f.label :mtype, "Full", value: "Full" %>
<%= f.radio_button :mtype, "Partial" %><%= f.label :mtype, "Partial", value: "Partial" %>
<%= f.radio_button :mtype, "None" %><%= f.label :mtype, "None", value: "None" %>
</div>
</fieldset>
<hr>
<%= f.submit "Next Step" %>
<% end %>
And the controller:
# controllers/monitoring_controller.rb
def new
#monitoring = Monitoring.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #monitoring }
end
end
def create
#monitoring = Monitoring.new(params[:monitoring])
respond_to do |format|
if #monitoring.save
format.html { redirect_to #monitoring, notice: 'Monitoring was successfully created.' }
format.json { render json: #monitoring, status: :created, location: #monitoring }
else
format.html { render action: "new" }
format.json { render json: #monitoring.errors, status: :unprocessable_entity }
end
end
end
This is most likely an issue with the way you are creating the new monitoring record. Can we see your form and your create controller action?

Resources