uninitialized constant CommentsController::Comments - Rails error - ruby-on-rails

I have just made a new model named Comments and now I'm trying to make a view so that user can leave comments from the UI(very basic stuff here). But, I'm running into this error uninitialized constant CommentsController::Comments for the life of me I can't figure out why it's throwing this error and not just rendering the page when it's clicked?
I'm going to post all the applicable code and error for clarity.
MODEL:
class Comment < ActiveRecord::Base
belongs_to :subscriber
end
CONTROLLER:
class CommentsController < ApplicationController
def new
#comments = Comments.new
end
end
ROUTES
Rails.application.routes.draw do
devise_for :users
resources :subscribers, except: :show
resources :comments
SCHEMA:
create_table "comments", force: :cascade do |t|
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "fav_drink"
t.string "visit_time"
end
VIEW:
<h2>Let us get to know you more <%= link_to 'Comment', new_comment_path %> </h2>
This is the link I've set up to click the the page where the user will leave a comment.
ERROR:
Let me know if you need to see anymore code. Thank you!

I just made a silly mistake and called Comments.new instead of Comment.new

Models are referenced singularly as they are classes. You have made a mistake of Comments.new but it should be Comment.new.

Related

Rails issue, trying to sort out my routes and link_to helper to direct me from sets index to cards index

