I have a project scaffold and stage scaffold. Project has many to one association with stage. Now I have created a task scaffold with many to one association with stage. but data from task form is not submitted to task table.
task form.html.erb:
<%= form_with model: [#project, #stage, #task] do |form| %>
<% if task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(task.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% task.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :task_name %>
<%= form.text_field :task_name %>
</div>
<div class="actions">
<%= form.submit 'Create', :class=>'button primary small' %>
</div>
<% end %>
tasks_controller.rb
def new
#task = #stage.tasks.build
end
def create
#project = Project.find(params[:project_id])
#task = #project.stages.build(task_params)
##task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
private
def set_task
#task = Task.find(params[:id])
end
def set_project
#project = Project.find(params[:project_id])
end
def set_stage
#stage = Stage.find(params[:stage_id])
end
def task_params
params.require(:task).permit(:task_name)
end
Ok, I see what's wrong. You have
#task = #project.stages.build(task_params)
so you're building Stage instead of Task instance here. What you actually need is:
#task = #stage.tasks.build(task_params)
I also encourage you to put some effort in actually understanding what you're doing here unless you want to ask a question on SO every half an hour of your development. ;)
It made me smile because as a new programmer, we tend to copy and paste but forget that unless we understand, we can't go that far :-)
Inside create method, in line: #project = Project.find(params[:project_id]) you are expecting params to have project_id but you have not passed it in the form and to pass it in form you need to have it in the first place in new action.
Do this:
def new
#task = #stage.tasks.build
#project = #stage.project
end
and then add this inside form:
<%= form.hidden_field :project_id, value: #project.id %>
Related
i created an edit page to edit the room(model) and update the form to change the current name and current capacity to whatever we wish but i am getting an error
ActionController::ParameterMissing in RoomsController#edit
param is missing or the value is empty: room
rooms_controller.rb
class RoomsController < ApplicationController
before_action :set_room, only: %i[show edit update]
def index
#rooms = Room.all
end
def show
end
def new
#room = Room.new
end
def create
#room = Room.new(room_params)
respond_to do |format|
if #room.save
format.html { redirect_to room_url(#room), notice: "Room was created Successfully" }
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
def edit
respond_to do |format|
if #room.update(room_params)
format.html { redirect_to room_url(#room), notice: "Room was successfully updated!" }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
private
def set_room
#room = Room.find(params[:id])
end
def room_params
params.require(:room).permit(:name, :capacity)
end
end
edit.hml.erb
<h2>Edit Room</h2>
<%= render "form", room: #room %>
_form.html.erb
<%= form_with(model: room) do |form| %>
<% if room.errors.any? %>
<div style="color: red">
<h2><%= pluralize(room.errors.count, "errors") %> Prohibited this Room from saving</h2>
<ul>
<% room.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= form.label :name, style: "display: block" %>
<%= form.text_field :name %>
</div>
<div>
<%= form.label :capacity, style: "display: block" %>
<%= form.number_field :capacity %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
i am using the same partial _form.html.erb for both new.html.erb and edit.html.erb , is it because of using same partial form for edit and new or there is some other reason?
new.html.erb
<h1>New Room</h1>
<%= render "form", room: #room %>
You're using the wrong action.
In Rails flavored REST the edit action responds to a GET /rooms/:id/edit request and just renders the form. It should also be idempotent. There is no room parameter since you're not responding to a form submission.
Updating the resource is done in the update method (PATCH /rooms/:id).
class RoomsController < ApplicationController
# ...
# you can actually completely omit this method
# Rails will implicitly render edit.html.erb anyways
# GET /rooms/1/edit
def edit
end
# PATCH /rooms/1
def update
# you don't need to use MimeResponds if you're only responding to HTML requests. KISS
if #room.update(room_params)
redirect_to #room, notice: "Room was successfully updated!"
else
render :edit, status: :unprocessable_entity
end
end
# ...
end
I'd like to automatically associate a new database entry with the database entry it belongs to without having to make a choice while on the form as the user can only come from the category page, so that once you're in a category and you decide to make a new entry within that category, the newly created entry is automatically within that category upon submission. Can anyone offer any help?
My models are as follows:
class Category < ActiveRecord::Base
has_many :guides
end
class Guide < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :ratings
def average_rating
average = ratings.inject(0.0){ |sum, el| sum + el.value }.to_f / ratings.size
average.round(2)
end
end
The link to create the new guide for the category is pretty standard, though I thought that adding an instance variable might automatically associate the entry with the category though it doesn't:
<%= link_to 'New Guide', new_guide_path(#category) %>
Here is the controller for the guide:
class GuidesController < ApplicationController
before_action :set_guide, only: [:show, :edit, :update, :destroy]
# GET /guides
# GET /guides.json
def index
#guides = Guide.all
end
# GET /guides/1
# GET /guides/1.json
def show
end
# GET /guides/new
def new
#guide = Guide.new
end
# GET /guides/1/edit
def edit
end
# POST /guides
# POST /guides.json
def create
#guide = Guide.new(guide_params)
respond_to do |format|
if #guide.save
format.html { redirect_to #guide, notice: 'Guide was successfully created.' }
format.json { render :show, status: :created, location: #guide }
else
format.html { render :new }
format.json { render json: #guide.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /guides/1
# PATCH/PUT /guides/1.json
def update
respond_to do |format|
if #guide.update(guide_params)
format.html { redirect_to #guide, notice: 'Guide was successfully updated.' }
format.json { render :show, status: :ok, location: #guide }
else
format.html { render :edit }
format.json { render json: #guide.errors, status: :unprocessable_entity }
end
end
end
# DELETE /guides/1
# DELETE /guides/1.json
def destroy
#guide.destroy
respond_to do |format|
format.html { redirect_to guides_url, notice: 'Guide was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_guide
#guide = Guide.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def guide_params
params.require(:guide).permit(:name, :category_id, :user_id, :stepOneText, :stepOnePhoto, :stepTwoText, :stepTwoPhoto, :stepThreeText, :stepThreePhoto)
end
end
Form is pretty standard too, is there anything I should put in here to automatically assign it to the category entry it belongs to?
<%= form_for(#guide) do |f| %>
<% if #guide.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#guide.errors.count, "error") %> prohibited this guide from being saved:</h2>
<ul>
<% #guide.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :stepOneText %>
<%= f.text_field :stepOneText %>
</div>
<div class="field">
<%= f.label :stepOnePhoto %>
<%= f.text_field :stepOnePhoto %>
</div>
<div class="field">
<%= f.label :stepTwoText %>
<%= f.text_field :stepTwoText %>
</div>
<div class="field">
<%= f.label :stepTwoPhoto %>
<%= f.text_field :stepTwoPhoto %>
</div>
<div class="field">
<%= f.label :stepThreeText %>
<%= f.text_field :stepThreeText %>
</div>
<div class="field">
<%= f.label :stepThreePhoto %>
<%= f.text_field :stepThreePhoto %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Seems to me that you could go for something like a nested route here :
resources :categories do
resources :guides
end
and then use your new route
<%= link_to 'New Guide', new_category_guide_path(#category) %>
This should make it easier to get the guide's category back when getting the form back.
Assuming that you have a column on your guide table that stores category ID, and your routes are nested as has been recommended, you should be able to add
#guide.category_id = #category.id
To your guides controller create action. And in your form change the first line to
<%= form_for[#category, #guide] do |f| %>
Now this should work
<%= link_to 'new guide', new_category_guide_path(#category) %>
And the current category should be assigned to your guide when it's created.
This is just a general question about the helper "form_for". I'm working on a program out of a textbook which has a form file using <%= form_for(#product) do |f| %>. The form is shared by the new and edit template. However, I've seen a lot of tutorials using a symbol (:product) instead of the instance variable. So, I tried swapping them to see what would happen. As it happens it gives me a routing error when trying to submit a form:
No route matches [POST] "/products/new"
and
No route matches [POST] "/products/5/edit"
Here's the code:
<%= form_for(:product) do |f| %>
<% if #product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% #product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :price %><br>
<%= f.text_field :price %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and in the product_controller
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
I thought I had read that "form_for :product" would search for an instance variable of the same name and use the same route, product_path, but it seems I was mistaken. I've looked at other posts on this site, but they don't seem to mention the routes. Why I'm getting this error?
EDIT: I added the option "url: products_path" to the form_for :product line and it works now. I'm guessing the symbol doesn't know to use the routes in resources like #product does?
If you have a routing error, please check the file confg/routes.rb it must include resources :products. If not, add it and restart the server.
And yes at routes we use a symbol with the table name (plural of model) for define resources.
edited:
With form_for use an instance variable: #product that was initialized on controller with an empty new product, or the finded product to update.
I have 2 models Event and Tasks.
Event has many tasks. and task is a nested resource under event
so I first create a event and ask a user how many tasks it wants to create in it.
Let say I create a Event and a user wants to create 3 tasks in it. I want to do it in 2 steps and not one
After successful creation of event,now I go to /events/1/tasks/new
here I want to have 3 task name fields and when the user submits it, there should be 3 rows created in Task table against the Event 1
How do I achieve this
So here is the task _form.html.erb
<%= form_for [#event, #task] do |f| %>
<% if #task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#task.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% #task.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Task controller
def new
#event=Event.find(params[:event_id])
#event.task_count do
#choice = #event.tasks.build
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #task }
end
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(params[:task])
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
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
I think you are making this more complicated by involving the tasks controller. Controllers direct actions in the web application. But by your description you seem to be wanting to have 3 tasks auto created when the event is created (if I'm understanding you correctly). Other than entering the initial names this doesn't really involve the user.
Have them submit the names and when the events controller creates the event it should create the tasks there.
If your nested resource is more complicated it is a job for nested forms. You might benefit from this screencast:
http://railscasts.com/episodes/196-nested-model-form-part-1
First you intilized 3 task aginst one eveent in this way
def new
#event=Event.find(params[:event_id])
3.times{#event.tasks.build}
respond_to do |format|
format.html # new.html.erb
format.json { render json: #task }
end
end
Then it will be surely create 3 task against 1 event.or you can help from ryan rails cast for nested forms also
I don't know if I am doing this in a wrong way but here is it.
I have 2 models Event and Tasks.
Event has many tasks. and task is a nested resource under event
so I first create a event and ask a user how many tasks it wants to create in it.
Let say I create a Event and a user wants to create 3 tasks in it. I want to do it in 2 steps and not one
After successful creation of event,now I go to /events/1/tasks/new
here I want to have 3 task name fields and when the user submits it, there should be 3 rows created in Task table against the Event 1
How do I achieve this
So here is the task _form.html.erb
<%= form_for [#event, #task] do |f| %>
<% if #task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#task.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% #task.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Task controller
def new
#event=Event.find(params[:event_id])
#event.task_count do
#choice = #event.tasks.build
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #task }
end
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(params[:task])
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
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
You can try like this
def new
#event=Event.find(params[:event_id])
3.times {#event.tasks.build}
respond_to do |format|
format.html # new.html.erb
format.json { render json: #task }
end
end