Beginner stuck on Ruby on Rails project "...must exist" - ruby

So my assignment asks me to generate a page that handles students, courses, and sections. I'm supposed to be using many_to_many or some similar method to be able to list all this shared data. My specific problem is that I created a new table (rails g scaffold enrollment students:references sections:references) that doesn't seem to work. when I attempt to create a new enrollment using a student and section, I get an error stating that "Section must exist" error . I have no idea where this error is coming from. The sections field in this view is only populated with existing sections, so the fact that it says "must exist" is very...confusing. Can anyone point me in the right direction to solve this? I've rebuilt this project 3 times trying different methods and am just... stuck. I'll post the relevant code, but if I'm wrong about which sections you may need to see, I'll happily post the rest.
class Enrollment < ApplicationRecord
belongs_to :section
belongs_to :student
end
<%= form_with(model: enrollment, local: true) do |form| %>
<% if enrollment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(enrollment.errors.count, "error") %>
prohibited this enrollment from being saved:</h2>
<ul>
<% enrollment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :student_id %>
<%= form.collection_select :student_id, Student.order(:student_name), :id,
:student_id, include_blank:true %>
</div>
<div class="field">
<%= form.label :course_id %>
<%= form.collection_select :course_id, Course.order(:name), :id, :name,
include_blank: true %>
</div>
<div class="field">
<%= form.label :sections_number %>
<%= form.collection_select :section_number, Section.all, :id,
:section_number, include_blank:false %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
class Section < ApplicationRecord
has_many :enrollments
has_and_belongs_to_many :students, through: :enrollments
belongs_to :course
def numsem
"#{course.name} #{course_id}"
end
end
L
-----------------------EDIT TO ADD CONTROLLER CODE----------------
class EnrollmentsController < ApplicationController
before_action :set_enrollment, only: [:show, :edit, :update, :destroy]
# GET /enrollments
# GET /enrollments.json
def index
#enrollments = Enrollments.all
end
# GET /enrollments/1
# GET /enrollments/1.json
def show
end
# GET /enrollments/new
def new
#enrollment = Enrollments.new
#sections = Section.all
#students = Student.all
end
# GET /enrollments/1/edit
def edit
end
# POST /enrollments
# POST /enrollments.json
def create
#enrollment = Enrollments.new(enrollment_params)
respond_to do |format|
if #enrollment.save
format.html { redirect_to #enrollment, notice: 'Enrollments was
successfully created.' }
format.json { render :show, status: :created, location: #enrollment }
else
format.html { render :new }
format.json { render json: #enrollment.errors, status:
:unprocessable_entity }
end
end
end
# PATCH/PUT /enrollments/1
# PATCH/PUT /enrollments/1.json
def update
respond_to do |format|
if #enrollment.update(enrollment_params)
format.html { redirect_to #enrollment, notice: 'Enrollments was
successfully updated.' }
format.json { render :show, status: :ok, location: #enrollment }
else
format.html { render :edit }
format.json { render json: #enrollment.errors, status:
:unprocessable_entity }
end
end
end
# DELETE /enrollments/1
# DELETE /enrollments/1.json
def destroy
#enrollment.destroy
respond_to do |format|
format.html { redirect_to enrollments_index_url, notice: 'Enrollments was
successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_enrollment
#enrollment = Enrollments.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list
through.
def enrollment_params
params.require(:enrollment).permit(:student_id, :section_id)
end
end

Section must exist
The error is because you are trying to save the #enrollment with a nil section_id which raises that exception. The problem lies with your form where you have this
<%= form.collection_select :section_number, Section.all, :id,
:section_number, include_blank:false %>
which should be
<%= form.collection_select :section_id, Section.all, :id,
:section_number, include_blank:false %>

Related

Rails 5 - save rolls back because nested models parent model is not being saved before child model

Ok folks, Rails 5 has really had its nuances differing from Rails 4. What I have going on is that every time I click the submit button on the form it reloads with the error Profile user must exist and Profile user can't be blank. The form loads fine including the nested models form, but for what ever reason it is failing to save the parent model before attempting to save the child model with the following output to the console:
Puma starting in single mode...
* Version 3.7.0 (ruby 2.2.6-p396), codename: Snowy Sagebrush
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
Started POST "/users" for 192.168.0.31 at 2017-03-09 18:51:04 -0500
Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
ActiveRecord::SchemaMigration Load (0.2ms) SELECT `schema_migrations`.* FROM `schema_migrations`
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JPKO+ppAYqwWS8tWeXhEtbUWynXREu9jYlF0KIlyPgUaabHSzjPZocSxCvr/WEm1r6wAQyT1CvA6hNkZWfPD3Q==", "user"=>{"username"=>"test", "password"=>"[FILTERED]", "user_type_id"=>"1", "profile_attributes"=>{"first_name"=>"123", "middle_name"=>"123", "last_name"=>"123", "email"=>"123#123.com", "phone_number"=>"1234567890", "cell_number"=>"1234567890"}}, "commit"=>"Create User"}
(0.1ms) BEGIN
(0.2ms) ROLLBACK
Rendering users/new.html.erb within layouts/application
Rendered users/_form.html.erb (112.5ms)
Rendered users/new.html.erb within layouts/application (118.7ms)
Completed 200 OK in 834ms (Views: 780.1ms | ActiveRecord: 2.2ms)
I have have had other problems out of this relationship and I am thinking that maybe I need to rebuild the project.
Here is all of the relevant code around this issue:
###############################################################################
### Users Model
###############################################################################
class User < ApplicationRecord
has_one :profile, inverse_of: :user
accepts_nested_attributes_for :profile, allow_destroy: true
end
###############################################################################
### Profile Model
###############################################################################
class Profile < ApplicationRecord
belongs_to :user, inverse_of: :profile
validates_presence_of :user
end
###############################################################################
### Users Controller
###############################################################################
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
#user.build_profile
end
# GET /users/new
def new
#user = User.new
#user.build_profile
end
# GET /users/1/edit
def edit
#user.build_profile
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:username, :password, :user_type_id, profile_attributes: [:id, :user_id, :first_name, :middle_name, :last_name, :phone_number, :cell_number, :email])
end
end
###############################################################################
### Form View
###############################################################################
<%= form_for(#user) do |f| %>
<% if user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
<!--<li><%= debug f %></li>-->
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :username %>
<%= f.text_field :username %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.text_field :password %>
</div>
<div class="field">
<% if params[:trainer] == "true" %>
<%= f.label :user_type_id %>
<%= f.text_field :user_type_id, :readonly => true, :value => '2' %>
<% else %>
<%= f.label :user_type_id %>
<%= f.text_field :user_type_id, :readonly => true, :value => '1' %>
<% end %>
</div>
<h2>Account Profile</h2>
<%= f.fields_for :profile do |profile| %>
<%#= profile.inspect %>
<div>
<%= profile.label :first_name %>
<%= profile.text_field :first_name %>
</div>
<div>
<%= profile.label :middle_name %>
<%= profile.text_field :middle_name %>
</div>
<div>
<%= profile.label :last_name %>
<%= profile.text_field :last_name %>
</div>
<div>
<%= profile.label :email %>
<%= profile.text_field :email %>
</div>
<div>
<%= profile.label :phone_number %>
<%= profile.telephone_field :phone_number %>
</div>
<div>
<%= profile.label :cell_phone %>
<%= profile.telephone_field :cell_number %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<%= debug params %>
<%= debug user %>
<%= debug user.profile %>
<% end %>
Alright I rephrased the question on another question and I finally found the answer to this. So I am pasting my answer from there, in case someone searches for the issue in the same fashion that I was asking the question here.
Ok, I am answering my own question because I know many people are struggling with this and I actually have the answer and not a vague response to the documentation.
First we will just be using a one to one relationship for this example. When you create your relationships you need to make sure that the parent model has the following
inverse_of:
autosave: true
accepts_nested_attributes_for :model, allow_destroy:true
Here is the Users model then I will explain,
class User < ApplicationRecord
has_one :profile, inverse_of: :user, autosave: true
accepts_nested_attributes_for :profile, allow_destroy: true
end
in Rails 5 you need inverse_of: because this tells Rails that there is a relationship through foreign key and that it needs to be set on the nested model when saving your form data. Now if you were to leave autosave: true off from the relationship line you are left with the user_id not saving to the profiles table and just the other columns, unless you have validations off and then it won't error out it will just save it without the user_id. What is going on here is autosave: true is making sure that the user record is saved first so that it has the user_id to store in the nested attributes for the profile model.
That is it in a nutshell why the user_id was not traversing to the child and it was rolling back rather than committing.
Also one last gotcha is there are some posts out there telling you in your controller for the edit route you should add #user.build_profile like I have in my post. DO NOT DO IT THEY ARE DEAD WRONG, after assessing the console output it results in
Started GET "/users/1/edit" for 192.168.0.31 at 2017-03-12 22:38:17 -0400
Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#edit as HTML
Parameters: {"id"=>"1"}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
Profile Load (0.5ms) SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 1 LIMIT 1
(0.1ms) BEGIN
SQL (0.5ms) UPDATE `profiles` SET `user_id` = NULL, `updated_at` = '2017-03-13 02:38:17' WHERE `profiles`.`id` = 1
(59.5ms) COMMIT
Rendering users/edit.html.erb within layouts/application
Rendered users/_form.html.erb (44.8ms)
Rendered users/edit.html.erb within layouts/application (50.2ms)
Completed 200 OK in 174ms (Views: 98.6ms | ActiveRecord: 61.1ms)
If you look it is rebuilding the profile from scratch and resetting the user_id to null for the record that matches the current user you are editing. So be very careful of this as I have seen tons of posts making this suggestion and it cost me DAYS of research to find a solution!
Rails 6.1
I had a similar issue that was fixed by removing validates_presence_of :user and validates :user_id, presence: true from my profile model. Your model obviously did not have the same validations mine had, but I thought it may be useful to add this answer in case others do.
I did not need to add inverse_of or autosave to either model to get the nested attributes to save correctly.
I came across this question because I had the same problem but only for my rspec tests. I ended up doing rails db:reset RAILS_ENV=test and that solved it. I did not need to add inverse_of: :user or autosave:true to the models.
One theory you could check in a dev or production system is if your seed for the table somehow got off. So then it can't insert the user row because the id is in use and then the profile create fails because the user create failed. In postgresql you could run: SELECT setval('users_id_seq', (SELECT max(id) FROM users}));
I was having a similar issue (did not save with nested attributes).
In the controller, I changed my #user.build_profile to #user.profile.build(params[:profile]) and it solved the issue.

undefined method `any?' for nil:NilClass for <% if #users.any? %>

I am following the Micheal Hartl Ruby on Rails tutorial. In the 12 chapter, I am getting this error.
I am trying to display the following and the followers, but I am not able to.
Following are the codes:
show.html.erb
<% provide(:title, #title) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= gravatar_for #user %>
<h1><%= #user.name %></h1>
<span><%= link_to "view my profile", #user %></span>
<span><b>Microposts:</b> <%= #user.microposts.count %></span>
</section>
<section class="stats">
<%= render 'shared/stats' %>
<% if #users.any? %>
<div class="user_avatars">
<% #users.each do |user| %>
<%= link_to gravatar_for(user, size: 30), user %>
<% end %>
</div>
<% end %>
</section>
</aside>
<div class="col-md-8">
<h3><%= #title %></h3>
<% if #users.any? %>
<ul class="users follow">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
</div>
</div>
relationship_controller.rb
class RelationshipsController < ApplicationController
before_action :logged_in_user
def create
def create
#user = User.find(params[:followed_id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow(user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
user_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
:following, :followers]
before_action:correct_user, only: [:edit, :update]
before_action:admin_user, only: :destroy
def index
#users= User.paginate(page: params[:page])
end
def show
#user= User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page], :per_page => 5)
end
def new
#user= User.new
end
def create
#user= User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def edit
#user= User.find(params[:id])
end
def update
#user= User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following.paginate(page: params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(page: params[:page])
render 'show_follow'
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
def correct_user
#user= User.find(params[:id])
redirect_to(root_url) unless #user== current_user
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Your issue is that the show action is actually using the #user instead of #users instance variable.
Your section for stats will not work since it's expecting what it looks like a collection of User as it would from the index action.
Since you have the action for followers which sets the #user and #users instance variables you have to visit that action instead and the code on your show.html.erb template will most likely have to move to the show_follow.html.erb template.
UPDATE
You need to remove this section from your show.html.erb template
<section class="stats">
<%= render 'shared/stats' %>
<% if #users.any? %>
<div class="user_avatars">
<% #users.each do |user| %>
<%= link_to gravatar_for(user, size: 30), user %>
<% end %>
</div>
<% end %>
</section>
</aside>
<div class="col-md-8">
<h3><%= #title %></h3>
<% if #users.any? %>
<ul class="users follow">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
</div>
I saw your repository and seems like you have messed up the code, according to what you are following(Ruby on Rails - Micheal Hartl), this is what you need to change:
The code in your show.html.erb should be placed in show_follow.html.erb
After this follow the 12th chapter again and place the right code in show.html.erb.

Ruby on Rails First argument in form cannot contain nil or be empty

I used the standard Ruby on Rails generate scaffolding. I need help to find out how to move a form from the "New" view to the "Posts" view (Main Page). I keep on getting the error "First argument in form cannot contain nil or be empty". Here is my "Posts" view code. It works fine in the "New" view but not the "Posts" view.
Posts View:
<%= form_for(#post) do |f| %>
New View:
<h1>New post</h1>
<%= render 'form' %>
<%= link_to 'Back', posts_path %>
Form View:
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
</div>
<div class="field">
<%= f.label :casino %>
<%= f.text_field :casino %>
</div>
</div>
<div class="field">
<%= f.label :City %>
<%= f.text_field :City %>
</div>
</div>
</div>
<div class="field">
<%= f.label :State %>
<%= f.text_field :State %>
</div>
</div>
<div class="field">
<%= f.label :Country %>
<%= f.text_field :Country %>
</div>
<div class="field">
<%= f.label :Game %>
<%= f.text_field :title %>
<div class="field">
<%= f.label :Minimum %>
<%= f.text_field :text %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
CONTROLLER CODE:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :text, :casino, :City, :State, :Country)
end
end
Add this line in index action of PostsController
#post = Post.new
This should solve your problem :)
SOLUTION:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
#post = Post.new
end

uninitialized constant error when trying to update the image file

I am trying to use and learn carrierwave. My problem is that I am able to upload files, but when trying to edit them I am getting the error uninitialized constant ImageFile
Heres my images_controller.rb
class ImagesController < ApplicationController
before_action :set_image, only: [:show, :edit, :update, :destroy]
# GET /images
# GET /images.json
def index
#images = Image.all
end
# GET /images/1
# GET /images/1.json
def show
end
# GET /images/new
def new
#image = Image.new
end
# GET /images/1/edit
def edit
end
# POST /images
# POST /images.json
def create
#image = Image.new(image_params)
respond_to do |format|
if #image.save
format.html { redirect_to #image, notice: 'Image was successfully created.' }
format.json { render :show, status: :created, location: #image }
else
format.html { render :new }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /images/1
# PATCH/PUT /images/1.json
def update
respond_to do |format|
if #image.update(image_params)
format.html { redirect_to #image, notice: 'Image was successfully updated.' }
format.json { render :show, status: :ok, location: #image }
else
format.html { render :edit }
format.json { render json: image.errors, status: :unprocessable_entity }
end
end
end
# DELETE /images/1
# DELETE /images/1.json
def destroy
#image.destroy
respond_to do |format|
format.html { redirect_to images_url, notice: 'Image was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_image
#image = Image.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def image_params
params.require(:image).permit(:Title, :ImageFile, :Comments)
end
end
and this is the _form.html.erb used in both new and edit
<%= form_for #image, html: { multipart: true } do |f| %>
<% if #image.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#image.errors.count, "error") %> prohibited this image from being saved:</h2>
<ul>
<% #image.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 :ImageFile %><br>
<%= f.file_field :ImageFile %>
</div>
<div class="field">
<%= f.label :Comments %><br>
<%= f.text_field :Comments %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and here is the image.rb
class Image < ActiveRecord::Base
# attr_accessible :Comments, :ImageFile, :Title
mount_uploader :ImageFile, ImageCreatorUploader
end
please help
You have an error in your Image class. you are not mounting the uploader correctly. You are passing in a symbol of a classname to the mount_uploader method. You need to pass a symbol of the field name. Replace:
class Image < ActiveRecord::Base
mount_uploader :ImageFile, ImageCreatorUploader
end
With:
class Image < ActiveRecord::Base
mount_uploader :image_file, ImageCreatorUploader
end
Method names should not be capitalised. Only class names.
Also, since you are using strong_parameters, you don't need attr_accessible. You've commented the line out, but I figured I would point this out. You've also capitalised your attribute names here, which is not correct. Use snake_case.
In ruby, attribute names, variable names, method names should all start with a small letter. Names starting with Capital letters are considered constants, and class names.
Change all references to your class's attributes (:Title, :ImageFile, :Comments) to snake_case (:title, :image_file, :comments)

Why did I get a "No Method" error?

I am currently going through "Agile web development with Rails - 4th edition" and I am stuck.
The checkout button is supposed to bring up an orders page, but instead I get this error:
NoMethodError in Orders#new
Showing C:/Sites/depot/app/views/orders/_form.html.erb where line #1 raised:
undefined method `model_name' for NilClass:Class
Extracted source (around line #1):
1: <%= form_for(#order) do |f| %>
2: <% if #order.errors.any? %>
3: <div id="error_explanation">
4: <h2><%= pluralize(#order.errors.count, "error") %>
After spending a lot of time trying to figure this out, I copied all the source code from the books website, which still didn't work. I even checked the errata and book forums and found nothing.
What am I doing wrong?
This is the code from the views/orders/_form.html.erb:
<%= form_for(#order) do |f| %>
<% if #order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#order.errors.count, "error") %>
prohibited this order from being saved:</h2>
<ul>
<% #order.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<!-- START_HIGHLIGHT -->
<%= f.text_field :name, size: 40 %>
<!-- END_HIGHLIGHT -->
</div>
<div class="field">
<%= f.label :address %><br />
<!-- START_HIGHLIGHT -->
<%= f.text_area :address, rows: 3, cols: 40 %>
<!-- END_HIGHLIGHT -->
</div>
<div class="field">
<%= f.label :email %><br />
<!-- START_HIGHLIGHT -->
<%= f.email_field :email, size: 40 %>
<!-- END_HIGHLIGHT -->
</div>
<div class="field">
<%= f.label :pay_type %><br />
<!-- START_HIGHLIGHT -->
<%= f.select :pay_type, Order::PAYMENT_TYPES,
prompt: 'Select a payment method' %>
<!-- END_HIGHLIGHT -->
</div>
<div class="actions">
<!-- START_HIGHLIGHT -->
<%= f.submit 'Place Order' %>
<!-- END_HIGHLIGHT -->
</div>
<% end %>
This is the Orders Controller:
class OrdersController < ApplicationController
def index
#orders = Order.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #orders }
end
end
# GET /orders/1
# GET /orders/1.json
def show
#order = Order.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #order }
end
end
# GET /orders/new
# GET /orders/new.json
def new
#cart = current_cart
if #cart.line_items.empty?
redirect_to store_url, notice: "Your cart is empty"
return
end
#order = Order.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #order }
end
end
# GET /orders/1/edit
def edit
#order = Order.find(params[:id])
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(params[:order])
#order.add_line_items_from_cart(current_cart)
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to store_url, notice:
'Thank you for your order.' }
format.json { render json: #order, status: :created,
location: #order }
else
#cart = current_cart
format.html { render action: "new" }
format.json { render json: #order.errors,
status: :unprocessable_entity }
end
end
end
# PUT /orders/1
# PUT /orders/1.json
def update
#order = Order.find(params[:id])
respond_to do |format|
if #order.update_attributes(params[:order])
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order = Order.find(params[:id])
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :ok }
end
end
end
This is the Order model:
class Order < ActiveRecord::Base
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
has_many :line_items, dependent: :destroy
# ...
validates :name, :address, :email, presence: true
validates :pay_type, inclusion: PAYMENT_TYPES
end
The form view believes that #order is nil here:
1: <%= form_for(#order) do |f| %>
What is the path that you are hitting in the browser? /orders/new
It does appear that Order#new is setting #order to Order.new, so I am wondering if you are actually hitting that controller.
Rails will route requests to controller actions based on what is setup in routes.rb. Run rake routes to see the routes you can access in the url.
Rails has conventions such that if you access the /orders/new using a simple GET request, it will route your request to the new action of the OrdersController and will attempt to render the associated app/views/orders/new.html.erb - unless you customize some aspect of this.
I would add a puts "Order is set to: #{#order}" in the new action following the #order = Order.new assignment to ensure it's actually going through that path.

Resources