Having major Rails issues currently. I'm creating a School-Dashboard app that takes an xref table called Enrollments that relates Courses and Students.
Any time I try to update a grade for an Enrollment, I constantly get this line
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: UPDATE
"enrollments" SET "grade" = ?, "updated_at" = ? WHERE "enrollments"."" IS NULL
This line does not appear when I update attributes for Courses or Students. Only for the :grade attribute in Enrollment.
For some reason, it isn't being read properly, even though it is a legitimate attribute in my db for Enrollment (check out my schema).
I do all of my preliminary work in the rails sandbox.
Using ruby 2.1.1, Rails 4.1.0.rc1
I'd really love some help here.
Here are my corresponding models
class Student < ActiveRecord::Base
has_many :enrollments
has_many :courses, through: :enrollments
end
class Course < ActiveRecord::Base
has_many :enrollments
has_many :students, through: :enrollments
end
class Enrollment < ActiveRecord::Base
belongs_to :student
belongs_to :course
end
The controllers:
Students
class StudentsController < ApplicationController
def index
#students = Student.all
end
def new
#student = Student.new
end
def show
end
def update
#student.update_attributes(student_params) ? redirect_to #student : render 'edit'
end
def create
#student = Student.new(student_params)
#student.save ? redirect_to #student : render 'new'
end
def destroy
end
def edit
end
private
def student_params
params.require(:student).permit(:first_name, :last_name, :student_number, :email)
end
end
Courses
class CoursesController < ApplicationController
def index
#courses = Course.all
end
def new
#course = Course.new
end
def show
end
def update
#course.update_attributes(course_params) ? redirect_to #course : render 'edit'
end
def create
#course = Course.new(course_params)
#course.save ? redirect_to #course : render 'new'
end
def destroy
end
def edit
# code here
end
private
def course_params
params.require(:course).permit(:course_name, :course_number)
end
end
Enrollments
class EnrollmentsController < ApplicationController
attr_accessor :course_id, :student_id, :grade
def index
#enrollments = Enrollment.all
end
def new
#enrollment = Enrollment.new
end
def create
#enrollment = Enrollment.new(enrollment_params)
#enrollment.save ? redirect_to #enrollment : render 'new'
end
def update
#enrollment.update_attributes(enrollment_params) ? redirect_to #enrollment : render 'edit'
end
def show
end
def destroy
#enrollment.destroy
end
def edit
# code here
end
private
def enrollment_params
params.require(:enrollment).permit(:course_id, :student_id, :grade)
end
end
And finally my schema.rb
ActiveRecord::Schema.define(version: 20140417152720) do
create_table "courses", force: true do |t|
t.string "course_name"
t.integer "course_number"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "enrollments", id: false, force: true do |t|
t.integer "course_id", null: false
t.integer "student_id", null: false
t.decimal "grade", precision: 5, scale: 2
t.datetime "created_at"
t.datetime "updated_at"
end
# noinspection RailsParamDefResolve
add_index "enrollments", ["course_id", "student_id"], name: "index_enrollments_on_course_id_and_student_id"
# noinspection RailsParamDefResolve
add_index "enrollments", ["student_id", "course_id"], name: "index_enrollments_on_student_id_and_course_id"
create_table "students", force: true do |t|
t.string "first_name"
t.string "last_name"
t.string "email"
t.integer "student_number"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Looks like I figured it out on my own!
So here's a bit of rails convention that needs to be addressed. The problem was with my database setup for 'Enrollments'. When I run the command
rails g migration CreateJoinTableEnrollments course student
Rails does too much work for me in my migration file (except for the table name and grade, I added that)
class CreateJoinTableEnrollments < ActiveRecord::Migration
def change
create_join_table :courses, :students, table_name: :enrollments, id: false, force: true do |t|
t.index [:course_id, :student_id], null: false
t.index [:student_id, :course_id], null :false
t.decimal :grade, precision: 5, scale: 2
t.timestamps
end
end
end
In reality, I didn't need any of that. In order to manipulate specific data in a row for Enrollments, there has to be an identifier for that row. With id: false, force: true that option got nullified. I also simplified things with the indexing. I just created regular old columns instead. Now my migration file looks like this.
class CreateJoinTableEnrollments < ActiveRecord::Migration
def change
create_table :enrollments do |t|
t.integer :course_id, null: false
t.integer :student_id, null: false
t.decimal :grade, precision: 5, scale: 2
t.timestamps
end
end
end
And with that, no issues! I've just been breaking my head over that for the past 2 days. Hope this helps anyone else who has this issue.
Related
In trying to run a setup rake tasks(to populate my dbase). It is telling me that questions must exist. When I do a count on 'Question.count' - it returns 4 - so I know questions exist.
What am I missing? typo? syntax? When I look at similiar SO, it shows as some sort of typo but I am not seeing it.
Here is the code that is not working:
def add_option_group
puts " * Add Option Groups...\n"
OptionGroup.transaction do
create_option_group(
option_group_name: "Always-Never",
question_id: Question.find_by(question_name: "Do you have an updated photo?")
)
create_option_group(
option_group_name: "Yes-No",
question_id: Question.find_by(question_name: "Do you have a bio saved (updated in last 12 months)?")
)
end
end
def create_option_group(options={ })
puts " * CREATE OptionGroup Section...\n"
option_group_attributes = {}
attributes = option_group_attributes.merge options
option_group = OptionGroup.create! attributes
option_group.save!
option_group
end
I am getting this error message:
Add Option Groups...
CREATE OptionGroup Section...
rake aborted!
ActiveRecord::RecordInvalid: Validation failed: Questions must exist
/Users/axxx/workspace/fresh-assess/lib/tasks/setup.rake:314:in create_option_group' /Users/axxx/workspace/fresh-assess/lib/tasks/setup.rake:298:in block in add_option_group'
/Users/axxx/workspace/fresh-assess/lib/tasks/setup.rake:297:in add_option_group' /Users/axxx/workspace/fresh-assess/lib/tasks/setup.rake:51:in create_sample_data!
Migration files:
***** migrations ******
class CreateOptionGroups < ActiveRecord::Migration[6.1]
def change
create_table :option_groups do |t|
t.bigint :question_id
t.text :option_group_name
t.timestamps
end
end
end
class CreateQuestions < ActiveRecord::Migration[6.1]
def change
create_table :questions do |t|
t.bigint :assessment_section_id
t.bigint :input_type_id
t.text :question_name
t.string :question_subtext
t.boolean :question_required_yn
t.boolean :answer_required_yn
t.boolean :allow_multiple_options_answers_yn
t.integer :dependent_question_id
t.integer :dependent_question_option_id
t.integer :dependent_answer_id
t.timestamps
end
end
end
Here is schema
t.bigint "question_id"
t.bigint "option_choice_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "questions", force: :cascade do |t|
t.bigint "assessment_section_id"
t.bigint "input_type_id"
t.text "question_name"
t.string "question_subtext"
t.boolean "question_required_yn"
t.boolean "answer_required_yn"
t.boolean "allow_multiple_options_answers_yn"
t.integer "dependent_question_id"
t.integer "dependent_question_option_id"
t.integer "dependent_answer_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
Add foreign key:
class ForeignMoreKeysToModels < ActiveRecord::Migration[6.1]
def change
add_foreign_key :option_groups, :questions, validate: false
add_foreign_key :option_choices, :option_groups, validate: false
end
end
In the model:
class Question < ApplicationRecord
has_one :assessment_section
belongs_to :assessment_section, optional: true
has_many :option_groups
end
class OptionGroup < ApplicationRecord
has_many :option_choices
belongs_to :questions
end
What am I missing?
thx.
Two issues:
In the OptionGroup class, it should say belongs_to :question.
Try adding .id to the question lookup:
create_option_group(
option_group_name: "Always-Never",
question_id: Question.find_by(question_name: "Do you have an updated photo?").id
)
I am extremely new to Ruby on Rails and while I am learning a lot fairly quickly, I have run into some issues with the proper syntax to interact between the Model and Controller layers. I ham working on a toy project that simulates a Jurassic Park management app. The db schema is as follows:
schema.rb
ActiveRecord::Schema.define(version: 2021_01_24_134125) do
create_table "cages", force: :cascade do |t|
t.string "name"
t.integer "max_capacity"
t.integer "number_of_dinosaurs"
t.string "power_status"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "dinosaurs", force: :cascade do |t|
t.string "name"
t.string "species"
t.string "diet_type"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "cage_id", null: false
t.index ["cage_id"], name: "index_dinosaurs_on_cage_id"
end
add_foreign_key "dinosaurs", "cages"
end
I have already written a few helper methods in both the dinosaur and cage models, but when I try to actually use them in the cage.controller or dinosaur.controller, I run into some issues with how to do so. These are the methods below:
cage.rb
class Cage < ApplicationRecord
has_many :dinosaurs
validates :name, :max_capacity, :power_status, presence: true
validates_uniqueness_of :name
def dinosaur_count
dinosaurs.count
end
def at_capacity?
return dinosaur_count == max_capacity
end
def is_powered_down?
return power_status == "DOWN"
end
def has_herbivore
dinosaurs.where(diet_type:"Herbivore").count > 0
end
def has_carnivore
dinosaurs.where(diet_type:"Carnivore").count > 0
end
def belongs_in_cage(diet)
return true if dinosaur_count == 0
return false if diet != 'Carnivore' && has_carnivore
return false if diet != 'Herbivore' && has_herbivore
return true if dinosaurs.where(diet_type: diet).count > 0
return false
end
def has_dinosaurs?
return dinosaur_count > 0
end
end
dinosaur.rb
class Dinosaur < ApplicationRecord
belongs_to :cage
validates :name, :species, :diet_type, :cage_id, presence: true
validates_uniqueness_of :name
def set_cage(c)
return false if c.at_capacity?
cage = c
end
def move_dino_to_powered_down_cage(c)
return false if c.is_powered_down?
cage = c
end
def is_herbivore?
return diet_type == "Herbivore"
end
def is_carnivore?
return diet_type == "Carnivore"
end
end
I have tried something like this in the cage.controller update, but it is ignored when updating a cage's power status for example.
if #cage.is_powered_down? == "true"
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #cage.errors, status: :unprocessable_entity }
else
format.html { redirect_to #cage, notice: "Cage was successfully updated." }
format.json { render :show, status: :ok, location: #cage }
end
Would anyone be able to assist me with this at all?
Ah yes, well #cage.is_powered_down? is returning a Boolean, so you can just do:
if #cage.is_powered_down?
I'm trying to "edit a gig" on my app but it's giving me the error that the gig has no user_id. Creating a new gig is no issue. I feel like it's just poor syntax I didn't look over correctly but I have no idea. I've tried everything.
NoMethodError at /gigs/:id/edit
undefined method `user_id' for nil:NilClass
file: gigs_controller.rb location: block in <class:GigController> line: 43
Below is my App Controller, Gig Controller, schema, and log.
Thanks!
APP CONTROLLER
require './config/environment'
class ApplicationController < Sinatra::Base
configure do
set :public_folder, 'public'
set :views, 'app/views'
enable :sessions
set :session_secret, "secret"
end
get '/' do
erb :welcome
end
get '/logout' do
session.clear
redirect to '/'
end
#helpers
helpers do
def logged_in?
!!current_user
end
def current_user
User.find_by_id(session[:user_id])
end
def is_authorized?(id)
current_user.id == id.to_i
end
end
end
GIG CONTROLLER
class GigController < ApplicationController
get '/gigs' do
if logged_in?
#gigs = Gig.all
erb :'/gigs/index'
else
redirect to '/signup'
end
end
get '/gigs/new' do
if logged_in?
#gigs = Gig.all
erb :'gigs/new'
else
redirect to '/login'
end
end
post '/gigs' do
if logged_in?
#gig = current_user.gigs.create(bands: params[:bands], location: params[:location], date: params[:date], time: params[:time])
"Event has been added."
redirect "/gigs"
else
"When creating a new Event, please provide Artists, a Location, a date and a time."
redirect '/gigs'
end
end
get '/gigs/:id' do
if logged_in?
#gig = Gig.find(params[:id])
erb :"gigs/show"
else
redirect '/login'
end
end
get '/gigs/:id/edit' do
if logged_in?
#gig = Gig.find(params[:id])
if current_user.id == #gig.user_id
erb :"gigs/edit"
else
"You are not authorized to edit this Event."
redirect to '/login'
end
end
end
end
SCHEMA-
ActiveRecord::Schema.define(version: 20200209173236) do
create_table "genres", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "gigs", force: :cascade do |t|
t.string "bands"
t.string "location"
t.date "date"
t.string "time"
t.integer "user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
ERROR-
D, [2020-02-10T13:53:35.237402 #11377] DEBUG -- : ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
D, [2020-02-10T13:53:35.257906 #11377] DEBUG -- : User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 4]]
D, [2020-02-10T13:53:35.262209 #11377] DEBUG -- : Gig Load (0.1ms) SELECT "gigs".* FROM "gigs" WHERE "gigs"."id" = ? LIMIT 1 [["id", nil]]
2020-02-10 13:53:35 - ActiveRecord::RecordNotFound - Couldn't find Gig with 'id'=:
/Users/melc/.rvm/gems/ruby-2.6.1/gems/activerecord-4.2.11.1/lib/active_record/core.rb:155:in `find'
/Users/melc/nyc-shows/app/controllers/gigs_controller.rb:42:in `block in <class:GigController>'
i'm learning Rails and i'm doing an exercise to practice associations and migration files.
Currently, trying to make a models between users, auction item, and bids.
So far for the migrate files I have the following:
class CreateItem < ActiveRecord::Migration
def change
create_table :auction do |t|
t.string :item_name
t.string :condition
t.date :start_date
t.date :end_date
t.text :description
t.timestamps
end
end
end
class CreateBids < ActiveRecord::Migration
def change
create_table :bids do |t|
t.integer :user_id
t.integer :auction_id
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.string :username
t.string :password_digest
t.timestamps
end
end
end
These are the following models:
class Bid < ActiveRecord::Base
belongs_to :bidder, class_name: "User", foreign_key: "bidder_id"
belongs_to :auction
end
class User < ActiveRecord::Base
has_many :bids
has_many :auctions, :foreign_key => 'bidder_id'
has_secure_password
end
class Auction < ActiveRecord::Base
belongs_to :seller, class_name: "User", foreign_key: :user_id
has_many :bids
has_many :bidders, through: :bids
end
Any suggestions or opinions? I'm currently trying to test the tables but auctions doesn't seem to be working...
Specifically, my auction table can't seem to find a user_id and therefore a user doesn't have any auctions.
foreign_key refers to the _id (by default) or any unique attribute used to associate the models.
I can't see bidder model, you need to replace them with user_id as they are associated to user model.
Refer for more details belongs_to
class CreateBids < ActiveRecord::Migration
def change
create_table :bids do |t|
t.integer :user_id **do not think this is correct**
t.integer :auction_id **or this one**
t.timestamps
end
end
end
You want to use something more along the lines of the following
class CreateGames < ActiveRecord::Migration[5.0]
def change
create_table :games do |t|
t.integer :total_time
t.references :version, foreign_key: true **#this is how a foreign key should be declared**
t.integer :total_points
t.timestamps
end
end
end
Alternatively, if you want to change things in future migrations you can always add a reference:
def change
add_reference :levels, :version, foreign_key: true
end
How can I set one of my database table to created_at as default value. I did this but didn't work, I have checked in the DB and the value of code is null.
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.string :title
t.string :location
t.text :description
t.date :occurs_on
t.string :code, :default => Event::created_at
t.timestamps
end
end
end