Rails creating more than one row from a single form - ruby-on-rails

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

Related

Creating new object with has_and_belongs_to_many association

My rails project consists of three models: User, Groups and Transactions. Groups and Transactions are connected by a has_and_belongs_to_many relationship and both belong to User. I'm trying to implement a feature where you can add new transactions on a groups' show page that will automatically be associated with the show pages' group. I've tried the following but in the transactions controller rails doesn't get which group the transaction is supposed to be associated with.
Groups' show page:
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #group.name %>
<% #group.deals.each do |deal| %>
<%= deal.name %>
<%= deal.user.name %>
<%= link_to 'Show', deal %>
<% end %>
</p>
<%= link_to 'Edit', edit_group_path(#group) %> |
<%= link_to 'Back', groups_path %>
<%= link_to 'New Transaction', new_transaction_path(#group) %> |
Group's controller page:
# GET /transactions/new
def new
#transaction = Transaction.new
end
# POST /transactions or /transactions.json
def create
#transaction = Transaction.new(transaction_params.merge(user_id: current_user.id))
respond_to do |format|
if #transaction.save
format.html { redirect_to #transaction, notice: "Transaction was successfully created." }
format.json { render :show, status: :created, location: #transaction }
#transaction.groups << #group
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
If I replace #group with f.e. Group.first the association is created - it's the wrong one in most cases ofc tho. Does the solution lie within in the views maybe, can anyone help out?

not able to set data into database in rails

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 %>

Does rails form_for use the same route when using a symbol or instance var?

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.

(Rails) I have 2 models, Area (parent) & RadioStation (child). How might I pull an Area object's name in a Station form using an :area_id foreign key?

I have two "CRUD" forms generated by the "rails g scaffold ModelName type:attribute1, type2:attribute2" command, which is quite powerful.
I'll try to just show what is relevant. First here are my models (attr_accessible tells the db migration stories for the most part)
class Area < ActiveRecord::Base
attr_accessible :description, :frequency, :name, :area_id
has_many :stations
end
class Station < ActiveRecord::Base
attr_accessible :description, :frequency, :name, :area_id
belongs_to :area
end
Next, here is the _form.html.erb for a Station object (currently I'm using a simple drop down which is OK, but I want those :area_id tags to somehow be able to pull the Area.find(params[:area_id]).name, or something like that. If '1' is Denver and '2' is Boulder, I want '1` to pull 'Denver' and so on on the Station _form.
So here is stations_controller.rb, which was generated by the "generate scaffold" command for the most part.
class StationsController < ApplicationController
def index
#stations = Station.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #stations }
end
end
def show
#station = Station.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #station }
end
end
def new
#area_count = Area.count
#station = Station.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #station }
end
end
def edit
#station = Station.find(params[:id])
end
def create
#station = Station.new(params[:station])
respond_to do |format|
if #station.save
format.html { redirect_to #station, notice: 'Station was successfully created.' }
format.json { render json: #station, status: :created, location: #station }
else
format.html { render action: "new" }
format.json { render json: #station.errors, status: :unprocessable_entity }
end
end
end
def update
#station = Station.find(params[:id])
respond_to do |format|
if #station.update_attributes(params[:station])
format.html { redirect_to #station, notice: 'Station was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #station.errors, status: :unprocessable_entity }
end
end
end
def destroy
#station = Station.find(params[:id])
#station.destroy
respond_to do |format|
format.html { redirect_to stations_url }
format.json { head :no_content }
end
end
end
Lastly, here is the _form.html.erb for Station
<%= form_for(#station) do |f| %>
<% if #station.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#station.errors.count, "error") %> prohibited this station from being saved:</h2>
<ul>
<% #station.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :frequency %><br />
<%= f.text_field :frequency %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :area_id %><br />
<%= f.select(:area_id, 1..#area_count) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
So to reiterate my goal/question, what I have currently for the :area_id selector is a dropdown bar which allows me to select from 1.."Area.count". I would like that drop down bar to list the names of the the different areas given the area_id.
Also, I'd like to be able to see a list of Station objects which are "owned" by a given area on the list of areas or perhaps just on the show.html.erb for a given Area.
For the select box:
You should use the collection_select form helper.
Replace
<%= f.select(:area_id, 1..#area_count) %>
With
<%= f.collection_select :area_id, Area.all, :id, :name %>
For showing the list of stations on the show view of an area:
There are several ways to do this, depending on how you want to display them in the HTML.
Here's one way to obtain a comma separated list of the station names:
<%= #area.stations.pluck(:name).join(", ") %>
If you need additional attributes of the stations besides just :name, you could iterate over the collection rather than using pluck:
<ul>
<% #area.stations.each do |s| %>
<li><%= s.name %> - <%= s.frequency %></li>
<% end %>
</ul>

Ruby on Rails update model with more than one row in a single form

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

Resources