in my search.html.haml, I want the user have the ability to click on the teacher name and it will lead them to the teacher show page. However, it also requires me to have the school_id because a teacher belongs to a school, and a school has many teachers. Now, I am wondering if there is a way for me to a the school_id to the path without breaking the application. The error that rails is throwing at me now is:
No route matches {:action=>"show", :controller=>"teachers", :id=>"1",
:school_id=>nil} missing required keys: [:school_id]
Here are my files:
search.html.haml:
.text-center
/ No search results announcement/notification
- if #teachers.blank?
%h2 Xin lỗi, hệ thống chúng tôi không có thông tin về giảng viên mà bạn muốn tìm.
- else
- #teachers.each do |teacher|
%h2= link_to teacher.fullName, school_teacher_path(#school, teacher)
#note
%em
Khoa #{teacher.department}, trường #{teacher.school.name}
teachers_controller.rb:
class TeachersController < ApplicationController
before_action :find_school, except: [:welcome, :search]
before_action :find_teacher, only: [:show, :edit, :update, :destroy]
def welcome
end
def show
end
def search
if params[:search].present?
#teachers = Teacher.search(params[:search], fields: [:fullName])
else
#teachers = nil
end
end
def new
#teacher = #school.teachers.build
end
def create
#teacher = #school.teachers.create(teacher_params)
#teacher.save
redirect_to(#school)
end
def edit
end
def update
#teacher.update(teacher_params)
redirect_to(#school)
end
private
def find_school
#school = School.find(params[:school_id])
end
def find_teacher
#teacher = Teacher.find(params[:id])
end
def teacher_params
params.require(:teacher).permit(:firstName, :lastName, :middleName, :department, :school_id, :fullName)
end
end
teacher.rb:
class Teacher < ActiveRecord::Base
belongs_to :school
has_many :ratings
searchkick
def name
"#{lastName} #{middleName} #{firstName}"
end
def to_s
name
end
end
school.rb:
class School < ActiveRecord::Base
has_many :teachers, dependent: :destroy
# searchkick
end
routes.rb:
Rails.application.routes.draw do
devise_for :users
resources :schools do
# collection do
# get 'search'
# end
resources :teachers do
collection do
get 'search'
end
end
end
resources :teachers do
collection do
get 'search'
end
resources :ratings
end
root 'teachers#welcome'
end
school_teacher_path is called with a #school that is nil since find_school is not used for search. You probably want to replace #school with teacher.school: school_teacher_path(teacher.school, teacher).
Related
When I try to access app/views/companies/courses/show.html.erb(which is redirected after app/views/companies/courses/new.html.erb), rails server says that it cannot find a course without an ID.
Also, when I run Course.all on rails console, the courses have the correct id, the correct description and the correct company id but no name attribute.
App/controllers/companies/courses_controller:
class Companies::CoursesController < ApplicationController
before_action :authenticate_company!
def new
#course = Course.new
end
def create
#course = current_company.courses.create(course_params)
if #course.save
redirect_to companycourse_path(:course => #course.id)
else
render 'new'
end
end
def show
#course = current_company.courses.find(params[:id])
end
def index
#courses = current_company.courses.all
end
private
def course_params
params.require(:course).permit(:title, :description)
end
end
App/models/course.rb:
class Course < ApplicationRecord
belongs_to :company
end
App/models/company.rb:
class Company < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :courses
end
Config/routes.rb:
Rails.application.routes.draw do
devise_for :companies
devise_for :users
root 'static_pages#home'
get 'users/:id' => 'users#show'
resources :users, only: [:show]
get 'companies/:id' => 'companies#show'
resources :companies, only: [:show] do
resources :courses, only: [:show,:new,:create,:index]
end
devise_scope :user do
get 'signup', to: 'users/registrations#new'
get 'login', to: 'users/sessions#new'
end
devise_scope :company do
get 'companysignup', to: 'companies/registrations#new'
get 'companylogin', to: 'companies/sessions#new'
get 'newcourse', to:'companies/courses#new'
post 'newcourse', to:'companies/courses#create'
get 'companycourse', to:'companies/courses#show'
get 'companycoursesindex', to:'companies/courses#index'
end
end
I had a similar problem building my app not long ago and my problem was coming from controllers.
In your routes.rb I would add resources :companies, :has_many => :courses.I also would add a validation to your course model in models/course.rb to make sure that when you save it to the database your object has a title: class Course < ApplicationRecord
belongs_to :company validates :title, presence: :true
end
Also try using this or something along lines in your courses_controller.rb instead of your current code:
def create
#company = find_company
#course = Course.new(course_params)
#course.company_id = current_company.id
if #course.save
your conditions here
else
your conditiona here
end
end
private
def find_company
params.each do |name, value|
if name == 'company_id'
return #company = Company.find(value.to_i)
end
end
nil
end
I hope it helps.
I'm completing this airbnb clone course (https://code4startup.com/projects/build-airbnb-with-ruby-on-rails-level-1) but have diverted a bit in order to complete my own project; a marketplace for education camps. Therefore I've added an additional model 'Courses'. It now has User>Listing>Course. This Courses model is working in rails console but not saving to my database when I'm running the server. Any suggestions would be appreciated...
Error Message
ActiveRecord::RecordInvalid in CoursesController#create
Validation failed: Listing must exist
Models
class User < ApplicationRecord
has_many :listings
has_many :courses, :through => :listings
end
class Listing < ApplicationRecord
belongs_to :user
has_many :courses
validates :listing_type, presence: true
validates :course_type, presence: true
validates :accommodate, presence: true
end
class Course < ApplicationRecord
belongs_to :listing
validates :curriculum_type, presence: true
validates :course_places, presence: true
end
Course Controller
class CoursesController < ApplicationController
before_action :set_course, except: [:index, :new, :create]
before_action :authenticate_user!, except: [:show]
def index
#courses = current_user.courses
end
def new
#course = current_user.courses.build
end
def create
#course = current_user.courses.build(course_params)
if #course.save!
redirect_to course_listing_path(#course), notice: "Saved..."
else
render :new, notice: "Something went wrong..."
end
end
def show
end
def listing
end
def pricing
end
def description
end
def photo_upload
end
def amenities
end
def location
end
def update
if #course.update(course_params)
flash[:notice] = "Saved..."
else
flash[:notice] = "Something went wrong..."
end
redirect_back(fallback_location: request.referer)
end
private
def set_course
#course = Course.find(params[:id])
end
def course_params
params.require(:course).permit(:name, :curriculum_type, :summary, :address, :course_places, :start_date, :finish_date, :price)
end
end
Routes
Rails.application.routes.draw do
root 'pages#home'
devise_for :users,
path: '',
path_names: {sign_in: 'login', sign_out: 'logout', edit: 'profile', sign_up: 'registration'},
controllers: { omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations' }
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :users, only: [:show]
resources :listings, except: [:edit] do
member do
get 'listing'
get 'pricing'
get 'description'
get 'photo_upload'
get 'amenities'
get 'location'
end
end
resources :courses, except: [:edit] do
member do
get 'listing'
get 'pricing'
get 'description'
get 'photo_upload'
get 'amenities'
get 'location'
end
end
end
below you can read my comments with the # sign
You are trying to save an object Course that has belongs_to listings so it is expected that it has as course.listing_id the id of an existing Listing
def create
#course = current_user.courses.build(course_params)
# You need to set #course.listing_id to an existing Listing
# You need to find that listing and save it in a variable.
# I am not getting into your logic, because your code is confused and need many adjustments
listing = Listing.find() # include hear your logic to find an existing listing from the db
#course.listing_id = listing.id
if #course.save!
redirect_to course_listing_path(#course), notice: "Saved..."
else
render :new, notice: "Something went wrong..."
end
end
Hello I have an exercise app where a user should be able to Like some products.
I could find a way to display the product he liked, but I really can't figure how to create and make work the like button.
I am not using any gem, I wan't to understand how to do it from Scratch.
Here are my models:
class User < ApplicationRecord
has_many :likes
has_many :liked_products, through: :likes, source: :product
end
class Product < ApplicationRecord
has_many :likes
end
class Like < ApplicationRecord
belongs_to :user
belongs_to :product
end
In my view product show where I want the like button:
<h1><%= #product.name %></h1>
<%= link_to "Like", product_likes_path(#product), method: :put, remote: true %>
my routes:
Rails.application.routes.draw do
root to: 'visitors#index'
devise_for :users
resources :users
resources :products do
resource :likes
end
end
That's my products controller, I think things must come in here but I don't know HOW!
class ProductsController < ApplicationController
before_action :find_product, only: :show
def index
#products = Product.all
end
def show
##product.like => gives an error 404
end
private
def find_product
#product = Product.find(params[:id])
end
end
I had created a likes controller but it seems it is not useful.... So... I gave up there...
class LikesController < ApplicationController
def new
#like = Like.new(like_params)
end
def create
#like = Like.new(like_params)
end
private
def like_params
params.require(:likes).permit(:user_id, :product_id)
end
end
I would really enjoy some light on this please :)
Finally found out how to set the controller
class LikesController < ApplicationController
def create
#user = current_user.id
#product = params[:product_id]
likes = {user_id: #user, product_id: #product}
#like = Like.new(likes)
#like.save!
if #like.save
redirect_to user_path(#user)
else
redirect_to product_path
end
end
end
the buttton
<%= link_to "Like", product_likes_path(#product), method: :post %>
routes
Rails.application.routes.draw do
root to: 'products#index'
devise_for :users
resources :users
resources :users do
resources :products do
resources :likes
end
end
end
You could try something along these lines:
Routes:
Rails.application.routes.draw do
root to: 'visitors#index'
devise_for :users
resources :users do
resources :products do
resources :likes
end
end
resources :products do
resource :likes
end
end
Which will give you something like:
... other routes ...
user_product_likes GET /users/:user_id/products/:product_id/likes(.:format) likes#index
POST /users/:user_id/products/:product_id/likes(.:format) likes#create
new_user_product_like GET /users/:user_id/products/:product_id/likes/new(.:format) likes#new
edit_user_product_like GET /users/:user_id/products/:product_id/likes/:id/edit(.:format) likes#edit
user_product_like GET /users/:user_id/products/:product_id/likes/:id(.:format) likes#show
PATCH /users/:user_id/products/:product_id/likes/:id(.:format) likes#update
PUT /users/:user_id/products/:product_id/likes/:id(.:format) likes#update
DELETE /users/:user_id/products/:product_id/likes/:id(.:format) likes#destroy
... other routes ...
Then:
<%= link_to "Like", user_product_likes_path(#user, #product), method: :post, remote: true %>
And in your LikesController:
class LikesController < ApplicationController
def new
#like = Like.new(like_params)
end
def create
#like = Like.new(like_params)
if #like.save
... do something happy
else
... do something sad
end
end
private
def like_params
params.require(:likes).permit(:user_id, :product_id)
end
end
Untested, so buyer beware. You might need to fiddle with your like_params and other stuff.
I created a polymorphic relation in a book reviewing app that I am writing. My app has the nested models: Piece >> Section >> Subsection >> Subsubsection, and I have created a model which belongs to all of these called KeyConcept, my intention being that each of these can have a key concept. When trying to display the "Show" view of the "Piece" model i get the following error:
NameError in Pieces#show
uninitialized constant Piece::Keyconcept
<h5>Summary: </h5><p><%= simple_format(#piece.summary) %></p>
<br/>
<% #piece.keyconcepts.each do |concept| %>
<li>
<%= link_to concept.definition, r, class: 'section_name' %>
</li>
So the routes.rb file looks like this:
resources :pieces do
resources :sections do
resources :subsections do
resources :subsubsections
end
end
resources :links
end
resources :pieces, :sections, :subsections, :subsubsections do
resources :connections, only: [:index, :new, :edit, :update, :destroy, :create]
resources :keyconcepts, only: [:index, :new, :edit, :update, :destroy, :create, :show]
end
the model.rb files look like this:
in models/concerns/conceptable.rb
module Conceptable
extend ActiveSupport::Concern
included do
has_many :keyconcepts, as: :conceptable
end
end
key_concept.rb
class KeyConcept < ActiveRecord::Base
belongs_to :conceptable, polymorphic: true
end
piece.rb
class Piece < ActiveRecord::Base
include Connectable
include Conceptable
has_many :sections
has_many :subsections, through: :sections
has_many :links
end
I don't know if this is a problem in the controller?
class KeyconceptsController < ApplicationController
include KeyconceptsHelper
def whereami
if params[:piece_id]
#piece = Piece.find(params[:piece_id])
here = #piece
parameter = :piece_id
type = "Piece"
elsif params[:section_id]
#section = ::Section.find(params[:section_id])
#piece = #section.piece_id
here = #section
parameter = :section_id
type = "Section"
elsif params[:subsection_id]
#subsection = Subsection.find(params[:subsection_id])
#section = #subsection.section_id
#piece = Section.find(id=#section).piece_id
here = #subsection
parameter = :subsection_id
type = "Subsection"
elsif params[:subsubsection_id]
#subsubsection = Subsubsection.find(params[:subsubsection_id])
#subsection = #subsubsection.subsection_id
#section = Subsection.find(id=#subsection).section_id
#piece = Section.find(id=#section).piece_id
here = #subsubsection
parameter = :subsubsection_id
type = "Subsubsection"
end
end
def redirect
if type == "Piece"
redirect_to piece_path(#piece)
elsif type == "Section"
redirect_to piece_section_path(#piece, #section)
elsif type == "Subsection"
redirect_to piece_section_subsection_path(#piece, #section, #subsection)
elsif type == "Subsubsection"
redirect_to piece_section_subsection_subsubsection_path(#piece, #section, #subsection, #subsubsection)
end
end
def index
whereami.call
end
def show
whereami.call
r = redirect.call
end
def new
#keyconcept = KeyConcept.new
#keyconcept.conceptable_id = here.id
end
def create
whereami.call
#keyconcept = KeyConcept.new(keyconcept_params)
#keyconcept.conceptable_id = params[parameter]
#keyconcept.conceptable_type = type
#keyconcept.save
redirect.call
end
def destroy
here.destroy
redirect.call
flash.notice = "#{type} '#{here.name}' from '#{#piece.name}' deleted!"
end
def edit
whereami.call
end
def update
whereami.call
here.update(keyconcept_params)
flash.notice = "#{type} '#{here.name}' Updated!"
redirect.call
end
end
I have reloaded the console and I get the same error. I have also tried to do a few things in the console and this: Piece.first.keyconcepts, does not work (i get the same NameError: uninitialized constant Piece::Keyconcept) however this: KeyConcept.first DOES work, i even though i get nil because i havent created any instances yet.
I notice that, in the error message it says Keyconcept and not camelcase KeyConcept. I think this is where the problem lies but I do not have enough experience to understand it.
I would appreciate help in solving this!
The problem here is you are not following proper conventions
Change your model name to Keyconcept and file_name to keyconcept.rb
keyconcept.rb
class Keyconcept < ActiveRecord::Base
belongs_to :conceptable, polymorphic: true
end
OR
You will need to change keyconcepts to key_concepts in the following places:
routes
resources :keyconcepts
controller name
class KeyConceptsController < ApplicationController
...
end
controller file name
key_concepts_controller.rb
strong params
def key_concept_params
params.require(:key_concept).permit(:your, :params)
end
associations
has_many :key_concepts
I have the Teacher model, and I am using the searchkick for this model. The first problem is when I search for a particular teacher, if the teacher is in model, it will not only return that teacher but also the rest of the teachers in my model. I did some research on the internet and couldn't find the solution for my case. Therefore, I really need your help guys.
Here are some of my files, just in case you need to see them, and I think you do.
teachers_controller.rb:
class TeachersController < ApplicationController
before_action :find_school
before_action :find_teacher, only: [:show, :edit, :update, :destroy]
def show
end
def search
if params[:search].present?
#teachers = #school.teachers.search(params[:search], fields: [{fullName: :exact}])
else
#teachers = []
end
end
def new
#teacher = #school.teachers.build
end
def create
#teacher = #school.teachers.create(teacher_params)
#teacher.save
redirect_to(#school)
end
def edit
end
def update
#teacher.update(teacher_params)
redirect_to(#school)
end
private
def find_school
#school = School.find(params[:school_id])
end
def find_teacher
#teacher = Teacher.find(params[:id])
end
def teacher_params
params.require(:teacher).permit(:firstName, :lastName, :middleName, :department, :school_id)
end
end
search.html.haml:
.text-center
/ No search results announcement/notification
- if #teachers.blank?
%h2 Xin lỗi, hệ thống chúng tôi không có thông tin về giảng viên mà bạn muốn tìm.
- else
- #school.teachers.each do |teacher|
%h2= link_to teacher.to_s, school_teacher_path(#school, teacher)
%br/
.text-center
= link_to("Trang Trước", school_url(#school), class: "btn btn-default btn-xs")
= link_to("Trang Chủ", root_path, class: "btn btn-default btn-xs")
teacher.rb:
class Teacher < ActiveRecord::Base
belongs_to :school
has_many :ratings
searchkick word_start: [:firstName, :lastName, :middleName]
def name
"#{lastName} #{middleName} #{firstName}"
end
def to_s
name
end
end
routes.rb:
Rails.application.routes.draw do
devise_for :users
resources :schools do
collection do
get 'search'
end
resources :teachers do
collection do
get 'search'
end
end
end
resources :teachers do
resources :ratings
end
root 'schools#index'
end