I have two models, Roaster and Roast
I want to have the user select the value of :roaster in the new roast form, from the Roaster model. I am using a collection_select which displays the list of roasters in the dropdown ok, but it doesn't insert the value into the table. From the console, it actually looks like it's trying to pass the roaster_id
"roast"=>{"roaster_id"=>"1", "name"=>"Rugby", "beans"=>"", "countries_attributes"=>{"0"=>{"country_name"=>"", "regions_attributes"=>{"0"=>{"region_name"=>""}}}, "1"=>{"country_name"=>"", "regions_attributes"=>{"0"=>{"region_name"=>""}}}, "2"=>{"country_name"=>"", "regions_attributes"=>{"0"=>{"region_name"=>""}}}}, "bestfor"=>"", "roast"=>"", "tastingnotes"=>""}, "commit"=>"Create Roast"}
My select:
<%= form.collection_select(:roaster_id, Roaster.all, :id, :roaster_name, :prompt => 'Select Roaster') %>
I've tried
<%= form.collection_select(:roaster_name, Roaster.all, :id, :roaster_name, :prompt => 'Select Roaster') %>
but this gives and undefined method error.
My roast_params
params.require(:roast).permit(:roaster, :roaster_id, :name, :bestfor, :beans, :roast, :tastingnotes, :notes, :slug, :avatar, countries_attributes: [:country_id, :country_name, regions_attributes: [:id, :region_name]])
Adding in :roaster_name doesn't solve either.
As requested full form:
<%= form_with(model: roast, local: true, multipart: true) do |form| %>
<% if roast.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger" role="alert">
<h2><%= pluralize(roast.errors.count, "error") %> prohibited this roast from being saved:</h2>
<ul>
<% roast.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
<form>
<div class="row">
<div class="col-6">
<div class="field form-group">
<%= form.label :roaster, class: 'control-label' %>
<%= form.collection_select(:roaster_id, Roaster.all, :id, :roaster_name, :prompt => 'Select Roaster') %>
</div>
</div>
<div class="col-6">
<div class="form-group">
<%= form.label :name, class: 'control-label' %>
<%= form.text_field :name, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<%= form.label :beans, "Blend", class: 'control-label' %><br />
<%= form.select :beans, [ 'Single Origin','Two Country Blend', 'Three Country Blend' ], :prompt => 'Select One', id: :roast_beans, class: "form-control" %>
</div>
<div class="row">
<%= form.fields_for :countries do |countries_form| %>
<div class="col-6">
<div class="form-group">
<%= countries_form.label :country %>
<%= countries_form.text_field :country_name, class: "form-control" %>
</div>
</div>
<div class="col-6">
<!-- note the appending of `countries_` to form.fields to allow for deeper nested to work-->
<%= countries_form.fields_for :regions do |regions_form| %>
<%= regions_form.label :region %>
<%= regions_form.text_field :region_name, class: "form-control" %>
<% end %>
<br />
</div>
<% end %>
</div>
<div class="form-group">
<%= form.label :bestfor, "Style", class: 'control-label' %><br />
<%= form.select :bestfor, [ 'Espresso','Filter' ], :prompt => 'Select One', id: :roast_bestfor, class: "form-control" %>
</div>
<div class="form-group">
<%= form.label :roast, "Strength", class: 'control-label' %><br />
<%= form.select :roast, [ 'Light','Medium','Dark' ], :prompt => 'Select One', id: :roast_roast, class: "form-control" %>
</div>
<div class="form-group">
<%= form.label :tastingnotes, "Tasting Notes (separate with commas, e.g chocolate, citrus)", class: 'control-label' %><br />
<%= form.text_area :tastingnotes, id: :roast_tastingnotes, class: "form-control" %>
</div>
<br />
<div class="form-group">
<%= form.label :avatar, "Upload image...", class: 'control-label' %>
<%= form.file_field :avatar %>
</div>
<div class="actions">
<%= form.submit class: "btn btn-success" %> <%= link_to "Cancel", "/roasts", class: "btn btn-secondary"%>
</div>
<% end %>
</form>
roast_controller.rb
class RoastsController < ApplicationController
before_action :set_roast, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:create, :edit, :update, :destroy]
before_action :set_search
# GET /roasts
# GET /roasts.json
def index
#q = Roast.ransack(params[:q])
#roastsalpha = #q.result.order(:name)
#roastcount = Roast.count(:country)
#roasts = Roast.order(:name).count
#countroastschart = Roast.order("roaster DESC").all
end
# GET /roasts/1
# GET /roasts/1.json
def show
#roast = Roast.friendly.find(params[:id])
#commentable = #roast
#comments = #commentable.comments
#comment = Comment.new
#sameroaster = Roast.where(roaster: #roast.roaster)
#samecountry = Roast.where(country: #roast.country)
#roastcount = Roast.where(roaster: #roast.roaster)
end
# GET /roasts/new
def new
#roast = Roast.new
3.times {#roast.countries.build.regions.build}
end
# GET /roasts/1/edit
def edit
3.times {#roast.countries.build.regions.build}
end
# POST /roasts
# POST /roasts.json
def create
#roast = Roast.new(roast_params)
respond_to do |format|
if #roast.save
format.html { redirect_to #roast, notice: 'Roast was successfully created.' }
format.json { render :show, status: :created, location: #roast }
else
format.html { render :new }
format.json { render json: #roast.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /roasts/1
# PATCH/PUT /roasts/1.json
def update
respond_to do |format|
if #roast.update(roast_params)
format.html { redirect_to #roast, notice: 'Roast was successfully updated.' }
format.json { render :show, status: :ok, location: #roast }
else
format.html { render :edit }
format.json { render json: #roast.errors, status: :unprocessable_entity }
end
end
end
# DELETE /roasts/1
# DELETE /roasts/1.json
def destroy
#roast.destroy
respond_to do |format|
format.html { redirect_to roasts_url, notice: 'Roast was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_roast
#roast = Roast.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def roast_params
params.require(:roast).permit(:roaster, :roaster_id, :name, :bestfor, :beans, :roast, :tastingnotes, :notes, :slug, :avatar, countries_attributes: [:country_id, :country_name, regions_attributes: [:id, :region_name]])
end
end
I think you are doing many wrong things. By looking your other questions I saw your models. I put some important things:
class Roast < ApplicationRecord
has_many :countries
accepts_nested_attributes_for :countries
end
class Country < ApplicationRecord
has_many :regions, inverse_of: :country
accepts_nested_attributes_for :regions
belongs_to :roast
end
class Region < ApplicationRecord
belongs_to :country, inverse_of: :regions
end
In these models I didn't see the Roaster. I assume a Roast belongs_to :roaster.
So: your Roast has many countries and each country has many regions. But you are passing country names and region names in your view to the create controller. You need to pass the ids, so that you save references to these models.
You have many unnecessary field in params, and some missing ones. This is how it should be:
def roaster_params
params.require(:roast).permit(:roaster_id, :name, :bestfor, :beans, :tastingnotes, :notes, :slug, :avatar, countries_attributes: [:id, regions_attributes: [:id]])
end
You don't need roast, roaster, country_name, region_name. You need the id of the country (and not the country_id), and the id of the region (and not the region_id)
In your form you should ask for country and region ids:
<%= countries_form.collection_select(:id, Country.all, :id, :name, :prompt => 'Select Country') %>
<%= regions_form.collection_select(:id, Region.all, :id, :name, :prompt => 'Select Region') %>
In fact this is more difficult, because a region belongs to a country, but here you are showing all regions. You should only show regions for the selected country (which is dynamic).
Related
My model/id/edit form is rendered blank, without rendering the values that are already in the database. I don't see this is the regular behaviour in a brand new rails app.
Any insights what's blocking those values to be rendered in the form?
Rails 6.1.4
ruby 2.7.3p183
_form.html.erb
<%= form_with(model: task) do |form| %>
<%= render "shared/error_messages", resource: form.object %>
<div class="form-group">
<%= form.label :title %>
<%= form.text_field :title, class: "form-control", prepopulated: "true", :value => params[:title] %>
</div>
<div class="form-group">
<%= form.label :description %>
<%= form.rich_text_area :description, data: { controller: "mentions", mentions_target: "field" }, class: "form-control", :value => params[:description] %>
</div>
<div class="form-group">
<%= form.label :credits %>
<%= form.number_field :credits, class: "form-control", :value => params[:credits] %>
</div>
<div class="form-group">
<%= form.label :category %>
<%= form.select :category, [ 'Development', 'Design' ], class: "form-control", :value => params[:category] %>
</div>
<% if current_user.admin === true %>
<%= form.collection_check_boxes(:user_ids, User.where(id: 1).all, :id, :name) do |u| %>
<%= u.label(class: "check_box") { u.check_box(checked: true, class: "add_margin") + u.text } %>
<% end %>
<% end %>
<div class="flex justify-between form-group">
<%= form.button class: "btn btn-primary" %>
<% if form.object.persisted? %>
<%= link_to t("delete"), form.object, class: "btn btn-danger outline", method: :delete, data: { confirm: t("are_you_sure") } %>
<% end %>
</div>
<% end %>
Controller
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :load_entities, only: :show
# GET /tasks/1/edit
def edit
end
# PATCH/PUT /tasks/1 or /tasks/1.json
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to #task, notice: "Task was successfully updated." }
format.json { render :show, status: :ok, location: #task }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
puts #task
puts #task.id
end
# Only allow a list of trusted parameters through.
def task_params
params.require(:task).permit(:title, :description, :credits, :deliverydate, :submitteddate, :createdby, :default, :status, :category, :assignedto, user_ids: [])
end
end
Edit:
Adding trace for set_task , example when opening the Edit form for Task ID 7
10:30:24 web.1 | ↳ app/controllers/tasks_controller.rb:91:in `set_task'
10:30:24 web.1 | #<Task:0x000000010d75ddf8>
10:30:24 web.1 | 7
10:30:24 web.1 | Rendering layout layouts/application.html.erb
I am currently trying to fix the relationship between delivery, delivery_orders and orders model. I've been trying all day to save a nested form that stores the orders inside of the delivery_orders table. Essentially, I want to be able to create deliveries, and then add orders to the deliveries through the delivery_order model. Normal users create orders, but Managers handle deliveries for those orders. So far, I've been unable to save the nested simple_form_for section for delivery_order model. It keep returning nil, even though the relationship is setup to support the transaction. One side note, I am unable to read the attributes of the orders through the delivery model. The code that I wrote is below. Structure User -> Order -> Manager Delivery[Delivery_order] -> Truck[Delivery]
delivery.rb
class Delivery < ApplicationRecord
belongs_to :warehouse, optional: true
belongs_to :truck, optional: true
has_one :delivery_order
has_one :order_tracker
has_many :breads
#after_create :decrement_bread_stock
accepts_nested_attributes_for :delivery_order
end
deliveryorder.rb
class DeliveryOrder < ApplicationRecord
has_many :orders, inverse_of: :delivery_order
belongs_to :delivery, optional: true
end
order.rb
class Order < ApplicationRecord
belongs_to :client, :dependent => :destroy, optional: true
belongs_to :delivery_order, optional: true
has_one :bread
has_one :order_tracker, :dependent => :destroy
after_create :build_order_tracker
geocoded_by :address, :latitude => :lat, :longitude => :lon
after_validation :geocode, if: ->(obj) {obj.client_address.present? && obj.client_address_changed?}
def address
[client_address, client_state].compact.join(', ')
end
end
deliveries_controller.rb
class DeliveriesController < ApplicationController
before_action :set_delivery, only: %i[show edit update destroy]
# GET /deliveries
# GET /deliveries.json
def index
#deliveries = Delivery.all
end
# GET /deliveries/1
# GET /deliveries/1.json
def show; end
# GET /deliveries/new
def new
#delivery = Delivery.new
#delivery.build_delivery_order
#delivery_orders = Order.all
end
# GET /deliveries/1/edit
def edit; end
# POST /deliveries
# POST /deliveries.json
def create
#delivery = current_manager.warehouse.deliveries.build(delivery_params)
respond_to do |format|
if #delivery.save
format.html { redirect_to #delivery, notice: 'Delivery was successfully created.' }
format.json { render :show, status: :created, location: #delivery }
else
format.html { render :new }
format.json { render json: #delivery.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /deliveries/1
# PATCH/PUT /deliveries/1.json
def update
respond_to do |format|
if #delivery.update(delivery_params)
format.html { redirect_to #delivery, notice: 'Delivery was successfully updated.' }
format.json { render :show, status: :ok, location: #delivery }
else
format.html { render :edit }
format.json { render json: #delivery.errors, status: :unprocessable_entity }
end
end
end
# DELETE /deliveries/1
# DELETE /deliveries/1.json
def destroy
#delivery.destroy
respond_to do |format|
format.html { redirect_to deliveries_url, notice: 'Delivery was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_delivery
#delivery = Delivery.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def delivery_params
params.require(:delivery).permit(:delivery_date, :delivery_on_time, delivery_order_attributes: %i[order_1 order_2 order_3 order_4 delivery_id order_id], orders_attributes: [:order_id])
end
end
delivery _form.html.erb
<div class="container">
<%= simple_form_for(#delivery) do |f| %>
<%= f.error_notification %>
<div class="form-group">
<label>Estimated Delivery Date</label>
<%= f.input :delivery_date, class: 'form-control', label: false %>
</div>
<%= simple_fields_for :delivery_order, #delivery.delivery_order do |d| %>
<div class="form-control">
<label>Delivery Order 1</label>
<%= d.input :order_1, collection: #delivery_orders, :label_method => lambda {|order| "Order Id: #{order.id} | Client Name: #{order.client_name} | Client Address: #{order.client_address} | Bread Type: #{order.bread_type} | Bread Quantity: #{order.bread_quantity}" }, value_method: :id, include_blank: false, prompt: 'Add your first order to the delivery', class: 'form-control', label: false %>
</div>
<div class="form-group">
<label>Delivery Order 2</label>
<%= d.input :order_2, collection: #delivery_orders, :label_method => lambda {|order| "Order Id: #{order.id} | Client Name: #{order.client_name} | Client Address: #{order.client_address} | Bread Type: #{order.bread_type} | Bread Quantity: #{order.bread_quantity}" }, value_method: :id, include_blank: false, prompt: 'Add your second order to the delivery', class: 'form-control', label: false %>
</div>
<div class="form-group">
<label>Delivery Order 3</label>
<%= d.input :order_3, collection: #delivery_orders, :label_method => lambda {|order| "Order Id: #{order.id} | Client Name: #{order.client_name} | Client Address: #{order.client_address} | Bread Type: #{order.bread_type} | Bread Quantity: #{order.bread_quantity}" }, value_method: :id, include_blank: false, prompt: 'Add your third order to the delivery', class: 'form-control', label: false %>
</div>
<div class="form-group">
<label>Delivery Order 4</label>
<%= d.input :order_4, collection: #delivery_orders, :label_method => lambda {|order| "Order Id: #{order.id} | Client Name: #{order.client_name} | Client Address: #{order.client_address} | Bread Type: #{order.bread_type} | Bread Quantity: #{order.bread_quantity}" }, value_method: :id, include_blank: false, prompt: 'Add your fourth order to the delivery', class: 'form-control', label: false %>
</div>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
</div>
orders _form.html.erb
<%= simple_form_for(#order) do |f| %>
<%= f.error_notification %>
<div class="form-group">
<label>Name</label>
<%= f.input :client_name, required: true, label: false, class: 'form-control' %>
</div>
<div class="form-group">
<label>Zip Code</label>
<%= f.input :client_zip_code, required: true, label: false, class: 'form-control' %>
</div>
<div class="form-group">
<label>Address</label>
<%= f.input :client_address, required: true, label: false, class: 'form-control' %>
</div>
<div class="form-group">
<label>State</label>
<%= f.input :client_state, required: true, label: false, class: 'form-control' %>
</div>
<div class="form-group">
<label>Choose a Bread</label>
<%= f.collection_select :bread_name, collection: Bread.all, required: true, label: false, class: 'form-control' %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
trucks_controller.rb
class TrucksController < ApplicationController
before_action :set_truck, only: %i[show edit update destroy]
before_action :authenticate_manager!
# GET /trucks
# GET /trucks.json
def index
#trucks = Truck.all
end
# GET /trucks/1
# GET /trucks/1.json
def show;
end
# GET /trucks/new
def new
#truck = Truck.new
#deliveries = Delivery.all
end
# GET /trucks/1/edit
def edit;
end
# POST /trucks
# POST /trucks.json
def create
#truck = current_manager.warehouse.trucks.build(truck_params)
respond_to do |format|
if #truck.save
format.html {redirect_to #truck, notice: 'Truck was successfully created.'}
format.json {render :show, status: :created, location: #truck}
else
format.html {render :new}
format.json {render json: #truck.errors, status: :unprocessable_entity}
end
end
end
# PATCH/PUT /trucks/1
# PATCH/PUT /trucks/1.json
def update
respond_to do |format|
if #truck.update(truck_params)
format.html {redirect_to #truck, notice: 'Truck was successfully updated.'}
format.json {render :show, status: :ok, location: #truck}
else
format.html {render :edit}
format.json {render json: #truck.errors, status: :unprocessable_entity}
end
end
end
# DELETE /trucks/1
# DELETE /trucks/1.json
def destroy
#truck.destroy
respond_to do |format|
format.html {redirect_to trucks_url, notice: 'Truck was successfully destroyed.'}
format.json {head :no_content}
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_truck
#truck = Truck.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def truck_params
params.require(:truck).permit(:delivery_total, :lon, :lat, :delivery_id, :loaded_date, :truck_driver_name, :current_street_address, :current_city, :current_state, :current_country)
end
end
truck.rb
class Truck < ApplicationRecord
belongs_to :warehouse, optional: true
has_many :deliveries
end
trucks _form.html.erb
<div class="container">
<%= simple_form_for(#truck) do |f| %>
<%= f.error_notification %>
<div class="form-group">
<div class="col-3">
<label>Loaded Date (Click Box Below)</label>
<%= f.input :loaded_date, as: :date_time_picker, class: 'form-control', placeholder: "Tap to view calendar <i class: 'fa fa-hand-o-up'></i>", label: false %>
</div>
</div>
<div class="form-group">
<div class="col-5">
<%= f.input :delivery_total, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-5">
<%= f.input :truck_driver_name, class: 'form-control btn btn-outline-primary' %>
</div>
</div>
<div class="form-group">
<div class="col-5">
<%= f.input :current_street_address, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-5">
<%= f.input :current_city, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-5">
<%= f.input :current_state, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-5">
<%= f.input :current_country, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-5">
<%= f.input :delivery_id, collection: #deliveries, :label_method => lambda {|delivery| "Estimated Delivery Date: #{delivery.delivery_date} | Order Id: #{delivery.id}"}, value_method: :id, label: "Delivery Jobs", include_blank: false, prompt: 'Add a delivery to the truck' %>
</div>
</div>
<div class="form-actions">
<%= f.button :submit, class: 'btn btn-outline-success' %>
</div>
<% end %>
</div>
I'm trying to create a record in a join table named Interventions. Basically in my application a user can do many interventions on an incident, and an incident can have interventions by many users. I pass the needed strong parameters, but the application gives the following errors when I try to save: "Incident must exist" and "User must exist". I spent hours on this, and can't figure out what is the problem. Can you please help me? I post the relevant code here:
user.rb (model)
has_many :interventions
has_many :incidents, through: :interventions
incident.rb (model)
has_many :interventions
has_many :users, through: :interventions
intervention.rb (model)
belongs_to :incident_priority
belongs_to :intervention_status
interventions_controller.rb
def new
#incident = Incident.find(params[:incident])
#user = User.find(current_user.id)
#intervention = Intervention.new(:user_id => #user, :incident_id => #incident)
#project = #incident.channel.project
#mirth = Mirth.find_by server_id: #incident.mirth_server_id
end
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
#intervention = Intervention.create(intervention_params)
#project = #incident.channel.project
#mirth = Mirth.find_by server_id: #incident.mirth_server_id
respond_to do |format|
if #intervention.save
format.html { redirect_to new_intervention_path(#incident), notice: 'Intervention was successfully created.' }
format.json { render :show, status: :created, location: #intervention }
else
format.html { render :new, incident: :incident_id }
format.json { render json: #intervention.errors, status: :unprocessable_entity }
end
end
end
< .... >
def intervention_params
params.require(:intervention).permit(:user_id, :incident_id, :incident_priority_id, :begin_date, :end_date, :description,
:intervention_status_id, :forwarded_to)
end
In my view (interventions_form.html.erb):
<%= form_for(#intervention) do |f| %>
<% if #intervention.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#intervention.errors.count, "error") %> prohibited this intervention from being saved:</h2>
<ul>
<% #intervention.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group form-inline">
<%= hidden_field_tag :user_id, #user.id %>
<%= hidden_field_tag :incident_id, #incident.id %>
<strong>Interveniente:</strong>
<%= #user.first_name %> <%= #user.last_name %>
</div>
<div class="form-group form-inline">
<%= f.label 'Prioridade' %>
<%= f.collection_select :incident_priority_id, IncidentPriority.all, :id, :description, {}, {class: "form-control"} %>
</div>
<div class="form-group form-inline">
<%= f.label 'Data início intervenção' %>
<%= f.datetime_select :begin_date %>
</div>
<div class="form-group form-inline">
<%= f.label 'Data fim intervenção' %>
<%= f.datetime_select :end_date, :include_blank => true %>
</div>
<div class="form-group form-inline">
<%= f.label 'Observações' %>
<%= f.text_area :description %>
</div>
<div class="form-group form-inline">
<%= f.label 'Estado' %>
<%= f.collection_select :intervention_status_id, InterventionStatus.all, :id, :description, {}, {class: "form-control"} %>
</div>
<div class="form-group form-inline">
<%= f.label 'Encaminhado para:' %>
<%= f.text_area :forwarded_to %>
</div>
<div class="actions" align="right">
<%= link_to 'Voltar', incidents_path(:mirth => #mirth, :project => #project), class: "btn btn-info" %>
<%= f.submit "Gravar", class: "btn btn-info" %>
</div>
I run debug and the values in the hidden_field_tags are correctly filled. Also in the controller the #user and #incident are correctly populated, but #intervention has nil in the foreign keys :user_id and :incident_id.
Thanks in advance!
You need to associate the user and the incident with the intervention.
in your model...
class Intervention
belongs_to :user
belongs_to :incident
in your create method...
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
#intervention = Intervention.create(intervention_params)
#intervention.incident = #incident
#intervention.user = #user
...
You need to change this:
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
# ...
end
For this:
def create
#incident = Incident.find(params[:incident_id])
#user = User.find(params[:user_id])
intervention_params.merge(user_id: #user.id, incident_id: #incident.id)
# ...
end
And your model:
class Intervention
belongs_to :user
belongs_to :incident
This is my first time with Cocoon, and maybe this is a really dumb question, but I already spend many time looking how to do this with ERB template and avoid using simple_form or other helper.
Take a look of my models:
models/loot.rb
class Lot < ActiveRecord::Base
has_many :colindanciums, dependent: :destroy
has_many :cardinal_points, through: :colindanciums
accepts_nested_attributes_for :colindanciums, allow_destroy: true
end
models/colindancium.rb
class Colindancium < ActiveRecord::Base
belongs_to :cardinal_poing
belongs_to :lot
end
models/cardinal_point.rb
class CardinalPoint < ActiveRecord::Base
has_many :colindanciums
has_many :lots, through: :colindanciums
end
The form:
views/lots/_form.html.erb
<%= form_for(#lot, remote: true) do |f| %>
<%= render 'shared/error_messages', object: #lot %>
...
...
...
<fieldset id="colindancium-orientation">
<ol>
<%= f.fields_for :colindanciums do |colindancium| %>
<%= render 'colindancium_fields', f: colindancium %>
<% end %>
</ol>
<%= link_to_add_association 'Nueva Colindancia', f, :colindanciums, 'data-association-insertion-node' => "#colindancium-orientation ol", 'data-association-insertion-method' => "append" %>
</fieldset>
...
...
...
<% end %>
The partial:
views/lots/_colindancium_fields.html.erb
<li class="control-group nested-fields">
<div class="controls">
<%= f.label :description, "Descripcion:" %>
<%= f.text_field :description %>
<%= f.label :linear_meters, "Metros Lineales:" %>
<%= f.text_field :linear_meters %>
<%= f.label :cardinal_point_id, "Orientacion:" %>
<%= f.select :cardinal_point_id,
options_from_collection_for_select(CardinalPoint.all, :id, :name), { }, { :class => "form-control", :prompt => "Seleccione un Punto Cardinal" } %>
<%= link_to_remove_association "Eliminar", f %>
</div>
</li>
Everything works great when I insert new fields, it saves it in DB, it Update it in DB, my problem is in the options_from_collection_for_select when I open the form in Edit Action, the fourth parameter of this helper is the selected value... I can't find the way to make selected the value that is stored in my db, it always show the 1 index... I can't access the #... object from the _form, the other fields (:description, :linear_meters) are working quite good my problem is in the f.select, I don't know how to do it.
EDIT My controller:
# GET /lots/new
def new
#lot = Lot.new
#lot.colindanciums.build
authorize #lot
end
# PATCH/PUT /lots/1
# PATCH/PUT /lots/1.json
def update
authorize #lot
respond_to do |format|
if #lot.update(lot_params)
format.html { redirect_to #lot, notice: 'Lot was successfully updated.' }
format.json { render :show, status: :ok, location: #lot }
format.js
else
format.html { render :edit }
format.json { render json: #lot.errors, status: :unprocessable_entity }
format.js { render json: #lot.errors, status: :unprocessable_entity }
end
end
end
I change my logic in the select, i made it works in this way:
<div class="form-group">
<%= f.label :cardinal_point_id, "Orientacion:", :class => "control-label" %>
<%= f.select :cardinal_point_id , CardinalPoint.all.collect {|p| [ p.name, p.id ] }, { :include_blank => 'Seleccione un Punto Cardinal'}, :class => "form-control" %>
</div>
I post my answer in case anybody have the same issue.
You forgot to put the parenthesis correctly
<%= f.select (:cardinal_point_id,
options_from_collection_for_select(CardinalPoint.all, :id, :name), { }, { :class => "form-control", :prompt => "Seleccione un Punto Cardinal" }) %>
I'm new to RoR and having an issue when trying to save from multiple dropdowns. I have three objects - books, genres, and authors. A book object has a genre and author associated to it, but the issue is I can only manage to save either a genre or author to my book object, and not both. Here's where I'm at:
class Author < ActiveRecord::Base
validates :name, :presence => true
validates :biography, :presence => true
has_many :books
end
class Genre < ActiveRecord::Base
validates :description, :presence => true
has_many :books
end
class Book < ActiveRecord::Base
belongs_to :genre
belongs_to :author
has_many :cartitems
validates :name, :presence => true
validates :price, :presence => true
validates :description, :presence => true
end
Controller:
def create
##book = Book.new(params[:book])
#author = Author.find(params[:author].values[0])
#genre = Genre.find(params[:genre].values[0])
#book = #author.books.create(params[:book])
#one or the other saves, but not both
##book = #genre.books.create(params[:book])
respond_to do |format|
if #book.save
format.html { redirect_to(#book, :notice => 'Book was successfully created.') }
format.xml { render :xml => #book, :status => :created, :location => #book }
else
format.html { render :action => "new" }
format.xml { render :xml => #book.errors, :status => :unprocessable_entity }
end
end
end
Not sure if this will help out or not, but here's what the dropdowns look like in the View:
<div class="field">
<%= f.label :genre %><br />
<%= #items = Genre.find(:all)
select("genre", "description", #items.map {|u| [u.description,u.id]}, {:include_blank => true})%>
Appreciate any help with this.
EDIT - Here's my full form.
<%= form_for(#book) do |f| %>
<% if #book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#book.errors.count, "error") %> prohibited this book from being saved:</h2>
<ul>
<% #book.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 :price %><br />
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :genre %><br />
<%= #items = Genre.find(:all)
select("genre", "description", #items.map {|u| [u.description,u.id]}, {:include_blank => true})%>
</div>
<div class="field">
<%= f.label :author %><br />
<%=#items = Author.find(:all)
select("author", "name", #items.map {|u| [u.name,u.id]}, {:include_blank => true}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Update your select fields to be defined like this:
<div class="field">
<%= f.label :genre %><br />
<%= f.select( :genre_id, Genre.all.map {|u| [u.description,u.id]}, {:include_blank => true}) %>
</div>
<div class="field">
<%= f.label :author %><br />
<%= f.select( :author_id, Author.all.map {|u| [u.name,u.id]}, {:include_blank => true}) %>
</div>
And your controller action should be like this:
def create
#book = Book.new(params[:book])
respond_to do |format|
if #book.save
format.html { redirect_to(#book, :notice => 'Book was successfully created.') }
format.xml { render :xml => #book, :status => :created, :location => #book }
else
format.html { render :action => "new" }
format.xml { render :xml => #book.errors, :status => :unprocessable_entity }
end
end
Also, remove the format.xml calls if you don't need them, they're just cluttering your controller action.
There are lots of different ways to fix your problem, it would help to see exactly what's in your params hash and what your full form looks like, but no matter. Here is one way:
#book = #author.books.create(:genre => #genre)
Here is another (essentially the same thing):
#book = #author.books.create {|book| book.genre = #genre}
You could also instantiate the book separately:
#author = Author.find(params[:author].values[0])
#genre = Genre.find(params[:genre].values[0])
#book = Book.create(:author => #author, :genre => #genre)
My guess is you didn't quite build your form correctly, otherwise your params hash would look similar to this {:book => {:author => 1, :genre => 5}} and you would be able to do this:
#book = Book.create(params[:book])
And you would not look up the author using params[:author], but would instead do params[:book][:author] if you needed to do it at all.