so I'm trying to create a videogame review website for practice. each game would have it's own page, and on each page, i'd like to have a form where you can input reviews, and have it show up on the same page when submitted.
I'm not sure how to handle this. but I managed to create two controllers -- one for creating games, and one for creating reviews.
I use devise for user logins/registration
I'll post the codes below: please let me know if you need to see other files.
routes.rb
Rails.application.routes.draw do
devise_for :users
resources :games
resources :reviews
root "games#index"
end
games_controller.rb -- to create new games
class GamesController < ApplicationController
before_action :set_game, only: [:show, :edit, :update, :destroy]
def index
#games = Game.all
end
def new
#game = Game.new
end
def create
#game = Game.create(game_params)
redirect_to #game
end
def edit
end
def update
#game.update(game_params)
redirect_to #game
end
def destroy
end
private
def game_params
params.require(:game).permit(:title, :image, :developer, :genre, :release_date, :platform)
end
def set_game
#game = Game.find(params[:id])
end
end
reviews_controller.rb -- to create reviews
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
def index
end
def show
end
def new
#review = Review.new
end
def create
#review = Review.create(review_params)
redirect_to #review
end
private
def review_params
params.require(:review).permit(:review)
end
def set_review
#review = Review.find(params[:id])
end
end
show.html.erb for games
<% if user_signed_in? %>
<p class=""><%= link_to "Update Details", edit_game_path %></p>
<p class=""><%= link_to "Update News", new_game_path %></p>
<% end %>
<%= flash[:notice] = "Successfully updated." %>
<hr>
<div class="game_summary">
<%= image_tag #game.image %>
<div class="game_details">
<h3 class="game_title"><%= #game.title %></h3>
<ul class="game_info">
<li>Developer: <%= #game.developer %></li>
<li>Release Date: <%= #game.release_date %></li>
<li>Genre: <%= #game.genre %></li>
<li>Platform(s): <%= #game.platform %></li>
</ul>
<button class="buttons" id="buy">Buy</button>
<button class="buttons" id="rent">Rent</button>
</div>
</div>
<div class="game_news">
<h2 class="game_news_title">News & Articles</h2>
</div>
<div class="game_reviews">
<%= link_to "Add Review", new_review_path %>
<h2>Reviews</h2>
<ul>
<li><%= %></li>
<li><%= %></li>
<li><%= %></li>
<li><%= %></li>
</ul>
</div>
In your games_controller.rb, you'd need a show method (which is created by default when you use scaffolding, but which you somehow missed). This show method would gather all the reviews pertaining to the game in question, assuming your Review model has a reference to its corresponding Game model (both as a foreign key specified in schema.rb and via belongs_to and has_many in their respective models).
The show method would look like this:
def show
#reviews = Review.where("game_id = ?", #game.id)
end
Then in your view, you'd have something like this:
<% #reviews.each do | review | %>
<%= review.title %>
<%= review.content %>
<% end %>
I have no idea what fields are contained in your Review object, but you can extrapolate from this example to get what you want.
Related
I am coding a Rails app, where I would like to show specific restaurants, hotels and bars for a specific city.
My problem is when I want to show a specific instance of a Restaurant (for now), I always end-up on the page of the Restaurant with the id 1.
Here is my routes file :
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
root to: 'cities#index'
resources :cities, only: %i[index show] do
resources :restaurants, only: [:show]
resources :hotels, only: [:show]
resources :clubs, only: [:show]
end
end
Here my show for a specific city:
<h1><%= #city.name %></h1>
<div class="row">
<div class="col-4">
<h2>Restaurants</h2>
<% #restaurants.each do |restaurant| %>
<h3><%= link_to restaurant.name, [#city, #restaurant] %></h3>
<% end %>
</div>
<div class="col-4">
<h2>Hotels</h2>
<% #hotels.each do |hotel| %>
<h3><%= hotel.name %></h3>
<% end %>
</div>
<div class="col-4">
<h2>Bars</h2>
<% #clubs.each do |club| %>
<h3><%= club.name %></h3>
<% end %>
</div>
</div>
Here my Cities controller:
class CitiesController < ApplicationController
def index
#cities = City.all
end
def show
#city = City.find(params[:id])
#restaurants = Restaurant.all
#hotels = Hotel.all
#clubs = Club.all
end
end
Here my restaurant controller:
class RestaurantsController < ApplicationController
before_action :find_city
before_action :set_restaurant, only: [:show]
def index
#restaurants = #city.restaurants
end
def show; end
private
def find_city
#city = City.find(params[:city_id])
end
def set_restaurant
#restaurant = #city.restaurants.find(params[:id])
end
end
On the city show, whatever the Restaurant I click on, I always end up on the page of the restaurant with the id 1 and with this path: http://localhost:3000/cities/1/restaurants/1 and I really don't understand why...
I have used this tutorial to help me but I am still missing something apparently.
Change this line:
<h3><%= link_to restaurant.name, [#city, #restaurant] %></h3>
to this:
<h3><%= link_to restaurant.name, restaurant %></h3>
I need help with this my code,that displays list of posts of users along with their username.What i want is, when i click on a username of a particular post, it should send me to that user's profile. instead, it send's to my own profile or the current user's profile whiles i want it to link me to the username i have clicked profile. (e.g like when you click on a username on Instagram, it links you to the user's profile so you can follow or unfollow and see their post)
Please i need help. what i'm i not doing right in my code.
i'm on rails 5.2.3 & ruby 2.3.3
Home
<div class="posts">
<% #posts.each do |post| %>
<section class="post">
<div class="user">
<div class="avatar">
<img src="assets/avater.jpg">
</div>
<%= link_to post.user.username, user_path(post.user), class: 'username' %>
</div>
<%= image_tag post.image, class: 'main-image' %>
<div class="description">
<% post.description.to_s.split(' ').each do |word| %>
<% if word.start_with?('#') %>
<%= link_to word, search_index_path(query: word) %>
<% else %>
<%= word %>
<% end %>
<% end %>
</div>
</section>
<% end %>
<%= paginate #posts %>
</div>
routes
Rails.application.routes.draw do
get 'search/index'
devise_for :users
get 'home/index'
resources :posts
root 'home#index'
resources :users, only: [:show, :edit, :update]
resources :posts, only: [:new, :create, :show, :destroy]
end
users controller
class UsersController < ApplicationController
before_action :find_user
def show
#user = User.find(params[:id])
#posts = current_user.posts.order(created_at: :desc)
end
def edit
end
def update
current_user.update(user_params)
redirect_to current_user
end
private
def find_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:username, :name, :website,:bio, :email, :phone, :gender, :avatar)
end
end
post controller
class PostsController < ApplicationController
def new
#post = current_user.posts.build
end
def create
#post = Post.create(post_params)
redirect_to root_path
end
def show
#post = Post.find(params[:id])
end
def destroy
#post = current_user.posts.find(params[:id])
#post.destroy
redirect_to user_path(current_user)
end
private
def post_params
params.require(:post).permit(:description, :image, :user_id)
end
end
home controller
class HomeController < ApplicationController
before_action :authenticate_user!
def index
#posts = Post.order(created_at: :desc).page(params[:page]).per(5)
end
end
I guess the problem is that on the show method from users_controller, you are getting the posts from current_user instead of the user, it should be #posts = #user.posts.order(created_at: :desc)
I am trying to access an "edit" link to edit an object, but I'm getting this error:
Param is missing or the value is empty: preview
Basically, I have 2 models that I linked through association:
Game model
Review model
I'm rendering reviews in the Game's show page. When I try to edit a review, it's saying I'm missing params or the value is empty in the Reviews controller.
The routes are also nested. How can I fix this?
Thanks in advance :)
routes.rb
Rails.application.routes.draw do
devise_for :users
root "games#index"
resources :games do
resources :news
resources :reviews, except: [:show, :index]
resources :previews, except: [:show, :index]
end
resources :platforms
resources :genres
end
show.html.erb (Linked to Games controller)
<% if #news.last.created_at > preview.updated_at %>
<p><%= link_to "edit", edit_game_preview_path(#game.id, preview.id) %></p>
<% end %>
<p><%= link_to "delete", game_preview_path(#game.id, preview.id), method: :delete %></p>
<% end %>
Reviews partial (Form)
<%= form_for [#game, #previews.new] do |r| %>
<h3 class="post_review">Preview this game</h3>
<p><%= flash[:notice_submit] %></p>
<p><%= r.text_field :title, placeholder: "Enter your tagline" %></p>
<p><%= r.text_area :content, placeholder: "Enter your review here" %></p>
<p><%= r.text_area :vote %></p>
<p><%= r.hidden_field :game_id, value: #game.id %></p>
<%= r.submit %>
<% end %>
Reviews controller
class PreviewsController < ApplicationController
before_action :authenticate_user!
before_action :set_preview, only: [:show, :edit, :update, :destroy]
before_action :set_game
def new
#preview = Preview.new
end
def create
#preview = Preview.new(preview_params)
#preview.user_id = current_user.id
#preview.game_id = #game.id
#preview.username = current_user.username
if #preview.save
redirect_to :back
flash[:notice_submit] = "Thanks for you comment!"
else
redirect_to :back
flash[:notice_submit] = "Either you've already voted, or you're not filling in all forms."
end
end
def edit
#preview.update(preview_params)
redirect_to #game
end
def destroy
#preview.destroy
redirect_to #game
end
private
def set_preview
#preview = Preview.find(params[:id])
end
def set_game
#game = Game.find(params[:game_id])
end
def set_user
#user = User.find(params[:user_id])
end
def preview_params
params.require(:preview).permit(:title, :content, :vote)
end
end
You are getting this error because in your preview_params you are requiring a preview object.
I think your controller logic for the edit action is invalid. For the edit action, you just need to set_preview and then render the edit template. The current logic in your edit action should go in an update action.
def edit
end
def update
#preview.update(preview_params)
redirect_to #game
end
Also the first line of your form should be:
<%= form_for [#game, #preview] do |r| %>
so I'm trying to create a video game review website for practice.
A game has many reviews, and votes. The idea is, in order to post a review, you must vote "Good" or "Bad" first, THEN submit a review. You can't post a text review without voting.
I'm trying to do this without the acts_as_voteable gem...
The data format for votes is boolean. "Good" is true, "Bad" is false.
How do I get the votes to save? below are my routes.rb, _review partial, reviews controller, and show page.
many thanks guys :)
edit****: also I'm trying to only one vote per user. I was thinking of using a token variable which equals to 1, and when a vote is cast, the token is -1. Is that a good approach? But the data type for vote is boolean, so how would that work -- or should I change the data type for vote from boolean to integer?
edit#2 -- so I added :vote into my params.
routes.rb
upvote_game_review_path
POST /games/:game_id/reviews/:id/upvote(.:format) reviews#upvote
downvote_game_review_path
POST /games/:game_id/reviews/:id/downvote(.:format) reviews#downvote
Rails.application.routes.draw do
devise_for :users
root "games#index"
resources :games do
resources :news
resources :reviews, except: [:show, :index] do
member do
post "upvote"
post "downvote"
end
end
end
resources :platforms
resources :genres
end
reviews_controller.rb
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :update, :edit, :destroy]
before_action :set_game
before_action :authenticate_user!
def new
#review = Review.new
end
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
#review.game_id = #game.id
if #review.save
redirect_to #game
else
render "review"
end
end
def upvote
#review.vote.create = true
redirect_to #game
end
def downvote
#review.vote.create
#review.vote = false
redirect_to #game
end
def edit
#review.update(review.params)
end
def destroy
#review.destroy
redirect_to #game
end
private
def set_review
#review = Review.find(params[:id])
end
def set_game
#game = Game.find(params[:game_id])
end
def review_params
params.require(:review).permit(:comment, :vote)
end
end
_review partial <-- to create a new review
<%= form_for [#game, #reviews.new] do |r| %>
<h3 class="post_review">Review this game</h3>
<p>
<%= r.text_area :comment %>
</p>
<p>
<%= button_to "Good", upvote_game_review_path(#game.id, r) %>
</p>
<p>
<%= button_to "Bad", downvote_game_review_path(#game.id, r) %>
</p>
<p>
<%= r.hidden_field :game_id, value: #game.id %>
<p>
<%= r.submit %>
<% end %>
show.html.erb
<p><%= link_to "<< Home", games_path %></p>
<span><%= link_to "Edit", edit_game_path(#game) %></span>
<span><%= link_to "Delete", game_path(#game), method: :delete %></span>
<div class="game_summary">
<h2><%= #game.title %></h2>
<%= image_tag #game.image %>
<p>Release Date: <%= #game.release_date %> </p>
<p>Genre: <%= #game.genre_id %> </p>
<p>Platforms: <%= #game.platform_id %></p>
</div>
<%= link_to "Add News", new_game_news_path(#game) %>
<h2>News & Articles</h2>
<%= link_to "view all", game_news_index_path(#game) %>
<% #news.each do |n| %>
<ol>
<li><%= link_to n.title, game_news_path(#game.id, n.id) %></li>
</ol>
<% end %>
<div class="game_review submit">
<%= render "review" %>
</div>
<% #reviews.each do |review| %>
<p><%= review.comment %></p>
<p><%= link_to "delete", game_review_path(#game.id, review.id), method: :delete %></p>
<% end %>
You don't specify which review you're loading in. The reason is here:
before_action :set_review, only: [:show, :update, :edit, :destroy]
You don't pull in the request's review instance when you go to either of those actions. Further, it doesn't look like you're actually saving them.
So, two things I'd recommend:
Add those methods to your before_action:
before_action :set_review, only: [:show, :update, :edit,
:destroy, :upvote, :downvote]
(May not be necessary, write tests to confirm this!) Actually save the entity after you've changed its value.
def upvote
#review.vote.create = true
#review.save
redirect_to #game
end
def downvote
#review.vote.create unless #review.vote
#review.vote = false
#review.save
redirect_to #game
end
I'm trying to add a flashcards(cardsets) feature in Rails and I'm having some problems implementing this as I'm getting an undefined methodcardsets' for nil:NilClass` error
I can get the page to render if I change: <% if #user.cardsets.any? %> to <% unless #cardsets.any? %> but the corresponding cardsets are being shown when I do this.
Here is the html.erb code that is producing this error:
<% provide(:title, "Flashcards") %>
<h1>Flashcards</h1>
<div class="row">
<aside class="span3">
<%= render "shared/cardset_form" %>
</aside>
<div class="span6">
**<% if #user.cardsets.any? %>**
<h3>Flashcard Sets (<%= #user.cardsets.count %>)</h3>
<ol class="cardsets">
<% #user.cardsets.each do |cardset| %>
<li>
<span class="topic"><%= link_to cardset.topic, show_cardset_path(cardset) %></span>
<%= link_to "edit", edit_cardset_path(cardset) %>
<%= render partial: "shared/delete_link", locals: {item: cardset} %>
</li>
<% end %>
</ol>
<% end %>
</div>
</div>
I've starred the line that is producing the undefined methodcardsets' for nil:NilClass` error.
This is what's in my cardsets_controller.rb:
class CardsetsController < ApplicationController
before_action :signed_in_user, only: [:new, :index, :create, :edit, :destroy, :update]
before_action :correct_user, only: [:edit, :update, :destroy]
def index
#cardsets = Cardset.all
end
def show
#cardset = Cardset.find(params[:id])
end
def create
#cardset = current_user.cardsets.build(cardset_params)
if #cardset.save
flash[:success] = "A new set of flashcards have been created!"
redirect_to #cardset
else
render "new"
end
end
def new
#cardset = Cardset.new
end
def edit
end
def update
#cardset = Cardset.find(params[:id])
if #cardset.update_attributes(cardset_params)
flash[:success] = "You've updated your flashcards!"
redirect_to #cardset
else
render "edit"
end
end
def destroy
#cardset = Cardset.find(params[:id])
#cardset.delete
redirect_to cardsets_path
end
private
def cardset_params
params.require(:cardset).permit(:topic, :description)
end
def correct_user
#cardset = current_user.cardsets.find_by_id(params[:id])
redirect_to root_url if #cardset.nil?
end
end
Here is the code in my cardset.rb file:
class Cardset < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
validates :topic, presence: true
end
Here is the code in my user.rb file:
class User < ActiveRecord::Base
has_many :cardsets
(...a bunch of other code...)
end
If anyone could provide some help or suggestions on where I may be going wrong I'd greatly appreciate it!
Thanks!
As far as I can tell, you aren't setting #user in your Controller, so #user is nil.
You probably want to either define #user or maybe you meant to use #cardsets.