Couldn't find Student with 'student_id'= RUBY ON RAILS - ruby-on-rails

I am trying to pull up an edit page for my simple system.
Here's my controller for student look like:
class StudentsController < ApplicationController
def index
#students = Student.newest_first
end
def show
#student = Student.find(params[:student_id])
end
def new
#student = Student.new
end
def create
#student = Student.new(student_params_create)
if #student.save
flash[:notice] = "Student record created successfully"
redirect_to(students_path)
else
render('new')
end
end
def edit
#student = Student.find(params[:student_id])
end
def update
#student = Student.find(params[:student_id])
if #student.update_attributes(student_params_update)
flash[:notice] = "Students updated"
redirect_to(students_path)
else
render('edit')
end
end
def delete
#student = Student.find(params[:student_id])
end
def destroy
#student = Student.find(params[:student_id])
#student.destroy
end
private
def student_params_create
params.require(:student).permit(:first_name, :last_name, :birthday, :email, :subjects, :username, :password)
end
def student_params_update
params.require(:student).permit(:first_name, :last_name, :birthday, :email, :subjects)
end
end
And I am trying to here's my index page where I can click edit on my student.
<% #students.each do |student|%>
<%= student.first_name %>
<%= student.student_id %>
<%= link_to("Show", student_path(student), :class => 'action show') %>
<%= link_to("Edit", edit_student_path(student), :class => 'action edit') %>
<%= link_to("Delete", delete_student_path(student), :class => 'action delete') %>
<% end %>
For my form edit, I got the ff:
<h2>Update Subject</h2>
<%= form_for(#student) do |f| %>
<%= f.text_field(:first_name) %>
<%= f.datetime_select(:created_at, :order => [:month, :day, :year]) %><
<%= f.submit("Update Subject") %>
<% end %>
When I tried to go to my resource for students: http://localhost:3000/students/
And click on one of my students I got the ff: error:
Any idea what am I doing wrong????
EDIT:
I set the 'id' to false during migration.
def up
create_table :students, :id => false do |t|
t.integer "student_id",:primary_key => true
t.string "first_name", :limit => 25
t.string "last_name", :limit => 50
t.string "email", :default => ' ', :null => false
t.string "birthday"
t.string "subjects"
t.string "teachers"
t.string "username", :limit => 25
t.string "password_digest"
t.timestamps
end
reversible do |dir|
dir.up { execute "ALTER TABLE students AUTO_INCREMENT = 1000" }
end
# execute "CREATE SEQUENCE students_student_id_seq OWNED BY students.student_id INCREMENT BY 1 START WITH 1001"
end
def down
drop_table :students
# execute "DELETE SEQUENCE students_student_id_seq"
end
Routes:
resources :students do
member do
get :delete
end
end

UPDATE
You could need to update your routes.rb with
resources :students, param: :student_id
And your Student model with
self.primary_key = :student_id
NOTE that you're having the ActiveRecord::RecordNotFound exception because find method throws exception when it can't actually find the record needed. Try to use find_by_id method instead. It will just return nil in that situation. You'll be able to handle it easily and your app will not crash here. So you could edit your show action like this
def show
#student = Student.find_by_id(params[:student_id])
end

Related

How to call worker role permission through role_permission

I'm doing a role permission edit function. It didn't have error but the logic of the code have some problem.
It didn't update the permission but update whole role_permission so it came out like image 1 & 2, it keep update many times.
I need to get the worker role_permission then check if that the permission already have?, if have then no need to add, if no then need to add(update). How can i check it at role controller update there?
Role controller
def edit
#role = Role.find(params[:id])
#role.company_id = params[:company_id]
#permissions = Permission.all
end
def update
#role = Role.find(params[:id])
#company_id = Company.find(params[:role][:company_id])
if #role.update!(role_params)
permission_ids = params[:permission_ids]
permission_ids.each do |permission_id|
RolePermission.update(role_id: #role.id, permission_id: permission_id)
end
flash[:success] = "Profile updated"
redirect_to #role
else
render 'edit'
end
end
Edit.html.erb
<% provide(:title, "Edit Roles") %>
<h1 class="dashboard">Update Role</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: #role, local: true) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= #permissions.each do |permission|%>
<%= check_box_tag 'permission_ids[]', permission.id%>
<%= f.label :permission_name, permission.name %>
<% end %>
<%= f.hidden_field :company_id , value: 2%>
<%= f.submit "Save changes", class: "btn btn-secondary bottom" %>
<% end %>
</div>
</div>
RolePermission migration table
create_table "role_permissions", force: :cascade do |t|
t.integer "role_id"
t.integer "permission_id"
t.integer "company_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
parameter pass in console
parameter pass in console
Update
roles controller (role_params)
def role_params
params.require(:role).permit(:name, :company_id)
end
console logs when update role
console log
console log
Hi since you want Update/Add permissions related to roles.
can do it with the help of first_or_initialize:
def update
#role = Role.find(params[:id])
#company_id = Company.find(params[:role][:company_id])
if #role.update!(role_params)
permission_ids = params[:permission_ids]
permission_ids.each do |permission_id|
role_permissions = #role.role_permissions.where(permission_id: permission_id).first_or_initialize
role_permissions.save
end
flash[:success] = "Profile updated"
redirect_to #role
else
render 'edit'
end
end
Read more about first_or_initialize
OR
you should have the following associations with the below models:
# role.rb
has_many :role_permissions, dependent: :destroy
has_many :permissions, through: :role_permissions, source: :permission
# role_permission.rb
belongs_to :role
belongs_to :permission
Then in your roles_controller.rb should have below:
def update
#role = Role.find(params[:id])
#company_id = Company.find(params[:role][:company_id])
if #role.update!(role_params)
flash[:success] = "Profile updated"
redirect_to #role
else
render 'edit'
end
end
def role_params
params.require(:role).permit(:name, :company_id, permission_ids: [])
end

ROR Active Record not save data correcty

Hi guys i have a problem and i dont' know how to solve it, i'm really new on the ROR's world.
preamble : each municiplaty has many itinerary, so :
1) i've created the itinerary table with this migration :
class CreateItineraries < ActiveRecord::Migration
def change
create_table :itineraries do |t|
t.string :title
t.string :json
t.integer :muncipality_id
t.text :description
t.boolean :published, :default => true, :null => false
t.timestamps null: false
end
end
end
2) i've added the municipality_id reference to the itineraries table, with this migration :
class AddMunicipalityIdToItineraries < ActiveRecord::Migration
def change
add_reference :itineraries, :municipality, index: true, foreign_key: true
end
end
3) i've created another table for the translations of itineraries :
class AddTranslationTablesForItineraries < ActiveRecord::Migration
def up
Itinerary.create_translation_table!({
:title => :string
}, {
:migrate_data => true
})
end
def down
add_column :itineraries, :title, :string
Itinerary.drop_translation_table! :migrate_data => true
end
end
now, the problem is when i try to save the data from the relative simple_form, it save the itinerary's title only in the translations table, why?!
here the code of the simple_form :
<%= simple_form_for [:admin, #municipality, #itinerary], url: #url, :html => {:class => ''} do |f| %>
<%= render 'application/translation_form_heading' %>
# ...
<%= f.input :title, required: true %>
<%= f.input :description, label: 'description', :as => :ckeditor, :input_html => {ckeditor: {toolbar: get_toolbar('default')},:rows => 15} %>
<%= f.input :json, required: true, label: 'GeoJSON', as: :text, :input_html => {:rows => 15} %>
# ...
<button type="submit" class="btn btn-primary pull-right">Save itinerary</button>
<% end %>
maybe it's a newbie question, but i don'r really know how to solve it, thank you!
edit : here the code of the itinerariesController :
class Admin::ItinerariesController < InheritedResources::Base
layout 'admin'
before_filter :authenticate_admin!
before_filter :set_page_title
load_and_authorize_resource
actions :all, :except => [:show]
belongs_to :municipality
def index
#itineraries = Itinerary.ordered
end
def new
#url = admin_municipality_itineraries_path(params[:municipality_id])
new!
end
def edit
#url = admin_municipality_itinerary_path(params[:municipality_id], params[:id])
edit!
end
def update
unless params[:translate_to].blank?
I18n.with_locale(params[:translate_to]) {
update!
}
else
update!
end
end
def set_page_title
#page_title = PointOfInterest.model_name.human(:count => 2).titleize
end
def create
create! {
admin_municipality_itineraries_path
}
end
private
def permitted_params
params.permit(:itinerary => [:id, :title, :json,:description, :municipality_id] )
end
end
Try to update this one in controller
private
def permitted_params
params.permit(:itinerary => [:id, :title, :description, :municipality_id, :json] )
end
You need to permit JSON value in params always at the end

(Unable to autoload constant Cflag, expected /app/app/models/cflag.rb to define it)

I have a very basic Photo and Comments model that works and then I have a built a Cflags model that is used to flag comments. I am getting the following error from Heroku log when I visit the photos/show.html.erb view.
LoadError (Unable to autoload constant Cflag, expected /app/app/models/cflag.rb to define it)
photos/show.html.erb
.
.
<% #photo.comments.each do |comment| %>
<%= form_for([comment, Cflags.new]) do |f| %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.submit "Report Inappropiate" %>
<% end %>
<% end %>
PhotosController
def show
#photo = Photo.approved.find(params[:id])
end
CommentsController
def create
#photo = Photo.find(params[:photo_id])
#comment = #photo.comments.build(comment_params)
#comment.save
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end
class CFlag < ActiveRecord::Base
belongs_to :comment, counter_cache: true
belongs_to :user, counter_cache: true
validates :user_id, presence: true
validates :comment_id, presence: true
validates :user_id, uniqueness: {
scope: [:comment_id],
message: 'You can only flag a comment once. Thank you for your feedback.'
}
default_scope -> { order(created_at: :desc) }
end
class CflagsController < ApplicationController
before_action :logged_in_user
def create
#comment = Comment.find(params[:comment_id])
#cflag = #comment.cflags.build(cflag_params)
if #cflag.save
if #comment.cflags_count > 1
#comment.update_attribute(:approved, false)
flash[:success] = "Flag created! Comment ##{#comment.id} has been removed for review. Thank you for your feedback"
redirect_to :back
else
flash[:success] = "Flag created! Thank you for your feedback"
redirect_to :back
end
else
redirect_to :back, notice: #cflag.errors.full_messages
end
end
private
def cflag_params
params.require(:cflag).permit(:user_id, :comment_id).merge(user_id: current_user.id)
end
end
resources :photos do
resources :comments do
resources :cflags
end
end
create_table "cflags", force: :cascade do |t|
t.integer "comment_id"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "cflags", ["comment_id"], name: "index_cflags_on_comment_id"
add_index "cflags", ["user_id"], name: "index_cflags_on_user_id"
If I change the form to:
<% #photo.comments.each do |comment| %>
<%= form_for([comment, comment.cflags.build]) do |f| %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.submit "Report Inappropiate" %>
<% end %>
<% end %>
I get the same error:
LoadError (Unable to autoload constant Cflag, expected /app/app/models/cflag.rb to define it):
There is a typo in the controller name.
Your model is CFlag with F uppercase but your controller has f lowercase.
Change it to CFlagsController
class CFlagsController < ApplicationController
before_action :logged_in_user
def create
...
end
end

No route matches {:action=>"show", :controller=>"items"} missing required keys: [:id]

Update: I've been trying to debug my files, so most of the files have changed recently
I am getting a strange error when trying to use a "new" action to my items_controller. Essentially, a wishlist has_many items and an item belongs_to wishlist. The error message is as follows:
Code
Here is my items_controller:
class ItemsController < ApplicationController
def show
#item = Item.find(params[:id])
end
def new
#item = Item.new
end
def create
#item = Item.new(item_params)
if #item.save
redirect_to "/wishlist", :notice => "Success!"
else
redirect_to "/wishlist", :notice => "Failure, try again later!"
end
end
def edit
#item = Item.find(params[:id])
end
def update
#item = Item.find(params[:id])
if #item.update_attributes(item_params)
redirect_to(:action => 'show', :id => #item.id)
else
render 'edit'
end
end
private
def item_params
params.require(:item).permit(:name,:size,:qty,:priority)
end
private
def create_params
params.require(:item).permit(:name,:size,:qty,:priority,:wishlist_id)
end
end
And my routes.rb:
Rails.application.routes.draw do
get '/wishlist' => 'wishlists#index', as: :wishlists
get '/wishlist/:id' => 'wishlists#show', as: :wishlist
get '/wishlist_items/new' => 'items#new'
get '/wishlist_items/:id' => 'items#show', as: :items
get '/wishlist_items/:id/edit' => 'items#edit', as: :edit_items
patch '/wishlist_items/:id' => 'items#update'
resources :items
And finally, my new.html.erb for the items model:
<h1>New Item</h1>
<div class="wishlist-new">
<% if true %>
<%= form_for(#item) do |f| %>
<%= f.text_field :name, :placeholder => "Name" %>
<%= f.text_field :size, :placeholder => "Specifications" %>
<%= f.text_field :qty, :placeholder => "Quantity" %>
<%= f.text_field :priority, :placeholder => "Priority" %>
<%= f.text_field :id, :placeholder => "Wishlist ID" %> # changing :id to :wishlist_id doesn't seem to do anything
<%= f.submit "Create Item", class: "btn-submit" %>
<% end %>
<% end %>
</div>
My migration files (so you know how my databases are structured:
# Migration file for items
class CreateItems < ActiveRecord::Migration
def change
drop_table :items
create_table :items do |t|
t.string :name
t.string :size
t.string :qty
t.integer :priority
t.references :wishlist
t.timestamps
end
end
end
# Migration File for Wishlists
class CreateWishlists < ActiveRecord::Migration
def change
drop_table :wishlists
create_table :wishlists do |t|
t.string :title
t.timestamps
end
end
end
Attempts to Debug
It seems like the routes.rb is sending requests to different methods in the items_controller because the error seems to say that /wishlist_items/new is accessing a show method even though its new method takes priority. To support this, the page loads properly when I comment out get '/wishlist_items/:id' => 'items#show', as: :items in the routes file. What happens is the page loads properly, and the Item is created properly (when I fill out the form) except that when I go into the console, it says that the Item created has a property of wishlist_id: nil even though I specified for it to be 1 in the form.
The method mentioned above has two problems: (1) it doesn't work entirely correctly, and (2) it becomes impossible to show a specific Item in the wishlist.
The error occurs before the inner section of the form_for is loaded, so the problem either is (a) a weird routing thing (as mentioned above) or (b) something weird happening to the #item variable.
Thanks in advance!

Ruby on Rails Difficult Form/Associations

I have a Rails 4.2 app which has 'Rooms', 'Bookings' and 'Extras'.
When making a booking it is for a room e.g. website.com/rooms/1/bookings/1
I have extras which I want to be associated with the booking for that room via check-boxes.
How can this be implemented? I've been reading about has_many :foo, :through => :bar associations but I'm not sure if that's the way to go.
The relevant code looks like this:
<!-- app\views\bookings\_form.html.erb -->
<%= form_for([#room, #booking]) do |f| %>
<p>
<%= f.label 'Select Customer:' %>
<%= f.collection_select :user_id, User.all, :id, :customer_name %>
</p>
<p>
<%= f.label 'start_time', 'Start Date and Time:' %>
<%= f.datetime_select :start_time, { minute_step: 15 } %>
</p>
<p>
<%= f.label 'length', 'Length of booking in hours:' %>
<%= f.number_field 'length', min: 1 %>
</p>
<p>
<%= f.label 'Room Price:' %>
<%= number_to_currency #room.price, unit: "£" %>
</p>
<p>
<%= f.label 'Extras:' %>
<%= f.collection_check_boxes :extra_ids, Extra.all, :id, :extra_info %>
</p>
<%= f.submit 'Submit' %>
<% end %>
# app\models\booking.rb
class Booking < ActiveRecord::Base
belongs_to :room
belongs_to :user
has_many :additions
has_many :extras, :through => :additions
end
# app\models\extra.rb
class Extra < ActiveRecord::Base
belongs_to :extracat
has_many :additions
has_many :bookings, :through => :additions
def extra_info
"#{name}"
end
end
# This model is for the has_many through testing I tried
# app\models\addition.rb
class Addition < ActiveRecord::Base
belongs_to :booking
belongs_to :extra
end
# Relevant section of schema
create_table "additions", force: :cascade do |t|
t.integer "booking_id"
t.integer "extra_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "bookings", force: :cascade do |t|
t.datetime "start_time"
t.datetime "end_time"
t.integer "length"
t.integer "room_id"
t.integer "user_id"
t.integer "extra_id"
end
EDIT - The section within the bookings show page.
# app\views\bookings\show.html.erb
<% #booking.extras.each do |e| %>
<%= e.name %>,
<% end %>
EDIT - Adding bookings controller
class BookingsController < ApplicationController
respond_to :html, :xml, :json
before_action :find_room
def index
#bookings = Booking.where("room_id = ? AND end_time >= ?", #room.id, Time.now).order(:start_time)
respond_with #bookings
end
def new
#booking = Booking.new(room_id: #room.id)
end
def create
#booking = Booking.new(params[:booking].permit(:room_id, :start_time, :length))
#booking.room = #room
if #booking.save
redirect_to room_bookings_path(#room, method: :get)
else
render 'new'
end
end
def show
#booking = Booking.find(params[:id])
end
def destroy
#booking = Booking.find(params[:id]).destroy
if #booking.destroy
flash[:notice] = "Booking: #{#booking.start_time.strftime('%e %b %Y %H:%M%p')} to #{#booking.end_time.strftime('%e %b %Y %H:%M%p')} deleted"
redirect_to room_bookings_path(#room)
else
render 'index'
end
end
def edit
#booking = Booking.find(params[:id])
end
def update
#booking = Booking.find(params[:id])
# #booking.room = #room
if #booking.update(params[:booking].permit(:room_id, :start_time, :length))
flash[:notice] = 'Your booking was updated succesfully'
if request.xhr?
render json: {status: :success}.to_json
else
redirect_to resource_bookings_path(#room)
end
else
render 'edit'
end
end
private
def save booking
if #booking.save
flash[:notice] = 'booking added'
redirect_to room_booking_path(#room, #booking)
else
render 'new'
end
end
def find_room
if params[:room_id]
#room = Room.find_by_id(params[:room_id])
end
end
def booking_params
params.require(:booking).permit(:user_id, :extra_id)
end
end
How is it possible to associate the extras with a booking? As so far they are not being saved with the booking into the database. Is this a controller issue?
You're not permitting the parameters correctly - the name is extra_ids. In addition since the parameter is an array you need to permit it like so:
params.require(:booking).permit(:room_id, :start_time, :length, :extra_ids => [])
Personally I recommend setting action controller to raise an error when unpermitted parameters are encountered in development or tests - very easy otherwise to miss the log messages

Resources