Couldn't find Object without an ID - ruby-on-rails

This is driving mi crazy. I don't know what I'm doing wrong, I'm getting this error:
ActiveRecord::RecordNotFound in AppointmentsController#new
Couldn't find Schedule without an ID
app/controllers/appointments_controller.rb:25:in `new'
I'm sure is a simple thing but I can't see it. Please can somebody point me the issue and how to solve it?
Here is my code
Routes.rb
scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
root :to => "Doctors#index"
resources :specialties
resources :branches
resources :doctors do
resources :appointments
resources :schedules
end
end
match '*path', to: redirect("/#{I18n.default_locale}/%{path}")
match '', to: redirect("/#{I18n.default_locale}")
Relationship
Class Appointment ...
belongs_to :doctor
belongs_to :schedule
end
Class Schedule ...
belongs_to :doctor
has_many :appointments
end
Class Doctor ...
has_many :appointments, dependent: :destroy
has_many :schedules, dependent: :destroy
end
schema
create_table "appointments", :force => true do |t|
t.integer "doctor_id"
t.date "adate"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.time "atime"
t.string "personal_id"
t.string "insurance_id"
t.string "prescription"
t.string "email"
t.string "full_name"
t.integer "schedule_id"
end
create_table "doctors", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "schedule"
t.string "prefix"
end
create_table "schedules", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "doctor_id"
t.boolean "sun"
t.boolean "mon"
t.boolean "tue"
t.boolean "wed"
t.boolean "thu"
t.boolean "fri"
t.boolean "sat"
end
Controller
def new
#schedule = Schedule.find(params[:schedule_id])
#doctor = Doctor.find(params[:doctor_id])
#appointment = #doctor.appointments.new
end
_form
<h1><%= #doctor.name %></h1>
<%= simple_form_for([#doctor, #appointment], :html => { :multipart => true, :class => 'form-horizontal' }) do |f| %>
<%= f.error_notification %>
<%= f.input :full_name %>
<%= f.input :email %>
<%= f.input :adate, as: :date_picker %>
<%= f.input :atime, as: :time_picker %>
<%= f.input :personal_id %>
<%= f.input :insurance_id %>
<%= f.input :prescription %>
<div class="controls"><%= f.button :submit, class: "btn btn-primary" %></div>
<% end %>
rails console test:
Loading development environment (Rails 3.2.11)
1.9.3p125 :001 > s = Schedule.last
Schedule Load (4.2ms) SELECT "schedules".* FROM "schedules" ORDER BY "schedules"."id" DESC LIMIT 1
=> #<Schedule id: 2, created_at: "2013-01-23 08:40:14", updated_at: "2013-01-23 08:40:14", doctor_id: 1, sun: true, mon: true, tue: true, wed: true, thu: true, fri: true, sat: true>
1.9.3p125 :002 > s.appointments
Appointment Load (0.7ms) SELECT "appointments".* FROM "appointments" WHERE "appointments"."schedule_id" = 2
=> []
root /:locale(.:format) Doctors#index
specialties GET /:locale/specialties(.:format) specialties#index
POST /:locale/specialties(.:format) specialties#create
new_specialty GET /:locale/specialties/new(.:format) specialties#new
edit_specialty GET /:locale/specialties/:id/edit(.:format) specialties#edit
specialty GET /:locale/specialties/:id(.:format) specialties#show
PUT /:locale/specialties/:id(.:format) specialties#update
DELETE /:locale/specialties/:id(.:format) specialties#destroy
branches GET /:locale/branches(.:format) branches#index
POST /:locale/branches(.:format) branches#create
new_branch GET /:locale/branches/new(.:format) branches#new
edit_branch GET /:locale/branches/:id/edit(.:format) branches#edit
branch GET /:locale/branches/:id(.:format) branches#show
PUT /:locale/branches/:id(.:format) branches#update
DELETE /:locale/branches/:id(.:format) branches#destroy
doctor_appointments GET /:locale/doctors/:doctor_id/appointments(.:format) appointments#index
POST /:locale/doctors/:doctor_id/appointments(.:format) appointments#create
new_doctor_appointment GET /:locale/doctors/:doctor_id/appointments/new(.:format) appointments#new
edit_doctor_appointment GET /:locale/doctors/:doctor_id/appointments/:id/edit(.:format) appointments#edit
doctor_appointment GET /:locale/doctors/:doctor_id/appointments/:id(.:format) appointments#show
PUT /:locale/doctors/:doctor_id/appointments/:id(.:format) appointments#update
DELETE /:locale/doctors/:doctor_id/appointments/:id(.:format) appointments#destroy
doctor_schedules GET /:locale/doctors/:doctor_id/schedules(.:format) schedules#index
POST /:locale/doctors/:doctor_id/schedules(.:format) schedules#create
new_doctor_schedule GET /:locale/doctors/:doctor_id/schedules/new(.:format) schedules#new
edit_doctor_schedule GET /:locale/doctors/:doctor_id/schedules/:id/edit(.:format) schedules#edit
doctor_schedule GET /:locale/doctors/:doctor_id/schedules/:id(.:format) schedules#show
PUT /:locale/doctors/:doctor_id/schedules/:id(.:format) schedules#update
DELETE /:locale/doctors/:doctor_id/schedules/:id(.:format) schedules#destroy
doctors GET /:locale/doctors(.:format) doctors#index
POST /:locale/doctors(.:format) doctors#create
new_doctor GET /:locale/doctors/new(.:format) doctors#new
edit_doctor GET /:locale/doctors/:id/edit(.:format) doctors#edit
doctor GET /:locale/doctors/:id(.:format) doctors#show
PUT /:locale/doctors/:id(.:format) doctors#update
DELETE /:locale/doctors/:id(.:format) doctors#destroy
/*path(.:format) :controller#:action
/ :controller#:action
appointment_steps GET /appointment_steps(.:format) appointment_steps#index
POST /appointment_steps(.:format) appointment_steps#create
new_appointment_step GET /appointment_steps/new(.:format) appointment_steps#new
edit_appointment_step GET /appointment_steps/:id/edit(.:format) appointment_steps#edit
appointment_step GET /appointment_steps/:id(.:format) appointment_steps#show
PUT /appointment_steps/:id(.:format) appointment_steps#update
DELETE /appointment_steps/:id(.:format) appointment_steps#destroy

Related

How can I save the datas checked with simple_form checkbox?

I am beginner with Ruby on Rails, and I am trying to build a little app that permit people to order a pastrie from a cooker, for a day chosen.
When they select the pastrie using a checkbox, I would like that the selected pastrie was saved as pastrie_id in the table fight but instead, I have an issue :
Validation failed: Pastrie must exist.
UPDATE this is working :
<%= f.association :pastrie, as: :check_boxes, label: 'Pastrie' %>
I still have an issue, the saving params are not good I have :
"fight"=>{"pastrie_id"=>["", "1"]},
I tried a lot of solutions found on stackoverflow but nothing seems to work.
I am using Rails 5.2.3
So, this is my schema :
ActiveRecord::Schema.define(version: 2019_06_06_094318) do
create_table "cookers", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "pastrie"
end
create_table "events", force: :cascade do |t|
t.datetime "date"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "fights", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "pastrie_id"
t.integer "event_id"
t.integer "cooker_id"
t.index ["cooker_id"], name: "index_fights_on_cooker_id"
t.index ["event_id"], name: "index_fights_on_event_id"
t.index ["pastrie_id"], name: "index_fights_on_pastrie_id"
end
create_table "pastries", force: :cascade do |t|
t.string "pastrie_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Here is my models :
class Event < ApplicationRecord
has_many :pastries, through: :fights
has_many :cookers, through: :fights
has_many :fights
end
class Fight < ApplicationRecord
belongs_to :pastrie
belongs_to :event
belongs_to :cooker, optional: true
end
class Pastrie < ApplicationRecord
has_many :fights
has_many :events, through: :fights
end
This is my controller. What I understand is : in order to create a Fight, I need an event_id and a pastrie_id (cooker_id is optional). So first, I create a new event (and so I have an event_id), and next, I need to connect a pastrie_id (existing in my seed) to my fight. But this is not working if I am doing that :
class FightsController < ApplicationController
def new
#fight = Fight.new
#event = Event.find(params[:event_id])
#pastries = Pastrie.all
end
def create
#fight = Fight.new(fight_params)
#event = Event.find(params[:event_id])
#fight.event = Event.find(params[:event_id])
#fight.pastrie_id = params[:fight][:pastrie_id]
#fight.save!
redirect_to root_path
end
def show
#events = Event.all
end
def index
#fights = Fight.all
fights_by_event = []
end
private
def fight_params
params.require(:fight).permit(:event_id, :pastrie_id, :cooker_id)
end
end
And my view when I am creating my "fight" :
<div class=margin-bottom>
<h2 class=text-center> Bonjour Linguini, quelles patisseries veux-tu choisir ?</h2>
</div>
<div class="container margin-bottom">
<%= simple_form_for [#event, #fight] do |f| %>
<% #pastries.each do |pastrie| %>
<%= f.label :pastrie_id do %>
<%= f.check_box :pastrie_id, as: :boolean, checked_value: true, unchecked_value: false %> <span><%= pastrie.pastrie_name%></span>
<% end %></br>
<% end %>
<%= f.submit "Valider", class: "btn btn-primary" %>
<% end %>
</div>
And this is my routes if you need this :
Rails.application.routes.draw do
root to: 'pages#home'
resources :events do
resources :fights, only: [:new, :show, :create]
end
resources :fights, only: [:index]
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
In your form change
<%= f.check_box :pastrie_id, as: :boolean, checked_value: true, unchecked_value: false %> <span><%= pastrie.pastrie_name%></span>
To
<%= f.check_box :pastrie_id, as: :boolean, checked_value: pastrie.id, unchecked_value: nil %> <span><%= pastrie.pastrie_name%></span>
In the first version you submit a param of {pastrie_id: true}, which obviously doesn't relate to a Pastry. The second version should submit the ID of the checked box (although if it belongs to only 1 pastry it might make more sense to make these radio buttons)

Creating a nested object with child in a form

I'm a rails noob that's tryin to do something in his app.
My problem is:
I have a Corso model, a Libro model and an Annuncio model. Corso has_many Libro, Libro has_many Annuncio, Annuncio belongs_to Libro and Libro belongs_to Corso. I want a form where the user can create a Libro (that MUST be associated to a Corso) and meanwhile an Annuncio of that Libro must be created. I'm literally freaking out, I saw hundreds of discussions but nothing solved my problem. Every time I change something I get some different errors.
My focus is:
- how to pass the corso_id (I mean, the objects Corso are already defined in the db) to the new Libro when I submit the form;
-I don't see why a Libro object is created (all fields nil) but an Annuncio object doesn't. It seems like the code #libro.annuncios.build in LibroController/new is useless.
I hope you will help me to get this form working.
LibroController:
class LibroController < ApplicationController
def new
#corso = Corso.find(params[:corso_id])
#libro = #corso.libros.build
#libro.annuncios.build
end
def create
#corso = Corso.find(params[:corso_id])
#libro = #corso.libros.build(libro_params)
if #libro.save
redirect_to #libro
else
redirect_to root_path
end
end
def show
#libro = Libro.find(params[:id])
end
def index
end
private
def libro_params
params.require(:libro).permit(:titolo, :autori, :casa_editrice, :edizione, :anno_pubblicazione, :ISBN, :immagine, :corso_id, annuncios_attributes[:prezzo, :note])
end
end
AnnuncioController:
class AnnuncioController < ApplicationController
def new
#annuncio = Annuncio.new
end
def create
#libro = Libro.find(params[:libro_id])
#annuncio = #libro.annuncio.build(annuncio_params)
if #annuncio.save
redirect_to #libro
else
redirect_to root_path
end
end
private
def annuncio_params
params.require(:annuncio).permit(:prezzo, :note)
end
end
Libro Model:
class Libro < ApplicationRecord
belongs_to :corso, inverse_of: :libros
has_many :annuncios, inverse_of: :libro
accepts_nested_attributes_for :annuncios
end
Annuncio Model:
class Annuncio < ApplicationRecord
belongs_to :utente, inverse_of: :annuncios
belongs_to :libro, optional: true, inverse_of: :annuncios
end
Corso Model:
class Corso < ApplicationRecord
belongs_to :facolta
has_many :libros
validates :nome, uniqueness: true
end
routes.rb (a little messed up)
Rails.application.routes.draw do
get 'facolta/new'
get 'sessions/create'
get 'sessions/destroy'
get 'users/new'
get 'corso/index'
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessions#destroy', as: 'signout'
resources :sessions, only: [:create, :destroy]
resource :home, only: [:show]
root 'facolta#index'
get 'corso_new' => 'corso#new'
get 'libro_new' => 'libro#new'
get 'about_us' => 'static_pages#about_us'
get 'faq' => 'static_pages#faq'
resources :facolta do
resources :corso
end
resources :corsos, shallow: true do
resources :libro
end
resources :libros do
resources :annuncio
end
resources :user do
resources :annuncio
end
end
views/libro/new
<h1>FORM DI REGISTRAZIONE HERE</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for([#corso, #libro]) do |libro| %>
<p>
<%= libro.label :titolo %>
<%= libro.text_field :titolo %>
</p>
<p>
<%= libro.label :autori %>
<%= libro.text_field :autori %>
</p>
<p>
<%= libro.label :casa_editrice %>
<%= libro.text_field :casa_editrice %>
</p>
<p>
<%= libro.label :edizione %>
<%= libro.text_field :edizione %>
</p>
<p>
<%= libro.label :anno_pubblicazione %>
<%= libro.text_field :anno_pubblicazione %>
</p>
<p>
<%= libro.label :ISBN %>
<%= libro.text_field :ISBN %>
</p>
<p>
<%= libro.label :immagine %>
<%= libro.text_field :immagine %>
</p>
<%= libro.fields_for :annuncios do |annuncio| %>
<p>
<%= annuncio.label :prezzo %>
<%= annuncio.text_field :prezzo %>
</p>
<p>
<%= annuncio.label :note %>
<%= annuncio.text_field :note %>
</p>
<% end %>
<%= libro.hidden_field :corso_id, value: params[:post_id]%>
<%= libro.submit "Inserisci il libro", class: "btn btn-primary" %>
<% end %>
</div>
</div>
schema.rb
create_table "annuncios", force: :cascade do |t|
t.integer "user_id"
t.integer "libro_id"
t.string "prezzo"
t.text "note"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["libro_id"], name: "index_annuncios_on_libro_id"
t.index ["user_id"], name: "index_annuncios_on_user_id"
end
create_table "corsos", force: :cascade do |t|
t.string "nome"
t.integer "facolta_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["facolta_id"], name: "index_corsos_on_facolta_id"
end
create_table "facolta", force: :cascade do |t|
t.string "nome"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "libros", force: :cascade do |t|
t.string "titolo"
t.string "autori"
t.string "casa_editrice"
t.string "edizione"
t.string "anno_pubblicazione"
t.string "ISBN"
t.string "immagine"
t.integer "corso_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["corso_id"], name: "index_libros_on_corso_id"
end
create_table "users", force: :cascade do |t|
t.string "provider"
t.string "uid"
t.string "name"
t.string "oauth_token"
t.datetime "oauth_expires_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email"
end
EDIT: edited with #arieljuod advices
You don't need to merge the corso_id here: #libro = #corso.libros.build(libro_params.merge({corso_id: #corso.id})). ActiveRecord already sets the corso_id since you are doing #corso.libros.build(...).
You also don't need that hidden_field with the Corso id since you already have that from the URL.
You may want to do #libro = #corso.libros.build on your new action too.
And finally, I think this is the main problem: this is wrong belongs_to :corso, inverse_of: :corsos, it should be inverse_of: :libros
Fix the other things I point out too to clean up your code.
EDIT:
to add a select do something like this:
= libro.select :corso_id, options_from_collection_for_select(Corso.all, :id, :name)

Belongs_to only recognized by console, not server

I've got a really weird problem with my project. I've got 2 models, the one is Link and the other Category. I've got a index view where all the links should be listed, together with the corresponding category names. When running the server and trying to use
<%= link.category.name %>
I get an error page with the following:
undefined method `name' for nil:NilClass
But when I open the console and write:
link = Link.find(1) #there is currently only one link
link.category.name
It returns the correct category name.
Here are my Models and schema.rb:
class Link < ActiveRecord::Base
attr_accessible :category_id, :description, :title, :url, :visible
belongs_to :category
scope :visible, lambda { where(visible: true) }
end
.
class Category < ActiveRecord::Base
attr_accessible :name
has_many :links
end
.
ActiveRecord::Schema.define(:version => 20130420070717) do
create_table "categories", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "categories", ["id"], :name => "index_categories_on_id"
create_table "links", :force => true do |t|
t.string "title"
t.text "description"
t.string "url"
t.integer "category_id"
t.boolean "visible"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "links", ["category_id"], :name => "index_links_on_category_id"
add_index "links", ["id"], :name => "index_links_on_id"
end
How can this happen? Thank you very much for your help!
Maybe I can help others facing the same issue.
The category_id was assigned to the link by a form which queries the existing categories from the db.
<%= f.select(:category_id, #categories.collect { |c| c.name }) %>
The category I wanted to assign has the id = 1. After selecting the category from the dropdown menu, the link.category_id was 0, it should have been 1.
UPDATE:
I fixed the wrong index by:
<%= f.collection_select :category_id, #categories, :id, :name, :prompt => "Select a category" %>

Populate Rails Form With Model Information From Another Controller

I've renamed the SessionsController and Session Model to Periods/Period because it conflicted with Devise and so you'll see this in the update
I have a sessions and events model/controller. When a new session is created, it needs to be associated with a particular event.
In my sessions model, I have an event_id, but I want to have a dropdown on the form that is populated with name of non-past events. Once that is selected, the form should be able to assign the correct event_id to the created session.
What is the correct way to go about doing this?
Here is my schema.rb to help you get a clearer picture of what the Models look like:
ActiveRecord::Schema.define(:version => 20120807154707) do
create_table "events", :force => true do |t|
t.string "name"
t.date "date"
t.string "street"
t.string "city"
t.string "state"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "sessions", :force => true do |t|
t.string "name"
t.integer "event_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "admin", :default => false
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
end
Here is my form:
<%= form_for(#period) do |f| %>
<%= f.label :Name %>
<%= f.text_field :name%>
<%= f.label :Event %>
<%= f.collection_select(:period, :event_id, Event.all, :id, :name)%>
<%= f.label :time %>
<%= f.text_field :time, id: "timepicker" %>
<%= f.submit "Create Event" %>
<% end %>
and I keep getting the following error: undefined methodmerge' for :name:Symbol`
Breaking out the various arguments of collection select: f.collection_select(:period, :event_id, Event.all, :id, :name)
:period -> The object
:event_id -> the method I want to set on the object.
Event.All -> The collection (for now I'll take all of them)
:id -> the value of the html element option
:name -> the value displayed to the user
Am I doing that correct?
To display a select menu with options from another model (not another controller), try collection_select.
In your new Session form, this might look like:
collection_select(:event, :id, Event.where("date > :date", date: Time.now.strftime("%m/%d/%Y"))
In the Sessions controller, in the create action, build the association like this:
#session.event = Event.find(params[:event][:id])
I have found that this structure works for me:
<%= f.label :event %>
<%= f.collection_select :event_id, Event.all, :id, :name, {:prompt=> "Pick an Event"}, {:class => "form-control"} %>
The last bit was the html part which I used to set the Bootstrap class.
:name here could be :date or :street etc...

Can't get association working in form

I'm having difficulties getting an association to work with simple_form.
I have the following models.
class Product < ActiveRecord::Base
belongs_to :Retailer
end
and
class Retailer < ActiveRecord::Base
has_many :Products
end
My form partial (products/_form.html.erb) contains the following
<%= simple_form_for(#product) do |f| %>
...
<% f.input :currency %>
<% f.association :retailer %>
...
It works without the association, but with it I get the following error:
undefined method `retailer_id' for #<Product:0x007ffbe0f7d530>
I'm (obviously) quite new to this, but haven't been able to work this out.
edit: checked I'd run migrations and they are up-to-date. The Retailer table has an id column!
> Retailer.all
Retailer Load (0.2ms) SELECT "retailers".* FROM "retailers"
=> [#<Retailer id: 1, name: "Retailer 1" etc...
chema file:
ActiveRecord::Schema.define(:version => 20120308195055) do
create_table "alerts", :force => true do |t|
t.string "url", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "products", :force => true do |t|
t.string "title", :null => false
t.integer "price_cents", :default => 0, :null => false
t.string "currency", :null => false
t.string "asin", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "retailers", :force => true do |t|
t.string "name", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
Since you have belongs_to :Retailer and <% f.association :retailer %> in your model and form for Product respectively, you'll need to add a retailer_id column to your products table.
You are missing t.references :retailer in your migration file for creating products table.
That is why, I quote you "it works without the association, but with it the error is undefined method 'retailer_id' for #<Product:0x007ffbe0f7d530>"
Yes, the retailers table has an id column but in order to reference a retailer from a product, your products table requires a retailer_id column.

Resources