In my rails app I have a simple poll system. User checks options he likes and votes. The problem is check_boxes not showing and even if will showing I wouldn't Vote all the same because made some mistakes in my code likely
polls/show.html.haml:
- for question in #poll.questions.each
%span= question.title
%p= question.comment
- form_tag upvote_question_path do
%p= check_box_tag question, question.id
%p= question.title
= submit_tag 'Vote'
questions_controller.rb
class QuestionsController < ApplicationController
def upvote
#question = Question.find(params[:id])
#question.increment!(:votes_count)
redirect_to :back
end
end
If you need more information please comment!
Try this
<% #poll.questions.each do |question| %>
<span> <%= question.title %></span>
<%= form_tag upvote_question_path do %>
<p><%= check_box_tag :question_id, question.id %></p>
<p><%= question.title %></p>
<%= submit_tag 'Vote' %>
<% end %>
<% end %>
In controller
def upvote
#question = Question.find(params[:question_id])
#question.increment!(:votes_count)
redirect_to :back
end
Several things:
Your update_vote_path doesn't seem to be a member route?
You could easily achieve this with a button
You're looping through questions -- maybe this is empty?
Code
I would try this:
#config/routes.rb
resources :questions do
#/questions/2/vote
post :vote
end
#app/views/your_view
- for question in #poll.questions.each
%span= question.title
%p= question.comment
- button_to "Vote", vote_questions_path(question), method: :post
#app/controllers/questions_controller.rb
class QuestionsController < ApplicationController
def vote
#question = Question.find(params[:question_id])
#question.increment!(:votes_count)
redirect_to :back
end
end
Modularity
You're trying to manually submit a form with specific params, whereas you can handle all of that with the routes
I think your main issue will be how you're calling the #poll.questions variable. I don't believe it will be loading correctly, but without seeing your other code, this is just speculation
Related
Currently learning Ruby on Rails and creating a simple blog app with comments. I have a Comment model and an Article model. Comment is polymorphic and both models have many comments.
I'm trying to come up with a destroy method that's able to delete both the comments that belong to Comment and the ones that belong to Article (and that remain as [deleted] without destroying their children, much like in Reddit, although I haven't even gotten to that part).
I have tried different paths but I haven't got it right yet. Nested paths still confuse me a little and I'm not sure on how to pass the params that the path requests when creating the link_to.
These are my files:
routes.rb:
Rails.application.routes.draw do
get 'comments/new'
get 'comments/create'
get 'articles/index'
get 'articles/show'
root 'articles#index'
resources :articles do
resources :comments
end
resources :comments do
resources :comments
end
end
article.rb:
class Article < ApplicationRecord
has_many :comments, as: :commentable
end
comment.rb:
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: :true
has_many :comments, as: :commentable
end
comments_controller.rb:
class CommentsController < ApplicationController
before_action :find_commentable
def new
#comment = Comment.new
end
def create
#comment = #commentable.comments.new(comment_params)
if #comment.save
redirect_back(fallback_location: root_path)
else
redirect_back(fallback_location: root_path)
end
end
def destroy
#comment = #commentable.comments.find(params[:id])
#comment.destroy
redirect_back(fallback_location: root_path)
end
private
def comment_params
params.require(:comment).permit(:body)
end
def find_commentable
if params[:article_id]
#commentable = Article.find_by_id(params[:article_id])
elsif params[:comment_id]
#commentable = Comment.find_by_id(params[:comment_id])
end
end
end
show.html.erb, where the form for commments that belong to Article.rb is:
<h1> <%= #article.title %> </h1>
<p> <%= #article.body %> </p>
<small>Submitted <%= time_ago_in_words(#article.created_at) %> ago </small> <br/>
<h3>Comments</h3>
<%= form_for [#article, Comment.new] do |f| %>
<%= f.text_area :body, placeholder: "Say something!" %> <br/>
<%= f.submit "Submit" %>
<% end %>
<ul class="parent-comment">
<%= render partial: 'comments/comment', collection: #article.comments %>
</ul>
<%= link_to "Index", articles_path %>
And the partial _comment.html.erb , which displays the comments that belong to the article as well as those that belong to other comments, and where I'm trying to integrate the link_to:
<p> <%= comment.body %> </p>
<small>Submitted <%= time_ago_in_words(comment.created_at) %> ago </small> <br/>
<%= form_for [comment, Comment.new] do |f| %>
<%= f.text_area :body, placeholder: "Add a reply!" %><br/>
<%= f.submit "Reply" %>
<%= link_to "Delete", comment_path(comment), method: :delete %>
<% end %>
<ul>
<%= render partial: 'comments/comment', collection: comment.comments %>
</ul>
Whenever I do seem to get the path right, NoMethodError in CommentsController#destroy — undefined method `comments' for nil:NilClass comes up. Why would the controller show it as undefined? It worked in the new method, as far as I can see.
Could you give some guidance as to what I should do or what I should fix? I'm not sure how to delete the parent comments, either, and I haven't managed to find information that suits this case. If you know where to point me to, I'm all eyes.
Thank you.
Because of your design model structure.
Your view
<%= link_to "Delete", comment_path(comment), method: :delete %>
Your find_commentable
elsif params[:comment_id]
#commentable = Comment.find_by_id(params[:comment_id])
end
#commentable will be a Comment class, so it won't have .comments methods as your Article class
check carefully to destroy the method
def destroy
#comment = #commentable.comments.find(params[:id])
#comment.destroy
redirect_back(fallback_location: root_path)
end
use #comment = #commentable.comments.find_by(id: params[:id]) and check whether #comment has some value or not?
just add one condition like this and it won't throw the error:
#comment.destroy if #comment
if #comment is nil and trying to destroy then it will throw the error.
I am using the acts_as_votable gem and am having an issue with the voting.
I have two models - User and Post. A User is able to vote on a post.
The problem I am having is that the User is only currently able to vote on their own post, but not other users' posts.
I think this is because I have done #posts.each and then the user is only being accessed for their own posts, so they can only vote on their own posts. Or the problem is in my index method in my controller.
Index.html.erb File:
<% #posts.each do |post| %>
<div class="user-input">
<% if post.user.voted_up_on? post %>
<%= link_to unlike_post_path(post), method: :put do %>
<%= image_tag("/assets/like.png") %>
<% end %>
<% else %>
<%= link_to like_post_path(post), method: :put do %>
<%= image_tag("/assets/heart.png") %>
<% end %>
<% end %>
</div>
<% end %>
Posts_controller (relevant methods):
def index
#posts = Post.includes(:user).order("created_at DESC") #Possible issue is here??
end
def like
#post.upvote_by current_user
redirect_to :back
end
def unlike
#post.unvote_by current_user
redirect_to :back
end
Routes:
resources :posts do
member do
put "like", to: "posts#like"
put 'unlike', to: 'posts#unlike'
end
end
If someone could help me understand why a User is only able to vote on their own posts that would be great.
Got it.
Had to replace
<% if post.user.voted_up_on? post %>
with:
<% if current_user.liked? post %>
I believe it was asking if the creator of the post has voted on the post, whereas I needed just the current user to see if they have voted on the post.
I am very new to rails.. I want to update the data which matches my condition.. I have a form which submits two values(order_no, order_date)., and i want to retrieve all the data which relates to that order_no.. I dont know to write the controller code for this . Can someone help me.. here is my code.. I am really sorry if you feel this doubt is silly. I really dont know how to code efficiently in rails.
//my view
<%= form_for([#order], :url=>{:controller=>"users"}) do |i|%>
<tr><td><%= i.label :order_no,"Order No" %></td></tr>
<tr><td><%= i.text_field :order_no %></td></tr>
<tr><td><%= i.label :order_date,"Order Date" %></td></tr>
<tr><td><%= i.text_field :order_date %></td></tr>
<%= link_to "Update",users_update_orderSummary_path(i) %>
<% end %>
my controller,
def edit_order
#order=Order.find params[:id]
end
def update_order
#order=Order.find params[:id]
#order=Order.where(order_no = params[:order_no])
if #order.update_attributes(order_params)
flash[:success] = "Order updated"
redirect_to :action=>"login"
else
render "edit_order"
end
end
And I am getting the following error..
ActiveRecord::RecordNotFound in UsersController#update_orderSummary
Couldn't find Order with 'id'=
Kindly please help me..
You should put your order actions into a separate controller:
#config/routes.rb
resources :orders, only: [:edit, :update], module: :users #-> url.com/orders/:id/edit
#app/controllers/users/orders_controller.rb
class Users::OrdersController < ApplicationController
def edit
#order = Order.find params[:id]
end
def update
#order = Order.find params[:id]
#orders = Order.where order_no: params[:order][:order_no]
if #orders.update_all order_params
redirect_to action: :logic, success: "Order Updated"
end
end
private
def order_params
params.require(:order).permit(:order_no, :order_date)
end
end
#app/views/users/orders/new.html.erb
<%= form_for #order do |f| %>
<%= f.text_field :order_no %>
<%= f.text_field :order_date %>
<%= f.submit %>
<% end %>
Your main problem is that you're trying to do two things with the update method -- Order.find && Order.where.
You can't update both - you have to do one.
I have used update_all, which can be used on your Order.where collection; if you wanted to update a single object, just use #order.update
Added an admin view to my rails app (this: http://www.interque.co/). Added a boolean state for approved to each question. I'm trying to toggle that state by clicking a link I've labeled approved.
Here is my controller:
class AdminController < ApplicationController
def index
#questions = Question.all
unless current_user && current_user.administrator?
redirect_to root_path
end
end
end
Here's the admin view I'm working with, which lists all unapproved questions:
<% if current_user %>
<% #questions.each do |question| %>
<% if question.approved == false %>
<div>
Title: <%= question.title %><br>
Description: <%= question.description %><br>
<%= link_to "Approve", question_path(question), :method => :put %>
</div>
<br>
<% end %>
<% end %>
<% end %>
Can I toggle the state by clicking a link_to? I just need to set question.approved = true.
Any help would be appreciated. Thanks in advance.
Add remote: true to your link and add a controller action that sets boolean state. You'll probably want to check that link is changed to 'approved' after that (included in the answer). Another good thing will be displaying an error message in case of error and disabling link during request.
config/routes.rb
resources :questions do
member do
put :approve
end
end
views/admin/index.html.erb
<span class="approve-question">
<%= link_to "Approve", approve_question_path(question), :method => :put, remote: true %>
</span>
views/questions/approve.js.erb
$('.approve-question').html('Approved');
controllers/questions_controller.rb
respond_to :js
def approve
#question = Question.find(params[:id])
if #question.update(approved: true)
render
else
render #question
end
end
I've been following this, making modifications where necessary.
I have equivalents of #post and #comment. My comments are 'questions'. I've tried following this procedure again but to the comments (rather than posts). Comments on comments if you like, these are answers/responses to the questions.
I've not been successful in getting this to work.
undefined method 'answers' for nil:NilClass`
is the error in answers/_form.html.erb which is rendered as part of a comment, which is in turn rendered as part of my post equivalent.
<%= form_for([#question, #question.answers.build]) do |f| %> is the line that raises the exception. I'm thinking the problem is that #question isn't being given a value for some reason?
Either that or my routes file isn't right (would be my guess at least).
resources :posts-equivalent do
...
resources :questions
end
resources :questions do
resources :answers
end
This has had me stumped all day - any ideas would be appreciated. If you'd like to see any more code drop a comment and I'll update it here.
Additional Code:
Error Message:
Showing .../app/views/answers/_form.html.erb where line #1 raised:
undefined method `answers' for nil:NilClass
Extracted source (around line #1):
1: <%= form_for([#question, #question.answers.build]) do |f| %>
Answers Controller:
class AnswersController < ApplicationController
def create
#question = Question.find(params[:question_id])
#answer = #question.answers.create(params[:answer])
redirect_to concept_path(#question.concept)
end
end
It looks like your AnswersController is not assigning a value to the #question instance variable. It's not clear what action you are running, but I'm assuming it's either new or edit based on the fact that you have a form. You should have something like this in those actions:
class AnswersController < ApplicationController
def new
#question = Question.find(params[:question_id])
#answer = #question.answers.new
end
def edit
#question = Question.find(params[:question_id])
#answer = #question.answers.find(params[:id])
end
end
Then you can have a single form shared between new and edit:
<%= form_for([#question, #answer]) %>
In the end I sorted this in a different manner. Each question was only ever going to have one answer and so I just gave question an answer attribute and assigned that.
On the post page:
...
<%= render #questions %>
<%= render "questions/form" %>
...
In _form.html.erb
<%= form_for([#concept, #concept.question.build]) do |f| %>
<%= f.hidden_field :contributor_id, :value => session[:contributor_id] %>
<div class="field">
<%= f.text_field :question, :placeholder => "Follow-up Question" %>
</div>
<% end %>
In the _question.html.erb
<%= form_for(question) do |f| %>
<div id="question">
"<%= question.question %>" asked by <%= question.contributor.email %> | <%= question.created_at %>.
<div id="answer">
- Answer: <%= question.answer %>
<%= f.text_field :answer, :placeholder => "Respond..." %>
</div>
</div>
<% end %>
Add this to the questions controller:
def update
#question = Question.find(params[:id])
#question.update_attributes(params[:question])
#concept = Concept.find(#question.concept.id)
redirect_to concept_path(#concept)
end
And that worked for me, I know it's not what I originally asked but that fixed my problem. Thanks to those who did try to help.