Error: param is missing or the value is empty:retweet - ruby-on-rails

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

Related

question id is not changing for user_choice

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>
.
.
.
.

Mailboxer N+1 Query detected

I managed to install Mailboxer with this tutorial but i have a recurring error :
N+1 Query detected
Mailboxer::Message => [:sender]
Add to your finder: :includes => [:sender]
N+1 Query method call stack
app/views/conversations/_messages.html.erb:12:in `block in _app_views_conversations__messages_html_erb__3829465222244059655_69982701059040'
app/views/conversations/_messages.html.erb:1:in `_app_views_conversations__messages_html_erb__3829465222244059655_69982701059040'
app/views/conversations/show.html.erb:27:in `_app_views_conversations_show_html_erb__1439517360344897040_69982700516580'
app/views/conversations/_messages.html.erb:12:in `block in _app_views_conversations__messages_html_erb__3829465222244059655_69982701059040'
app/views/conversations/_messages.html.erb:1:in `_app_views_conversations__messages_html_erb__3829465222244059655_69982701059040'
app/views/conversations/show.html.erb:27:in `_app_views_conversations_show_html_erb__1439517360344897040_69982700516580'
I had another one for :message but i fixed the problem with includes. If i try to do the same with :sender, i have this error:
Association named 'sender' was not found on Mailboxer::Receipt; perhaps you misspelled it?
Tutorial original code : conversations_controller.rb
class ConversationsController < ApplicationController
before_action :authenticate_user!
def new
end
def create
recipients = User.where(id: conversation_params[:recipients])
conversation = current_user.send_message(recipients, conversation_params[:body], conversation_params[:subject]).conversation
flash[:success] = "Your message was successfully sent!"
redirect_to conversation_path(conversation)
end
def show
#receipts = conversation.receipts_for(current_user)
# mark conversation as read
conversation.mark_as_read(current_user)
end
def reply
current_user.reply_to_conversation(conversation, message_params[:body])
flash[:notice] = "Your reply message was successfully sent!"
redirect_to conversation_path(conversation)
end
def trash
conversation.move_to_trash(current_user)
redirect_to mailbox_inbox_path
end
def untrash
conversation.untrash(current_user)
redirect_to mailbox_inbox_path
end
private
def conversation_params
params.require(:conversation).permit(:subject, :body,recipients:[])
end
def message_params
params.require(:message).permit(:body, :subject)
end
end
Tutorial original code : show.html.erb
<div class="row">
<div class="spacer"></div>
<div class="col-md-6">
<%= link_to "Compose", new_conversation_path, class: "btn btn-success" %>
</div>
<div class="col-md-6 text-right">
<% if conversation.is_trashed?(current_user) %>
<%= link_to 'Untrash', untrash_conversation_path(conversation), class: 'btn btn-info', method: :post %>
<% else %>
<%= link_to 'Move to trash', trash_conversation_path(conversation), class: 'btn btn-danger', method: :post,
data: {confirm: 'Are you sure?'} %>
<% end %>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-body">
<%= render 'mailbox/folders' %>
</div>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-body">
<%= render partial: 'messages' %>
</div>
<div class="panel-footer">
<!-- Reply Form -->
<%= form_for :message, url: reply_conversation_path(conversation) do |f| %>
<div class="form-group">
<%= f.text_area :body, placeholder: "Reply Message", rows: 4, class: "form-control" %>
</div>
<%= f.submit "Reply", class: 'btn btn-danger pull-right' %>
<% end %>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
Tutorial original code : _messages.html.erb
<% #receipts.each do |receipt| %>
<% message = receipt.message %>
<div class="media">
<div class="media-left">
<!-- user avators can go here -->
<a href="#">
<img class="media-object" src="http://placehold.it/64x64" alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">
<%= message.sender.username %> <br>
<small><b>Subject: </b><%= message.subject %></small><br>
<small><b>Date: </b><%= message.created_at.strftime("%A, %b %d, %Y at %I:%M%p") %></small>
</h4>
<%= message.body %>
</div>
</div>
<% end %>
If i delete <%= message.sender.username %> the problem is solved...
Any ideas ?
Normally, to fix these N+1 query problems we use an includes and by passing a hash, we can includes nested associations. So looking at this code, calling receipt.message.sender is triggering the error, so we have a Receipt model, a message association on it and a sender associated to that. So if we can find where we load the Receipt we can add includes(message: :user) like we would for any other model.
Digging into the mailboxer gem, the receipts_for method in your show action is just a wrapper for a couple of scopes on Mailboxer::Receipt. Since this method just runs some scopes for you, we can chain onto the end of it as if it were a normal ActiveRecord where chain.
So with all that in mind, we should be able to add on our includes and avoid the N+1 query problem, ending up with something like
#receipts = conversation.receipts_for(current_user).includes(message: :sender)

(Ruby on Rails) Trying To Edit A Post Using Partials But Having Problems

