NameError in Discussions#index - ruby-on-rails

Im trying to write an ruby app that lets you post discussions and comment on posts. The issue is that I cant get the comments- here called microposts, to show up below the discussions. Right now, im getting the error NameError in Discussions#index: undefined local variable or method `discussion' for #<#:0x0000010563a1e0>. Any ideas?
the micropost form
<% #micropost = Micropost.new %>
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.hidden_field :discussion_id, discussion.id%>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
micropost controller
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def index
end
def create
#discussion = current_user.discussions.new
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Posted!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
end
end
discussion controller
class DiscussionsController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update]
def show
#user = User.find(params[:id])
#discussions = #user.discussion.paginate(page: params[:page])
#microposts = #user.micropost.paginate(page: params[:page])
end
def index
#discussions = Discussion.all
end
def create
#discussion = current_user.discussions.build(params[:discussion])
if #discussion.save
flash[:success] = "Discussion Started!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
end
def edit
end
def update
end
def new
end
end
discussion view
<% content_for :script do %>
<%= javascript_include_tag 'hover_content' %>
<% end %>
<li>
<div class = "intro-bar"><span class = "intro"><%=discussion.intro %></span></div>
<div class = "content-bar">
<span class = "content"><%= discussion.content %></span>
<div class = "buttons">
<div class = "vote-neg"><%= link_to "Break Up", signup_path,class: "btn btn-large btn-breakup" %></div>
<div class = "vote-plus"><%= link_to "Stay Together", signup_path,class: "btn btn-large btn-staytogether" %></div>
</div>
</div>
</li>
<span class = "timestamp">
Posted <%= time_ago_in_words(discussion.created_at) %> ago.
</span>
<div class = "comments">
<% discussion.microposts.each do |micropost| %>
<li>
<div class = "post-comment"><%= micropost.content%></div>
</li>
<% end %>
</div>
<% if signed_in? %>
<div class = "row">
<aside class = "span4">
<section>
<%= render 'shared/micropost_form', :locals => {:discussion => discussion }%>
</section>
</aside>
</div>
<% end %>
thanks for the help, im sure its something really simple. Im quite new at this

In this code,
class DiscussionsController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update]
def show
#user = User.find(params[:id])
#discussions = #user.discussion.paginate(page: params[:page])
#microposts = #user.micropost.paginate(page: params[:page])
end
it looks like #user.discussion is your problem. Should probably be #user.discussions. Likewise with the next line, #user.microposts