I am trying to link from my set index page to card index directly without having to go through the show index. I am also concerned that my routes may be wrong due to a foreign key missing in my schema. I have added card_id manually to my set model. I will put all the relevant files below.
ActiveRecord::Schema[7.0].define(version: 2022_12_04_135913) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "pokemon_cards", force: :cascade do |t|
t.string "name"
t.string "set"
t.string "artist"
t.integer "price"
t.boolean "owned"
t.boolean "needed"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "pokemon_sets", force: :cascade do |t|
t.string "name"
t.string "series"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "card_id"
t.string "image_url"
t.string "symbol_url"
end
end
The below line which has a comment has the following error :
No route matches {:action=>"index", :controller=>"pokemon_cards", :pokemon_set_id=>nil}, missing required keys: [:pokemon_set_id]
<h1>Pokemon Sets</h1>
<ul>
<% #pokemon_sets.each do |set| %>
<li><%=link_to(set.name, pokemon_set_pokemon_cards_path(#pokemon_set)) %></li> # this throws an error
<li><%= set.series %></li>
<li><%= image_tag(set.image_url, size: "250x150") %></li>
<% end %>
</ul>
I will put below my nested resources in my routes file and also my routes in the terminal.
Rails.application.routes.draw do
root to: "pages#home"
resources :pokemon_sets, only: [:index, :show], path: 'sets' do
resources :pokemon_cards, only: [:index, :show], path: 'cards'
end
end
Prefix Verb URI Pattern Controller#Action
root GET / pages#home
pokemon_set_pokemon_cards GET /sets/:pokemon_set_id/cards(.:format) pokemon_cards#index
pokemon_set_pokemon_card GET /sets/:pokemon_set_id/cards/:id(.:format) pokemon_cards#show
pokemon_sets GET /sets(.:format) pokemon_sets#index
pokemon_set GET /sets/:id(.:format) pokemon_sets#show
class PokemonSetsController < ApplicationController
before_action :find_pokemon_set, only: [:show]
def index
#pokemon_sets = PokemonSet.all
end
def show
end
private
def find_pokemon_card
#pokemon_card = PokemonCard.find(params[:card_id])
end
def find_pokemon_set
#pokemon_set = PokemonSet.find(params[:id])
end
def pokemon_sets_params
params.require(:pokemon_cards).permit(:name, :series, :card_id)
end
end
I have tried a few things, like specifiying the controller in the link to to use the pokemon_cards controller but that did not work.
Is not a problem with your schema, the routes does not know what is going on with schema.
Are there some problems:
Models: In your problem pokemon set needs to have many cards, so you need pokemon_set_id inside pokemon_card model no, the other way around.
Controllers: You need two controller one PokemonSetsController and other PokemonSets::PokemonCards::Controller. For the second one i suggest you to read this post: https://www.digitalocean.com/community/tutorials/how-to-create-nested-resources-for-a-ruby-on-rails-application
The route error is because you do not set pokemon_set_id, you should use this:
<%=link_to(set.name, pokemon_set_pokemon_cards_path(pokemon_set_id: #pokemon_set.id)) %>
But is better try to re-write some parts of the code following the post in the second topic.

undefined method `respond_to' for Api::V1::LocationsController:Class

I am new to rails and decided to make make an application that shows the weather. I followed this tutorial and GoRails Rails API video course. When I run server (path: http://127.0.0.1:3000/api/v1/locations), I see undefined method respond_to for Api::V1::LocationsController:Class error. The same is with http://127.0.0.1:3000/api/v1/locations/1. I googled a lot, but didn't see an appropriate answer. I am leaving code here. Locations is for the city and Recordings is for temperature. I am also leaving schema here if this is the case. A screen of directories tree is attached.
I'VE NEVER BEEN SO STUCK
routes.rb
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :locations
end
end
resources :locations
root "locations#index"
end
locations_controller:
module Api
module V1
class LocationsController < ApplicationController
respond_to :json
def index
respond_with LocationsController.all
end
def show
respond_with find_location
end
private
def find_location
#location = LocationsController.find(params[:id])
end
end
end
end
recordings_controller
class RecordingsController < ApplicationController
end
application_controller
class ApplicationController < ActionController::Base
end
Models:
location.rb
It is also not able to find these fields in db for some reason...
class Location < ApplicationRecord
belongs_to :recording
validates_uniqueness_of :name
end
recording.rb
class Recording < ApplicationRecord
has_many :locations
end
schema:
ActiveRecord::Schema[7.0].define(version: 2022_10_20_135036) do
create_table "locations", force: :cascade do |t|
t.integer "recording_id", null: false
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["recording_id"], name: "index_locations_on_recording_id"
end
create_table "recordings", force: :cascade do |t|
t.integer "temp"
t.string "status"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "locations", "recordings"
end
I thought to use here one-to-many association. As I thought, one city has one temperature and one temperature has loads of cities.
The tutorial you are following is quite old and partly outdated. The respond_to method which is in the first line of the Api::V1:: LocationsController was removed in Ruby on Rails 5.0 about six years ago.
But the good news it that its functionality has been extracted to the responders gem. That means when you add that gem to your application's Gemfile then it might work after running bundle install and restarting the server.
Note. I wrote it might work because it is possible that there are other incompatibilities between the tutorial and your current, up-to-date Ruby on Rails version 7.0.

Need help rails routing using model attribute

I am currently learning rails and in the process of building my first rails project. I created a :restaurant model (along with other models - bookings and user) with several attributes which include :city. Here's my schema:
create_table "restaurants", force: :cascade do |t|
t.string "name"
t.string "city"
t.string "website"
t.string "phone_number"
t.integer "ratings"
t.integer "capacity"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
In my root '/' page, I am displaying the unique city values as a list with links. I was hoping that the user can browse restaurants by clicking on the city that they are in or planning to visit (ideally with a link '/restaurants/#{city}' and through that end up in a page with the list of restaurants in that city.
I have been trying to figure out how to do this currently my relevant routes look like this:
resources :restaurants do
resources :bookings
end
I tried creating :city as a nested resource but this ended up with url '/restaurants/:restaurant_id/:city' which isn't what I'm trying to achieve.
But most importantly, I cannot work out how the 'city' that the user clicked in the root page can lead to the page with all the restaurants in that city.
Any advice would be most helpful.
Thank you.
Routes are extremely flexible and give you a lot of power.
First option: I'd suggest the more traditional Rails way: Separate out your cities into their own model and relate them to a restaurant.
Something like this:
class City < ApplicationRecord
has_many :restaurants, inverse_of: :city
...
end
class Restaurant < ApplicationRecord
belongs_to: city, inverse_of: :restaurants
...
end
Then, I'd move your database around a bit:
create_table :cities do |t|
t.string :name, null: false
t.timestamps
end
create_table :restaurants do |t|
t.string :name
t.references :city
t.string :website
t.string :phone_number
t.integer :rating
t.integer :capacity
end
This will get you on the right track for nested routing like:
/cities/:city_id/restaurants
Second option is to wander off the RESTful path and play with the flexibility of routes:
(I'm suggesting getting away from /restaurants/:city and just use /:city, but the idea is the same)
# routes.rb
# warning! Put this towards the very end of your file. Even then, any URL you try to hit that fits
# this pattern will get sent to this controller action. e.g. "yoursite.com/badgers"
# you'll need to explore handling RecordNotFound and redirecting someplace else
get '/:city', to: 'restaraunts#by_city', as: 'restaurants_by_city'
Now in your Restaurants controller:
class RestaurantsController < ApplicationController
...
def by_city
city = params[:city] # this will be whatever is in the url
#restaurants = Restaurant.where(city: city)
# you'll need some error handling:
redirect to root_path if #restaurants.empty?
...
end
end

undefined method or my Active Record mistakes

Sorry if my problem will be silly but Rails are new to me. I made two models and two controllers. My problems were started after I made second model and added reference to the first one.
class SentencesController < ApplicationController
before_action :find_story
def create
#sentence = find_story.sentences.build(sentence_params)
if #sentence.save
flash[:success] = "You wrote the continuation!"
render 'stories/show'
else
render 'stories/show'
end
end
private
def sentence_params
params.require(:sentence).permit(:content)
end
def find_story
#story = Story.find(params[:id])
end
end
and this:
class StoriesController < ApplicationController
........
def show
#story = Story.find(params[:id])
#sentence = #story.sentences.build
end
.........
end
And I have a problem with defining instance variable #story = Story.find(params[:id]). Error: ActiveRecord::RecordNotFound in SentencesController#create. I have tried many combinations.
This is my migrate files:
class CreateStories < ActiveRecord::Migration[5.1]
def change
create_table :stories do |t|
t.string :title
t.text :content
t.timestamps
end
end
end
class CreateSentences < ActiveRecord::Migration[5.1]
def change
create_table :sentences do |t|
t.text :content
t.references :story, foreign_key: true
t.timestamps
end
add_index :sentences, [:story_id, :created_at]
end
end
What did I do wrong?
EDIT (routes):
Rails.application.routes.draw do
root 'stories#index'
get 'stories/show'
get 'stories/new'
resources :stories
resources :sentences, only: [:create]
end
and schema:
ActiveRecord::Schema.define(version: 20180322121215) do
create_table "sentences", force: :cascade do |t|
t.text "content"
t.integer "story_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["story_id"], name: "index_sentences_on_story_id"
end
create_table "stories", force: :cascade do |t|
t.string "title"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
As stated in the comments, you probably want your routes to look something like:
resources :stories do
resources :sentences, only: [:create]
end
Which will give you:
story_sentences POST /stories/:story_id/sentences(.:format) sentences#create
stories GET /stories(.:format) stories#index
POST /stories(.:format) stories#create
new_story GET /stories/new(.:format) stories#new
edit_story GET /stories/:id/edit(.:format) stories#edit
story GET /stories/:id(.:format) stories#show
PATCH /stories/:id(.:format) stories#update
PUT /stories/:id(.:format) stories#update
DELETE /stories/:id(.:format) stories#destroy
Which you might use something like:
<%= form_tag story_sentences_path(#story) do %>
...
<% end %>
Then, as Matt said, change your find to:
#story = Story.find(params[:story_id])
There are a couple of reasonable ways you can find the story in your sentences controller.
You can add a story_id field to your form and submit it as a param along with the sentence content. Just make sure to add it to sentence_params in the controller so it's not ignored.
def sentence_params
params.require(:sentence).permit(:content, :story_id)
end
And then you'll need to update your find_story method in the controller to:
#story = Story.find(sentence_params[:story_id])
You can set up nested resources in your routes file (where the sentences resource is nested within the stories resource). That will give you access to the story_id from the route itself (ie. you wouldn't need to submit the story_id through the form).
And if you go this way, you'll also need to tweak the find_story method in the controller, but this time it should be:
#story = Story.find(params[:story_id])

Need help in troubleshooting association in Rails !

I'm new to rails and and I'm on the urge of learning Associations.
I'm using Rails version 3.
I have a user model and post model.My need is as below:-
Models
class User < ActiveRecord::Base
has_many :post
end
class Post < ActiveRecord::Base
belongs_to :user
validates_associated :user
end
Schema
ActiveRecord::Schema.define(:version => 20101016171256) do
create_table "posts", :force => true do |t|
t.integer "sell_or_buy"
t.string "title"
t.text "body"
t.integer "user_id" <<<<<<< I thought this will help to associate to user model.
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.string "password"
t.integer "rank"
t.datetime "created_at"
t.datetime "updated_at"
end
end
I thought keeping a user_id field and the belongs_to association will do my job, but
when i tried to display all the posts belonging to a user as follows:
<%= #user.posts %>
in my show.html.erb file. But I get only the following display:-
Name: saran
Email: saran.saran007#gmail.com
Password: abcd
Rank:
Edit | Back
Posts
#<Post:0xb69f47f8>#<Post:0xb69f3024>
I want to display the associated posts "title" and "body" in a readable format.
Also I'm able to create a post with a user_id in which no user exists!. The validates_associated :user is also not working, Please help me out.
Its
class User
has_many :posts
end
Not
has_many :post
Edit and Update your results.
You are getting the posts as expected in your view... So I'm not sure I understand that part of your question. As to the other part, validates_associated just ensures that the attached object is valid itself, and not if it exists at all. For that you want validates_presence_of. See the docs.
I wrote the following partial for my purpose and it works well :).
Thanks for all your inputs.
<% for post in #user.posts do %>
<h3> <%= post.title %> </h3>
<%= post.body %>
<% end %>

Resources