I'm making a bloglike application. I want to make it so that blog posts are editable if clicked.
This is my partial that displays all the posts of a user and makes them clickable
<% if #feed_items.any? %>
<% #feed_items.in_groups_of(3, false).each do |feeds| %>
<div class="row">
<% feeds.each do |feed| %>
<div class="col-md-4">
<ol class="posts">
<%= link_to edit_post_path(feed) do %>
<%= render feed %>
<% end %>
</ol>
</div>
<% end %>
</div>
<% end %>
<% end %>
This is the Edit view that it redirects to when a post is clicked:
<% if logged_in? %>
<div class="row">
<%= render 'shared/post_form' %>
</div>
<% end %>
And this is the '_post_form' partial which is the layout for an editable post:
<%= form_for(#post) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new post..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
When I click a post to edit it it does redirect however it gives me the error: "First argument in form cannot contain nil or be empty"
Any suggestions on how to resolve this?
In your controller's edit method you have to set #post like,
def edit
#post = Post.find(params[:id])
end

Rails show error message of another model

I have a html partial that displays errors:
shared/model_errors.html.erb
<% model.errors.full_messages.each do |msg| %>
and I render it at top of each html file like
<%= render partial: 'shared/model_errors',locals: {model: #model_to_check_errors}%>
This is working fine for most of them.
Let's say that I'm on the show.html.erb template of the ConversationsController, and I have there a form_tag which submits messages to the MessagesController. If the submitted message is empty, the MessagesController won't allow it to be saved, because it has validation errors. How do I display those validations errors in my show.html.erb, considering I don't have access to the #message object of the create action of the MessagesController. Is there any way to add the error message to the ConversationsController? They will be displayed that way.
Edit:
show.html.erb of the ConversationsController
<div class="container nav_exp">
<%= render partial: 'shared/model_errors',locals: {model: #???}%>
<div class="ch-body">
<div class="col-md-12 bg-white ">
<div class="chat-message">
<ul class="chat" id="messages">
<% if #messages != nil %>
<%= render partial: 'conv_message', collection: #messages,:as => :message%>
<% else %>
<div class="panel-body hidden"></div>
<%end%>
</ul>
</div>
<%=form_tag(messages_path, :method=>'post',authenticity_token: true,remote: true) do%>
<div class="chat-box bg-white">
<div class="input-group">
<%= text_field_tag :body,"", id:"message_body",class: "form-control border no-shadow no-rounded", placeholder: "Type your message here"%>
<%= hidden_field_tag :conversation_id, #conversation.id %>
<%= hidden_field_tag :receiver, #other.id %>
<span class="input-group-btn">
<%= submit_tag 'Submit', class: "btn btn-success no-rounded" %>
</span>
</div><!-- /input-group -->
</div>
<% end %>
</div>
</div>
</div>
The create method of the MessagesController - messages_path
def create
message = Message.new(message_params)
message.user = current_user
if message.save
...
else
puts 'not working'
'I think 1 solution would be to add here flash messsages'
end
end
private
def message_params
params.permit(:body, :conversation_id, :receiver)
end

partial form not creating new value RoR

I am new to Ruby on Rails. My Question might sound weird, but i am stuck. i have a form Create that is on html page. i used render partial, but this form is not creating any value. here is my controller code.
Controller.rb
before_filter :signed_in_user, only: [:create, :destroy]
def create
#suppliers = current_user.suppliers.build(params[:supplier_name])
if #suppliers.save
flash[:success] = "Supplier Saved!"
redirect_to 'suppliers/home'
else
render 'suppliers/home'
end
end
def destroy
end
def home
if signed_in?
#supplier = current_user.suppliers.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
my home.html.erb
<div class="row">
<aside class="span4">
<section>
<%= render 'suppliers/suppliers_form' %>
</section>
</aside>
<div class="span8">
<h3>Micropost Feed</h3>
<%= render 'suppliers/feed_supplier' %>
</div>
</div>
My _supplier_form.html.erb is
<%= form_for(#supplier) do |f| %>
<div>
<%= f.text_field :supplier_name, placeholder: "Add new Supplier" %>
</div>
<%= f.submit "Add", class: "btn btn-large btn-primary" %>
<% end %>
My _feed_supplier.html.erb is
<% if #feed_items.any? %>
<ol class="microposts">
<%= render partial: 'suppliers/feed_item', collection: #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
my _feed_item.html.erb is
<li id="<%= feed_item.id %>">
<span class="user">
<%= link_to feed_item.user.name, feed_item.user %>
</span>
<span class="content"><%= feed_item.supplier_name %></span>
</li>
please guide me to right direction, and if anything else is required then do ask. Thanks in advance
Note: all the mentioned files are in same folder i.e. suppliers. except the controller file
form_for #supplier
will create a parameter hash like
{ :supplier => { :supplier_name => '[some value you put in your form]' }}
so the create action should use
#suppliers = current_user.suppliers.build(params[:supplier])
There is no params[:supplier_name].
I think for the partials, you don't need to write suppliers/*, for example:
<%= render 'suppliers/suppliers_form' %>
could just be
<%= render 'suppliers_form' %>
not sure why that would be causing your app to do what it's doing, but worth a try!

Resources