question id is not changing for user_choice - ruby-on-rails

Here is my
question.controller
class QuestionsController < ApplicationController
def index
#questions = Question.all
end
def new
#question=Question.new
end
def create
#question=Question.new(question_params)
if #question.save
flash[:success] = "Question saved successfully"
redirect_to questions_url, notice: "Sucessfully created question"
else
render :new
end
end
private
def question_params
params.require(:mc_question).permit(:question, :option1, :option2, :option3, :option4, :answer)
end
# def result
# #question = Question.find(params[:id])
# #question.update(result_params) # not sure this is best way here, need to research a better way to create the nested resources rather than update
# end
# private
# def result_params
# params.require(:result).permit(result_attributes: [:user_choice, :question_id, :user_id])
# end
end
My result controller:
class ResultController < ApplicationController
def create
#result=Result.create(user_choice: params[:user_choice],
question_id: params[:question_id],
user_id: current_user.id)
end
end
My index for question and storing user_choice:
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body ">
<!-- Nested Row within Card Body -->
<div class="row py-5">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4 ">Multiple-Choice Questions</h1>
</div>
<%= form_with model: #result ,url: result_path do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<% #questions.each do |question| %>
<%= f.fields_for #questions do |fa|%> # with this i get nothing no error and no save
<%= fa.hidden_field :question_id, value: question.id %>
<%end%>
<%= f.hidden_field :user_id, value: current_user.id %>
<p><%= question.question %></p>
<% choices = [question.option1, question.option2, question.option3, question.option4] %>
<% choices.each do |c| %>
<div>
<%= f.radio_button :"user_choice[#{question.id}]", c %>
<%= f.label :user_choice, c %>
</div>
<%end%>
<% end %>
<div class="sub"> <%= f.submit "Submit", class:"btn btn-primary" %></div>
<% end %>
<div class="para1"><%= link_to 'New Question', new_question_path,class:"btn btn-primary btn-user" %>
</div>
</div>
</div>
</div>
</div>
</div>
With this
with this i get save everything but question id comes the last question id for every choice like if i have 12 questions then 12 will come for each choice
<%= fa.hidden_field :question_id, value: question.id %>
<%end%>
<%= f.hidden_field :user_id, value: current_user.id %>
I want a different id for each choice please help me if anyone knows what's the issue and how to solve it.

The reason you have that is because you have placed <%= fa.hidden_field :question_id, value: question.id %> inside of this loop <%= f.fields_for #questions do |fa|%> and it will populate using only one instance of your parent loop. Sort of like for i in 0...12 for j in 0...13 for every i instance, the j loop will run 13 times.
Long story short, do this
<% #questions.each do |question| %>
<%= fa.hidden_field :question_id, value: question.id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<p><%= question.question %></p>
<% choices = [question.option1, question.option2, question.option3,
question.option4] %>
<% choices.each do |c| %>
<div>
.
.
.
.

Related

form_with produces first record as nil

