Ruby on Rails multiple Buttons - ruby-on-rails

I have the following written:
<% if #document != nil %>
<%= form_for(#document, :html => { :multipart => true }) do |f| %>
<% if #document.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#document.errors.count, "error") %> prohibited this document from being saved:</h2>
<ul>
<% #document.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<%= render partial: 'documents/resume' %>
<div id="add_buttons">
<%= f.file_field :resume %>
<%= f.submit %>
</div>
<% end %>
<% else %>
<h1>No Document Available</h1>
<% end %>
Sorry about the indenting, copy/paste didn't paste it right. Anyways, this is using paperclip and works fine to upload a document as long as in the resume partial that I have listed I have my delete button commented out. Here is the code for that partial:
<div class='Resume_1'>
<%#= #current_user = session[:user] %>
<%#= #document = #current_user[:document] %>
Current Resume:
<%= render partial: 'documents/resumelink' %>
</div>
<div class='Resume_2'>
<% if (#document != nil) && (#document.resume_file_name != nil) %>
<%= button_to "Delete Resume", #document, method: :delete, data: { confirm: 'Are you sure you wish to delete your resume?' } %>
<% end %>
</div>
If the button_to line is commented out, the update document (f.submit) button works fine. However, if the button_to line is left in, the f.submit button does nothing. And here's the destroy function (which is where the delete method is routed to) since this doesn't actually seem to remove the resume either.
def destroy
#document.resume = nil
respond_to do |format|
format.html { redirect_to welcome_url, notice: 'Resume was successfully deleted.' }
format.json { head :no_content }
end
end
Thanks for any help.

If you look at docs. The html generated by button_to helper is
<%= button_to "New", action: "new" %>
# => "<form method="post" action="/controller/new" class="button_to">
# <div><input value="New" type="submit" /></div>
# </form>"
So when you have a button_to inside a form you basically have a form inside a form and hence your submit button doesn't work.
Fix:
Instead of using a button_to use link_to helper and give bootstrap classes or some custom class to make it look like a button
<%= link_to "Delete Resume", #document, class: "btn btn-default" method: :delete, data: { confirm: 'Are you sure you wish to delete your resume?' } %>

Related

How can I make follow form work with a list

I have a relationship model that follow users back n forth
now it works very well when I use it in users#show in my view just like this screenshot
now this works good but what I have is a list of users.. and with that list I want to render similar type of follow form next to every item in list
here is the screenshot for reference
but of course this doesn't work because in my relationship controller I am finding user/amitian to follow with their id in params[:id] as in show page i have it but in my list page i don't
here is the code in controller for reference
def create
#amitian = Amitian.find(params[:followed_id])
current_amitian.follow(#amitian)
respond_to do |format|
format.html { redirect_to #amitian }
format.js
end
end
def destroy
#amitian = Relationship.find(params[:id]).followed
current_amitian.unfollow(#amitian)
respond_to do |format|
format.html { redirect_to #amitian }
format.js
end
end
is there any solution for this so that I can render a follow_form in my listpage
it doesn't matter even if i have to render a new follow_form.. it just i want follow mechanism to work even from list page rather than only from show page of every user.
here is the show form in my show page..
show_form
<%if amitian_signed_in?%>
<% if #amitian != current_amitian %>
<div id="follow_form">
<% if current_amitian.following?(#amitian) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
<%end%>
follow_form
<%if amitian_signed_in?%>
<%= form_for(current_amitian.active_relationships.build , remote: true ) do |f| %>
<div><%= hidden_field_tag :followed_id, #amitian.id %></div>
<%= f.submit "Follow", class: "btn btn-primary form-control" %>
<% end %>
<%end%>
unfollow form
<%if amitian_signed_in?%>
<%= form_for(current_amitian.active_relationships.find_by(followed_id: #amitian.id), remote: true,
html: { method: :delete }) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-danger form-control" %>
<% end %>
<%end %>

Following users on Ruby on Rails

I decided to upgrade code of https://www.railstutorial.org/book chapter 14 Following users. My code does not work, when current_user goes on another page and open following. current_user sees himself and want to unfollow like original instagram. unfollow button does not work
show_follow.html.erb:
<div class="line-gray-modals"></div>
<% if #users.any? %>
<% #users.each do |user| %>
<ul class="follow-list">
<li><%= image_tag(user.avatar.url(:thumb), :class => "img-cirkle") %></li>
<li >
<div class="modal-follow-ns" > <div class="bold"> <%= link_to user.username, user %></div> <br>
<div class="modal-follow-ns2"><%= link_to truncate(user.status, :length => 50) %></div></div>
</li>
<li class="button-modal">
<% unless user == current_user %>
<div id="follow_form">
<% if current_user.following?(user) %>
<%= form_for(current_user.relationships.find_by(followed_id: user),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</div>
<% end %>
<% if user == current_user %>
<%= form_for(#user.relationships.find_by(followed_id: user),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% end %>
</li>
<%= will_paginate %>
<li> <div class="line-gray-modals"></div></li>
</ul>
<% end %>
relationships_controller.rb:
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
Terminal:
Completed 500 Internal Server Error in 10ms (ActiveRecord: 1.9ms)
NoMethodError (undefined method `destroy!' for nil:NilClass):
app/models/user.rb:28:in `unfollow!'
app/controllers/relationships_controller.rb:15:in `destroy'
Looking at the code below specially #user is probably nil. changing it to user does not make sense either. since you wanted to unfollow that user.
<%= form_for(#user.relationships.find_by(followed_id: user), html: { method: :delete }, remote: true) do |f| %>
Instead, use current_user
<%= form_for(current_user.relationships.find_by(followed_id: user), html: { method: :delete }, remote: true) do |f| %>

Paginating users with a follow/unfollow button: Ajax runs into problems because of duplicate class names

My users/show.html.erb pages work correctly because there is only one class name displayed on each page. When users are paginated in users/index.html.erb along with follow/unfollow buttons the relationship/js.create.erb and relationship/js.destroy.erb get wacky because there are duplicate class names on the page, (the first paginated user updates regardless of which user is followed/unfollowed and this only fixes itself when the page is refreshed (the actual model still works correctly)).
I did not use the unfollow/follow partials in users/index.html.erb because there is no #user variable in index.html.erb, it paginates #users, so I use user.id.
class RelationshipsController < ApplicationController
before_action :logged_in_user
def create
#user = User.find(params[:followed_id])
current_user.follow(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
**relationships/create.js.erb**
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %> <br> followers');
**relationships/destroy.js.erb**
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= #user.followers.count %> <br> followers');
**users/index.html.erb**
<div class="row community">
<% #users.in_groups_of(3, false).each do |users| %>
<div class="col-sm-12">
<% users.each do |user| %>
<ul class="name-head">
<% unless current_user == user %>
<div id="follow_form">
<% if current_user.following?(user) %>
<%= form_for(current_user.active_relationships.find_by(followed_id: user.id),
html: { method: :delete }, remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-primary" %>
<% end %>
<% else %>
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
<% end %>
</ul>
<div class="col-xs-12">
<div class="col-xs-4">
<a href="<%= following_user_path(user.id) %>">
<center><strong id="following" class:"stat">
<%= user.following.count %><br>
following
</strong></center>
</a>
</div>
<div class="col-xs-4">
<a href="<%= followers_user_path(user.id) %>">
<center><strong id="followers" class="stat">
<%= user.followers.count %><br>
followers
</strong></center>
</a>
</div>
<div class="col-xs-4">
<center><strong id="photo-count" class="stat">
<%= user.photos.count %><br>
photos shared
</strong></center>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
<%= will_paginate %>
**users/show.html.erb**
.
.
.
<li class="follow">
<%= render 'follow_form' if logged_in? %>
</li>
</ul>
</div>
<div class="col-xs-12">
<div class="col-xs-4">
<a href="<%= following_user_path(#user) %>">
<center><strong id="following" class:"stat">
<%= #user.following.count %><br>
following
</strong></center>
</a>
</div>
<div class="col-xs-4">
<a href="<%= followers_user_path(#user) %>">
<center><strong id="followers" class="stat">
<%= #user.followers.count %><br>
followers
</strong></center>
</a>
</div>
<div class="col-xs-4">
<center><strong id="photo-count" class="stat">
<%= #user.photos.count %><br>
photos shared
</strong></center>
</div>
end
**_follow_form.html.erb**
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
**_follow.html.erb**
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, #user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
**_unfollow.html.erb**
<%= form_for(current_user.active_relationships.find_by(followed_id: #user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-primary" %>
<% end %>
Edit: I thought about passing the user_id into the classes, such as:
<div id="follow_form<%="#{user.id}"%>">
which created <div id="follow3">
However I do not know how I can pass this into the destroy.js.erb and create.js.erb
I have tried many combinations such as:
$("#follow_form<%="#{user.id}"%>").html("<%= escape_javascript(render('users/unfollow')) %>");
and
$("#follow_form<%= #user.id%>").html("<%= escape_javascript(render('users/unfollow')) %>");
however, the code is still does not work and even if it did, it would still need work because changing the create/destroy.js.erb files would break the users/show.html.erb follow/unfollow buttons.
EDIT: I have also found this question which is similar but it does not contain an accepted answer.
Edit for Heroku Logs: This is what I get when I follow/unfollow a user on my users/index.html.erb page:
Started DELETE "/relationships/360" for 184.90.97.154 at 2016-05-13 20:05:17 +0000
Processing by RelationshipsController#destroy as JS
Rendered users/_follow.html.erb (1.6ms)
(1.1ms)[0m [1mSELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = $1[0m [["followed_id", 1]]
Started POST "/relationships" for 184.90.97.154 at 2016-05-13 20:07:26 +0000
Processing by RelationshipsController#create as JS
[1m[36m (1.5ms)[0m [1mCOMMIT[0m
I've duplicated your code and, after adding the modifications below, it worked perfectly. (i.e. I don't need a page reload for the "Follow/Unfollow" button to change)
Try the following to see if it works:
users/index.html.erb (only the relevant code here, which is the "Follow/"Unfollow" button)
<ul class="name-head">
<% unless current_user == user %>
<%= render partial: 'follow_form', locals: { user: user } %>
<% end %>
</ul>
users/_follow_form.html.erb
<div id="follow_form-<%= user.id %>">
<% if current_user.following?(user) %>
<%= render partial: 'unfollow', locals: { user: user } %>
<% else %>
<%= render partial: 'follow', locals: { user: user } %>
<% end %>
</div>
users/_unfollow.html.erb
<%= form_for(current_user.active_relationships.find_by(followed_id: user.id), html: { method: :delete }, remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn-default" %>
<% end %>
users/_follow.html.erb
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, user.id %></div>
<%= f.submit "Follow", class: "btn" %>
<% end %>
relationships/create.js.erb
$("#follow_form-<%= #user.id %>").html("<%= escape_javascript(render(partial: 'users/unfollow', locals: { user: #user })) %>");
relationships/destroy.js.erb
$("#follow_form-<%= #user.id %>").html("<%= escape_javascript(render(partial: 'users/follow', locals: { user: #user })) %>");
Note the use of <%= render partial: "_partial.html.erb", locals: { var_name: var } %>. the optional hash locals: { ....... } allows you to pass in a local variable to a partial you want to render (_partial.html.erb) In this case, you also need to add partial: before the name of the partial you want to render.
This way, your user local variable will become available not only in users/index.html.erb, but also in other files listed above.
The problem is in your relationship/js.create.erb and relationship/js.destroy.erb partials, because with your code you only update the first #follow-form div in your page (that is the #follow-form for first user, as you are reporting).
You should change your users\index.html.erb to
<% unless current_user == user %>
<div id="follow-form-<%= user.id %>">
This way, every user will have its unique div element. Then, just modify relationship/js.create.erb as follows:
$("#follow-form-<%= #user.id %>").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %> <br> followers');
and relationship/js.destroy.erb accordingly, then you should have everything working as expected.

Implementing Ajax - Rails App

I'm trying to implement ajax into when I favorite a place, but the reload/update of the section/ajax functionality doesn't work. Only if I reload the page, then I see the action that has occurred. Would appreciate any tips.
My favorite_places/show.html.erb
<div class="heart">
<p class="text-center">
<% if current_user %>
<%- unless current_user.favorite_places.exists?(id: #place.id) -%>
<%= link_to favorite_places_path(place_id: #place), remote: true, method: :post do %>
<span title="Favorite this Place"><i class="glyphicon glyphicon-heart-empty"></i></span>
<% end %>
<%- else -%>
<%= link_to favorite_place_path(#place), remote: true, method: :delete do %>
<span title="Un-Favorite this Place"><i class="glyphicon glyphicon-heart"></i></span>
<% end %>
<% end %>
<% end %>
</p>
</div>
My favorite_places_controller.rb
def update
#favorite_place.update_attributes[params[:place]]
respond_to do |format|
format.html { redirect_to #place }
format.js
end
end
My update.js.erb
<% if #place.favorited %>
$(' #<%= #place.id %>').html("true");
console.log ("<%= #place.name %> has been favorited.");
<% else %>
$(' #<%= #place.id %>').html("false");
console.log ("<%= #place.name %> is not a favorite.");
<% end %>
My dev console output
DELETE http://0.0.0.0:3000/favorite_places/34 406 (Not Acceptable)
jquery.js?body=1:8716send
jquery.js?body=1:8716jQuery.extend.ajax
jquery.js?body=1:8146$.rails.rails.ajax
jquery_ujs.js?body=1:73$.rails.rails.handleRemote
jquery_ujs.js?body=1:149(anonymous function)
jquery_ujs.js?body=1:299jQuery.event.dispatch
jquery.js?body=1:5108elemData.handle

Rails 3.1 - Extra result of each loop?

This is really simple, but i'm going slightly mad and probably missing something that's staring me in the face. Can anyone help?
Basically, I have a simple each loop that's returning an extra rogue line. Even when there's nothing in the db, I get one line returned!
My show view including the loop is:
<p id="notice"><%= notice %></p>
<p>
<b>Header:</b>
<%= #mailer.header %>
</p>
<p>
<b>Subtext:</b>
<%= #mailer.subtext %>
</p>
<div id="" class="" padding-left: 30px;>
<h3>Mailer Products </h3>
<ol id="mailer-Product-list">
<% #mailer.mailer_products.sort_by { |mailer_products| mailer_products.position }.each do |mailer_product| %>
<%= content_tag_for :li, mailer_product do %>
<%= mailer_product.product.cat_no %>
<% end %>
<% end %>
</ol>
<%#= link_to 'Done', #product, :class => "standard-button" %>
</div>
<%= form_for([#mailer,#mailer.mailer_products.build]) do |f| %>
<div class="field">
<%= f.label :product_id %><br />
<%= f.text_field :product_id %>
</div>
<div class="field">
<%= f.hidden_field :mailer_id, :value => #mailer.id %>
</div>
<div class="actions">
<%= f.submit "Add Product" %>
</div>
<% end %>
<%= link_to 'Edit', edit_mailer_path(#mailer) %> |
<%= link_to 'Back', mailers_path %>
The controller code is:
class MailersController < ApplicationController
def show
#mailer = Mailer.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #mailer }
end
end
class MailerProductsController < ApplicationController
def index
#mailer_products = MailerProduct.find(:all)
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #mailer_products }
end
end
end
end
Your call to form_for looks like this
form_for([#mailer,#mailer.mailer_products.build]) do |f|
You get an extra blank item because that's what calling .build on mailer_products does: it appends a new instance to the array
When the form is after the loop this doesn't matter, but when things are the other way around the loop will be on the modified array
My usual mistake is adding a <%= instead of a <% on the loop...
<%= #foo.each do |itme| %>
# do stuff
<% end %>
which should be
<% #foo.each do |itme| %>
# do stuff
<% end %>
Double check your tags...

Resources