I suppose you show discussion with show method. But, in show method and everywhere else in controller except create you declare #discussions.
I actually can't get, why in show method you do what suits more for index method, but anyway, Rails pass variable from controller to views if it is declared as instance (with #).
So, to define variale in views, you should have #discussion in relative controller method, and locals should also pass #discussion:
:locals => {:discussion => #discussion }

Related

rendering form, and display the input on the same page

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.

Undefined method build in rails 4 has_many association

I have the following set up in rails:
Document has_many Sections
Section belongs_to Document
The Section form is completed in the documents/show view...the Document controller for this action is:
def show
#document = current_user.documents.find(params[:id])
#section = Section.new if logged_in?
end
The Section form in documents/show is as follows:
<%= form_for(#section) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new section..." %>
</div>
<%= hidden_field_tag :document_id, #document.id %>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
Where you can see a hidden_field_tag is sending the document_id
The sections_controller is as follows:
class SectionsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy, :show, :index]
def create
#document = Document.find(params[:document_id])
#section = #document.build(section_params)
if #section.save
flash[:success] = "Section created!"
redirect_to user_path(current_user)
else
render 'static_pages/home'
end
end
def destroy
end
def index
end
private
def section_params
params.require(:section).permit(:content)
end
end
I get the following error which I have not been able to resolve.
**NoMethodError (undefined method `build' for #<Document:0x00000004e48640>):
app/controllers/sections_controller.rb:6:in `create'**
I am sure it must be something simple I am overlooking but can't seem to find it. Any help would be appreciated:
Replace the below line :-
#section = #document.build(section_params)
with
#section = #document.sections.build(section_params)
You have a has_many associations named sections in the Document model. Thus as per the guide, you got the method collection.build(attributes = {}, ...). Read the section 4.3.1.14 collection.build(attributes = {}, ...) under the link I gave to you.

First argument in form cannot contain nil or be empty with Gamepost

Recieve this error in my Game page in Rails 4
ActionView::Template::Error (First argument in form cannot contain nil or be empty):
_Gamepost_form.html.erb
<%= form_for (#gamepost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new game sale..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
Controller
class GamepostsController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy, :]
before_action :correct_user, only: :destroy
def index
#gamepost = current_user.gameposts.build
end
def create
#gamepost = current_user.gameposts.build(gamepost_params)
if #gamepost.save
flash[:success] = "Game Sale created!"
redirect_to root_url
else
#gamefeed_items = []
render 'static_pages/home'
end
end
def destroy
#gamepost.destroy
redirect_to root_url
end
private
def gamepost_params
params.require(:gamepost).permit(:content)
end
def correct_user
#gamepost = current_user.gameposts.find_by(id: params[:id])
rescue
redirect_to root_url
end
end
Have a similar example using microposts and its working fine no idea why this instance is not working
After the answer Vee provided,
ActionView::Template::Error (undefined method `any?' for nil:NilClass):
1: <% if #gamefeed_items.any? %>
2: <ol class="gameposts">
3: <%= render partial: 'shared/gamefeed_item', collection: #gamefeed_items %>
This shows up in same page
Following up in the comments in your question.
Looks like you are rendering that form from your index action.
class GamepostsController < ApplicationController
before_action :signed_in_user, only: [ :index, :create, :destroy]
...
def index
#gamepost = current_user.gameposts.build
end
...
end
Note that, you also need to add :index and not :new in before_action :signed_in_user. This is to ensure that the current_user becomes available in so that current_user.gameposts.build does not fail!

Why isn't this portion of HTML rendering and why do I get a undefined method `cardsets' for nil:NilClass in Rails?

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.

How can I add a related record whilst on its parents edit page?

I have a table of venues and offers. Each venue can have have many offers.
I would like to be able to add the offers to the venues from the venues edit page. So far I have this (code below) but its giving a "NoMethodError in Venues#edit, undefined method `model_name' for NilClass:Class" error.
venues edit page
(the div id="tabs-3" is a container in an accordion)
<div id="tabs-3">
<%= form_for [#venue, #offer] do |f| %>
<h2 class="venue_show_orange">Offers</h2>
<%= f.fields_for :offers do |offer| %>
<div class="add_offer">
<%= offer.text_field :title %><br>
</div>
<div class="button"><%= submit_tag %></div>
<% end %>
<% end %>
</div>
offers controller
class OffersController < ApplicationController
def new
#offer = Offer.new
end
def create
#offer = #venue.offers.create!(params[:offer])
#offer.venue = #venue
if #offer.save
flash[:notice] = 'Offer added'
redirect_to offers_path
else
render :action => :new
end
end
def edit
#offer = Offer.find(params[:id])
end
def update
#offer = Offer.find(params[:id])
#offer.attributes = params[:offer]
if #offer.save!
flash[:notice] = 'Offer updated successfully'
redirect_to offers_path(#offer)
end
end
end
venues controller
(nothing offer related in here - is this where I'm going wrong?)
class VenuesController < ApplicationController
protect_from_forgery :only => [:update, :delete, :create]
load_and_authorize_resource
def new
#venue = Venue.new
5.times { #venue.venuephotos.build }
end
def create
#venue = Venue.new params[:venue]
if #venue.save
flash[:notice] = 'Venue added'
redirect_to venues_path
else
render :action => :new
end
end
def edit
#venue = Venue.find(params[:id])
5.times { #venue.venuephotos.build }
end
def update
#venue = Venue.find(params[:id])
#venue.attributes = params[:venue]
if #venue.save!
flash[:notice] = 'Venue updated successfully'
redirect_to :back
end
end
end
Any help is much appreciated thanks very much!
edit
venues edit page
<div id="tabs-3">
<%= form_for #venue do |f| %>
<div class="edit_venue_details">
<h2 class="venue_show_orange">Offers</h2>
<%= render :partial => 'offers/offer', :collection => #venue.offers %>
<div class="clearall"></div>
<h2 class="edit_venue_sub_header">Add a new offer</h2>
<%= f.fields_for :offers do |offer| %>
<% if offer.object.new_record? %>
<p class="edit_venue">title: <br>
<%= offer.text_field :title, :class => "edit_venue_input" %></p>
<% end %>
<% end %>
</div>
<button class="submit_button" type="submit"> Save changes</button>
<% end %>
</div>
whats being displayed
however if I add a new offer, that will display correctly:
Some remarks:
1) Replace:
<%= form_for [#venue, #offer] do |f| %>
with:
<%= form_for #venue do |f| %>
Because offers data will be updated through the related venue, only one controller action will handle the form.
2) If you want to add some unexisting offers in this form, you shoud instantiate them the way you did with venuephotos
3) Show your Venue model. You should have at least:
accepts_nested_attributes_for :offers
Fixed with:
<%= f.fields_for :offers, #venue.offers.build do |offer| %>

Resources