comment controller
class CommentsController < ApplicationController
before_action :load_commentable
before_action :checked_logged_in, only: [ :create]
def new
#comment = #commentabl.comments.new
end
def create
#comment = #commentable.comments.new(comment_params)
#comment.user_id = current_user.id
#comment.commenter = current_user.username
if #comment.blank? || #comment.save
flash[:success] = "Commented was created"
ActionCable.server.broadcast 'comment_channel',
commenter: current_user.username,
comment: #comment.content
redirect_to #commentable
else
flash[:danger] = render_to_string(:partial => 'shared/error_form_messaging',
:locals => {obj: #comment},
format: :html)
redirect_to #commentable
end
end
private
def comment_params
params.require(:comment).permit(:content, :commenter, :user_id)
end
def load_commentable
resource, id = request.path.split('/')[1,2]
#commentable = resource.singularize.classify.constantize.find(id)
end
def checked_logged_in
unless logged_in?
flash[:danger] = 'please log in to be able to comment'
redirect_to login_path
end
end
end
my form for creating a comment:
<%= form_with model:[commentable, commentable.comments.new], :html => {class: "form-horizontal", role:"form"} , local: true do |form| %>
<div class="form-group">
<div class="control-label col-sm-2">
<%= form.label :content, 'Comment' %>
</div>
<div class="col-sm-8">
<%= form.text_field :content , class: 'form-control', placeholder: "enter your comment here", autofocus: true %>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<%= form.submit 'Comment' , class: ' btn btn-primary' %>
</div>
</div>
<% end %>
the form is called in show.html.erb
<h2 class="text-center">
Title: <%= #article.title %>
</h2>
<div class="well col-xs-8 col-xs-offset-2">
<div id="user-info-showpage" align="center">
Created by: <%= render 'shared/user-info', obj: #article.user %>
</div>
<h4 class="text-center">
<strong>Description:</strong>
</h4>
<hr />
<%= simple_format(#article.description) %>
<% if #article.categories.any? %>
<p>Categories: <%= render #article.categories %></p>
<% end %>
<div class="article-actions">
<% if logged_in? && (current_user == #article.user || current_user.admin?) %>
<%= link_to "Delete", article_path(#article), method: :delete,
data: {confirm: "Are you sure you want to delete the article?"},
class: 'btn btn-xs btn-danger' %>
<%= link_to "Edit", edit_article_path(#article), class: 'btn btn-xs btn-success'%>
<%end%>
<%= link_to "View All Articles", articles_path , class: 'btn btn-xs btn-primary'%>
</div>
</div>
<% if logged_in? %>
<div class="col-xs-8 col-xs-offset-2">
<%#= render partial: 'comments/form', :locals => {commentable: #article} %>
</div>
<%end%>
<div class="col-xs-8 col-xs-offset-2">
<div id="comments"></div>
<%= #article.comments.inspect %>
<% #article.comments.each do |c| %>
<div class="well">
<%= c.content %> by
<%= c.commenter %>
</div>
<%end%>
<div id="comments"></div>
</div>
my result is in view is
Please if more info needed, ask me so I can provide
Note: I am not sure this empty record is owing to commentable.comments to be nil or I miss something
I commented render form in show page and now the empty record is gone, so my issue must be related to form_with
From my understanding, you
Expect:
in your articles#show page to not show the empty by _________ <div> HTML because the comment is still built (still in-memory), and not yet saved (not yet in DB).
Solution 1:
app/views/articles/show.html.erb
...
<div class="col-xs-8 col-xs-offset-2">
<div id="comments"></div>
<% #article.comments.each do |c| %>
<!-- ADD THIS LINE -->
<% if c.persisted? %>
<div class="well">
<%= c.content %> by
<%= c.commenter %>
</div>
<% end %>
<%end%>
<div id="comments"></div>
</div>
...
Solution 2 (better but still is a workaround):
app/views/comments/_form.html.erb
<%= form_with model:[commentable, Comment.new(commentable: commentable)], :html => {class: "form-horizontal", role:"form"} , local: true do |form| %>
Explanation:
The reason the page is displaying an empty by _________ <div> is that because you "built" a new comment before .each is called. Because they are sharing same memory space, the build basically also adds it to the array in-memory. See the following:
# rails console
article = Article.create!
comment1 = Comment.create!(commentable: article)
# from here, comment1 is then saved already in the DB
# now let's see what happens when you use "build" or "new"
# They have differences, it seem: for details: https://stackoverflow.com/questions/1253426/what-is-the-difference-between-build-and-new-on-rails/1253462
# redefine (to simulate your #article = Article.find(params[:id])
article = Article.find(article.id)
comment2 = article.comments.build
puts article.comments.count
# SQL: Select count(*) FROM ...
# => 1
puts article.comments.size
# => 2
# notice how `count` and `size` are different. `count` value is "DB-based" while `size` is "memory-based". This is because `count` is an `ActiveRecord` method while `size` is a delegated `Array` method.
# now let's simulate your actual problem in the view, where you were looping...
article.comments.each do |comment|
puts comment
end
# => <Comment id: 1>
# => <Comment id: nil>
# notice that you got 2 comments:
# one is that which is already persisted in DB
# and the other is the "built" one
# the behaviour above is to be expected because `.each` is a delegated `Array` method
# which is agnostic to where its items come from (DB or not)
This is the reason why in your page, the "built" comment is shown in the page because you are calling
<%= render partial: 'comments/form', :locals => {commentable: #article} %>
... which calls commentable.comments.build
BEFORE the <% "article.comments.each do |c| %>
If this is not clear enough yet, try putting
<%= render partial: 'comments/form', :locals => {commentable: #article} %>
... which calls commentable.comments.build
AFTER the <% "article.comments.each do |c| %> ... <% end %>
... and the by _________ <div> should already not show up.

How does my index page need to be written in order to display data?

I am developing a form that is dropdown in nature for the first time. With the help of some of you I have been successful thus far, but at this point I am creating the app/index.html.erb page:
<% #jobs.each do |job| %>
<h2><%= #job.category %></h2>
<p><%= #job.poster %></p>
<% end %>
The code above is rendering the following error:
NoMethodError in Jobs#index
undefined method `category' for nil:NilClass
I thought the code was telling me that I had nil in category which I did and so I updated category as well as others in rails console, but I continue to receive this error and I am not sure why nor how to fix it.
In my app/show.html.erb the code is similar:
<h1><%= #job.category %></h1>
<p><%= #job.poster %></p>
<p><%= #job.location %></p>
<p><%= #job.description %></p>
<%= link_to "Home", root_path %>
and it works just fine.
This is my form partial:
<%= simple_form_for(#job, html: {class: 'form-horizontal'}) do |f| %>
<div class="control-group">
<%= f.label "Poster:", class: 'control-label' %>
<div class="controls">
<%= f.select(:poster, options_for_select([['Nick Maloney','Nick Maloney'],
['Peter Brown','Peter Brown'],['Jen Morris','Jen Morris']])) %>
</div>
</div>
<div class="control-group">
<%= f.label "Category:", class: 'control-label' %>
<div class="controls">
<%= f.select(:category, options_for_select([['Landscaping','Landscaping'],
['Babysitting','Babysitting'],['Tree planting','Tree planting']])) %>
</div>
</div>
<div class="control-group">
<%= f.label "Location:", class: 'control-label' %>
<div class="controls">
<%= f.select(:location, options_for_select([['Dorchester','Dorchester'],
['Roxbury','Roxbury'],['Mattapan','Mattapan']])) %>
</div>
</div>
<div class="control-group">
<%= f.label "Status:", class: 'control-label' %>
<div class="controls">
<%= f.select(:status, options_for_select([['New','New'],
['Pending','Pending'],['Complete','Complete']])) %>
</div>
</div>
<%= f.input :description, label: "Job Description" %>
<%= f.submit 'Add Job', class: 'btn btn-default' %>
<% end %>
and this is my jobs_controller.rb:
class JobsController < ApplicationController
before_action :find_job, only: [:show, :edit, :update, :destroy]
def index
#jobs = Job.all.order("created_at DESC")
end
def show
end
def new
#job = Job.new
end
def create
#job = Job.new(jobs_params)
if #job.save
redirect_to #job, notice: 'Your job was successfully added'
else
render "New"
end
end
def edit
end
def update
end
def destroy
end
private
def jobs_params
params.require(:job).permit(:poster, :category, :location, :status, :description)
end
def find_job
#job = Job.find(params[:id])
end
end
It depends on what value has #job, note that when you iterate over jobs assign a block variable called job, but then inside you want to get the category attribute from #job, the instance variable, and Rails will try to know where does that variable come from and what's the value.
Try job.attribute:
<% #jobs.each do |job| %>
<h2><%= job.category %></h2>
<p><%= job.poster %></p>
<% end %>
#job isn't available in your index view, because your index method has a #jobs variable with all the Job records. And the reason you can access #job.category in your show method is because you have a #job variable created in the private method find_job which is available in such method thanks the before_action callback setted in the second line.

Error: param is missing or the value is empty:retweet

I am new to Rails. I want to pass parameters to DB via controller, but I receive this error param is missing or the value is empty:retweet. I think the problem is the way of passing parameters in view.
Here is the view
<% for #p in #posts %>
<div class="panel panel-default post-panel">
<div class="panel-body row">
<div class="col-sm-1">
<img src="/avatar.png" class="rounded-img" height="50px" width="50px">
</div>
<div class="col-sm-11">
<p class="post-title"><%= User.find(#p.user_id).username %> <span class="post-creation">- <%= #p.created_at.to_formatted_s(:short) %></span></p>
<p class="post-content"><%= #p.content %></p>
</div>
<div class="col-sm-12">
<p class="post-links">
<span class="glyphicon glyphicon-comment g-links" aria-hidden="true"></span>
**<%= form_for Retweet.new do |f| %>
<%= hidden_field_tag current_user.id, (:user_id) %>
<%= hidden_field_tag #p.id, (:post_id) %>
<%= f.submit "Retweet", class:"btn btn-primary"%>**
<% end %>
And here is the Controller
def new
#retweet = Retweet.new
end
def create
#retweet = Retweet.new(post_params)
redirect_to(:back)
end
private def post_params
params.require(:retweet).permit(:user_id, :post_id)
end
end
You should read up some tutorials on basic REST controllers in Rails. Your create action didn't save the retweet.
def create
#retweet = Retweet.new(post_params)
if #retweet.save
redirect_to(:back)
else
render action: 'new'
end
end
Edit: Just noticed your form is all wrong:
<%= form_for Retweet.new do |f| %>
<%= f.hidden_field :user_id, current_user.id %>
<%= f.hidden_field :post_id, #p.id %>
<%= f.submit "Retweet", class:"btn btn-primary"%>**
<% end %>
Mind you that you shouldn't allow settign the user_id like this, it is very easy to change it and thus mess around with your data. Instead you should add this to retweet#create:
#retweet.user = current_user

Rails: Two different NoMethodError's when trying to display files

I'm making a basic application and I made it so a user can attach a file to a form post. That all works perfectly fine, but now I'm trying to display a link to the file and it doesn't seem to work.
I'm getting two errors. One if I attach a file and another if I don't attach a file. They both say undefined method 'doc=' for nil:NilClass but are on different lines of code.
If I don't upload a file this is what I get: NoMethodError in Projects#index on this line of code <% if #project.doc %>.
If I do upload a file this is what I get: NoMethodError in ProjectsController#create on this line of code #project.doc = uploaded_io.original_filename
projects_controller.rb
class ProjectsController < ApplicationController
def index
#projects = Project.all
end
def show
end
def new
#projects = Project.new
end
def create #no view
#projects = Project.new(project_params)
uploaded_io = params[:doc]
if uploaded_io.present?
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
file.write(uploaded_io.read)
#project.doc = uploaded_io.original_filename
end
end
if #projects.save
redirect_to projects_path, :notice => "Your project was sent!"
else
render "new"
end
end
def edit
#projects = Project.find(params[:id])
end
def update #no view
#projects = Project.find(params[:id])
if #projects.update_attributes(project_params)
redirect_to projects_path, :notice => "Your project has been updated."
else
render "edit"
end
end
def destroy #no view
#projects = Project.find(params[:id])
#projects.destroy
redirect_to projects_path, :notice => "Your project has been deleted."
end
private
def project_params
params.require(:project).permit(:title, :description)
end
end
index.html.erb
<div class="container">
<div class="page-header">
<h1>Projects<small> Here are all of your projects.</small></h1>
</div>
</div>
<% #projects.each do |project| %>
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<%= project.title %>
</div>
</div>
<div class="panel-body">
<p>
<%= project.description %>
</p>
<br>
<%= link_to "Discuss", new_project_discussion_path(project) %> |
<%= link_to "Tasks", new_project_task_path(project) %> |
<%= link_to "Edit", edit_project_path(project) %> |
<%= link_to "Delete", project, :method => :delete %>
<% if #project.doc %>
<p>Document: <%= link_to #project.doc, "/uploads/#{#project.doc}", :target => "_blank" %></p>
<% end %>
</div>
</div>
<%end%>
<br>
<br>
<div class="container">
<p><a class="btn btn-primary btn-lg" href="/projects/new" role="button">Create project</a></p>
</div>
_form.html.erb
<%= form_for(#projects, :html => { :multipart => true}) do |f| %>
<% if #projects.errors.any? %>
<ul>
<% #projects.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<div class="container">
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: "form-control" %>
</div>
<%= label_tag :doc, 'Files (optional)' %>
<%= file_field_tag :doc %>
<br>
<div class="form-group">
<%= f.submit "Submit Project", class: "btn btn-primary" %>
</div>
<% end %>
Updated :
You have many errors, here are a few that I found :
uploaded_io = params[:doc]
Should be
uploaded_io = params[:project][:doc]
Also delete this line
#project.doc = uploaded_io.original_filename
You don't need that.
Finally, in your views, you should have project.doc instead of #project.doc

recipient checklist with text_area form

I am working on implementing a form where a user can compose a message and choose multiple recipients from a checklist in the same form.
I have already built and tested the messaging system which is working but now I want to create the proper form for my desired functionality.
When I use a multipart select form it works fine and looks like this.
<%= form_for #message do |f| %>
<div class="modal-body">
<%= f.text_area :body, class: "form-control"%>
</div>
<!-- displays the current users frinds their following -->
<%= f.select :user_tokens, #user.collect {|x| [x.name, x.id]}, {}, :multiple => true, class: "form-control" %>
<br>
<div class="modal-footer">
<%= f.button :submit, class: "btn btn-primary" %>
</div>
<% end %>
But I want to instead display the users in a checklist, this is what I have so far which displays everything with no errors, but dosent send messages.
<div class="results">
<%= form_tag new_message_path, method: 'get' do %>
<div class="modal-body">
<%= text_area :body, class: "form-control"%>
</div>
<table class="table-bordered">
<thead>
<tr>
<td class="col-md-1">Select</td>
<td class="col-md-1">User</td>
</tr>
</thead>
<% #user.each do |user| %>
<tbody>
<tr>
<td><%= radio_button_tag :user_tokens, user.id %></td>
<td><%= user.name %></td>
</tr>
</tbody>
<% end %>
</table>
<%= submit_tag "Send Message", :name => nil, class: "btn btn-primary" %>
</div>
<% end %>
</div>
Here is my controller
class MessagesController < ApplicationController
before_action :authenticate_user!
def new
#message = Message.new
#user = current_user.following
#users = User.all
end
def create
#message = current_user.messages.build(message_params)
if #message.save
flash[:success] = "Message Sent!"
redirect_to messages_path
else
flash[:notice] = "Oops!"
render 'new'
end
end
def index
#user = User.find(current_user)
#messages = Recipient.where(:user_id => #user).order("created_at DESC")
end
private
def message_params
params.require(:message).permit(:body, :sender_id, user_tokens: [])
end
end
My question is what is the best way to get this functionality?
Let me know if you need to see any other info, thanks.
I ended up figuring it out Thanks to this previous post I found, rails 3 has_many :through Form with checkboxes.
<%= form_for #message do |f| %>
<%= f.text_field :body %>
<p>
<% #user.each do |user| %>
<div>
<%= check_box_tag "message[user_tokens][]", user.id, #message.users.include?(user) %>
<%= user.name %>
</div>
<% end %>
</p>
<p><%= f.submit %></p>
<% end %>

Resources