carrierwave AJAX upload with remotipart - ruby-on-rails

In my rails4 I would like to submit a form via AJAX that has a file uploaded via carrierwave. As far as I know it can be done via remotipart, but can't figure it out how I can do that. (Remotipart installed properly since it's working with refile gem that I also use in the app.)
With the current code below the form gets submitted according to the logs and it says the create.js.erb is rendered, but the code in the create.js.erb file never runs.
Rendered posts/create.js.erb (387.0ms)
What should I do?
form
<%= form_for #post, remote: true, method: :post, :html => { :multipart => true, class: "post-create-form" } do |f| %>
<img id="img_prev" style="margin-bottom:10px;" width=300 height=200 src="#" class="img-thumbnail hidden"/>
<%= f.text_area :body, placeholder: "Share something useful..", class: "form-control post-create-body" %>
<%= f.button "SHARE", class: "btn btn-primary btn-sm btn-create-post", data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %>
<span class="btn btn-success btn-sm btn-message-file">Upload Image
<%= f.file_field :post_image, class: "choose-message-file", id: "avatar-upload" %>
</span>
<%= f.hidden_field :post_image_cache %>
<% end %>
create.js.erb
$('ul.errors').hide();
$('.alert-danger').hide();
$('.post-index').prepend('<%= j render #post %>');
$('.post-create-body').val('');
$('.btn-create-post').prop('disabled',true);
_post.html.erb
<div class="col-md-2">
<%= link_to user_path(post.user) do %>
<%= image_tag post.user.avatar.url(:base_thumb), class: 'post-avatar' %>
<% end %>
</div>
<div class="col-md-8">
<div class="post-info">
<%= link_to user_path(post.user) do %>
<span class="post-user-name"><%= post.user.full_name %></span>
<% end %>
<span class="post-updated"><%= local_time_ago(post.updated_at) %></span>
</div>
<div class="post-body">
<%= simple_format(find_links(h post.body)) %>
</div>
<div class="post-image" data-postlink="<%= post_path(post) %>">
<% if post.post_image? %>
<button data-toggle="modal" data-target="#post-image-modal">
<%= image_tag post.post_image.url(:base_thumb) %>
</button>
<% end %>
</div>
</div>
UPDATE:
The problem is connected to updating the post object. The update form code can be found in the _post.html.erb, so that's why <%= j render #post %> didn't work. Still don't know what the problem is.
So what works:
1. creating post that has no image
2. updating post that has no image
3. updating post that has image BUT image is not edited
Not working:
1. creating post that has image
2. updating post that has image which is edited
<%= form_for post, method: :patch, remote: true, :html => { :multipart => true } do |f| %>
<div class="modal fade updatepost" id="updatepost_<%= post.id %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content" style="text-align:left">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="edittaskmodalohhhhh">Edit Task</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger" style="display:none">
<ul class="errors" style="display:none">
<%= render 'layouts/error_messages', object: f.object %>
</ul>
</div>
<div class="field form-group">
<%= f.file_field :post_image, id: "avatar-upload-update" %>
<%= f.hidden_field :post_image_cache %>
</div>
<div class="field form-group">
<%= f.text_area :body, class: "form-control edit-post-body" %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" id="updatepostclose">Close</button>
<%= f.button "Update post", class: 'btn btn-primary edit-post-submit', data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %>
</div>
</div>
</div>
</div>
<% end %>
update.js.erb
$("ul.errors").html("");
<% if #post.errors.any? %>
$('.alert-danger').show();
$('ul.errors').show();
<% #post.errors.full_messages.each do |message| %>
$("ul.errors").append($("<li />").html("<%= message.html_safe %>"));
<% end %>
<% else %>
$('ul.errors').hide();
$('.alert-danger').hide();
$('#updatepost_<%= #post.id %>').modal('hide');
$post = $('<%= j render #post %>');
editPostHideDanger($post);
$('#post_<%= #post.id %>').remove();
$(".new-post-insert").prepend($post);
$("html, body").animate({ scrollTop: 0 }, "slow");
<% end %>

There was some issue (still don't know what) with the bootstrap modals. I changed the structure of the modals and now it's working fine.

Related

Nil:nil class error on each loop when Form to build object loaded on page first

I have a form on a page that is building a “tip” for a “guide”. Below the form, I am running an each loop over all the #guide.tips. I keep getting an error as the each loop is loading the forms blank object as it sees it as a tip. I’ve currently solved the problem by using jQuery to inject the form after page load, but there has to be a better solution.
Each Loop on Guide.html.erb
<% if !#guide.tips.blank? %>
<% #guide.tips.each do |tip| %>
<div class="row mx-1">
<div class="col-md-3 border-right">
<div class="float-left">
<%= image_tag avatar_url(tip.user), class: "float-left text-left align-middle rounded img-fluid mx-3", width: "30%" %>
<p><%= tip.user.fullname %></p>
</div>
<div class="float-right mr-3">
<%= link_to like_tip_path(tip), method: :put do %>
<div class="fas fa-angle-up"></div>
<%= tip.get_upvotes.size %>
<% end %><br/>
<%= link_to dislike_tip_path(tip), method: :put do %>
<div class="fas fa-angle-down"></div>
<%= tip.get_downvotes.size %>
<% end %>
</div>
</div>
<div class="col-md-8 ml-3">
<h6><%= tip.title %> -<span class="ml-1"><small><%= tip.created_at.strftime("%A, %d %b %Y %l:%M %p")%></small></span></h6>
<%= tip.tip %>
</div>
</div><hr/>
<% end %>
<% end %>
Tips_Controller.rb
def new
#guide = Guide.find(params[:guide_id])
#tip = Tip.new
end
def edit
end
def create
#guide = Guide.find(params[:guide_id])
params[:tip][:user_id] = current_user.id
#tip = #guide.tips.create!(tip_params)
redirect_to guide_path(#guide)
end
Tip Form Partial
<%= form_for([#guide, #guide.tips.build]) do |f| %>
<div class="form-group row">
<div class="col-sm-12">
<p class="text-left">Tip Title</p>
<%= f.text_field :title, placeholder: "Enter Title", class: "form-control" %>
</div>
<div class="col-sm-12 mt-2">
<p class="text-left">Your Tip</p>
<%= f.text_area :tip, placeholder:"What's your tip for this travel guide?", class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<div class="col-md">
<%= f.submit 'Submit', class: 'btn btn-primary btn-block' %>
</div>
</div>
<% end %>
Here is another solution that does not separate the logic between the controller and the view and cleans up your empty array statement for your loop
Each Loop on Guide.html.erb
<% #guide.tips.each do |tip| %>
<div class="row mx-1">
<div class="col-md-3 border-right">
<div class="float-left">
<%= image_tag avatar_url(tip.user), class: "float-left text-left align-middle rounded img-fluid mx-3", width: "30%" %>
<p><%= tip.user.fullname %></p>
</div>
<div class="float-right mr-3">
<%= link_to like_tip_path(tip), method: :put do %>
<div class="fas fa-angle-up"></div>
<%= tip.get_upvotes.size %>
<% end %><br/>
<%= link_to dislike_tip_path(tip), method: :put do %>
<div class="fas fa-angle-down"></div>
<%= tip.get_downvotes.size %>
<% end %>
</div>
</div>
<div class="col-md-8 ml-3">
<h6><%= tip.title %> -<span class="ml-1"><small><%= tip.created_at.strftime("%A, %d %b %Y %l:%M %p")%></small></span></h6>
<%= tip.tip %>
</div>
</div><hr/>
<% end unless #guide.tips.blank? %>
Tip Form Partial
By creating the Tip from outside the association (i.e. not using build), it will not be loaded into the class variable's children
<%= form_for([#guide, Tip.new(guide: #guide)]) do |f| %>
<div class="form-group row">
<div class="col-sm-12">
<p class="text-left">Tip Title</p>
<%= f.text_field :title, placeholder: "Enter Title", class: "form-control" %>
</div>
<div class="col-sm-12 mt-2">
<p class="text-left">Your Tip</p>
<%= f.text_area :tip, placeholder:"What's your tip for this travel guide?", class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<div class="col-md">
<%= f.submit 'Submit', class: 'btn btn-primary btn-block' %>
</div>
</div>
<% end %>
Another Example / Q&A
Using the structure you already have you could do:
<% if #guide.tips.count > 1 %> (assuming this will always be shown with an empty "build" tip)
or you can use:
<% next unless tip.persisted? %>
inside the loop, before the actual form.
You also don't need the blank? check as an .each on an empty enumerator simply won't execute the block, and as long as there's a has_many relationship between guide and tips it will always yield a collection proxy.
I would write it as:
<% #guide.tips.each do |tip| %>
<% next unless tip.persisted? %>
<div class="row mx-1">
<div class="col-md-3 border-right">
...
<% end %>

Problems with Modal in Rails opening the same object

I'm maintaining an older Rails 3.2.22 app and I'm trying to add a modal to pop up with a simple form to add a note.
Here is my view (cut down for readability)
<% #assigned.each do |call| %>
<%= link_to "Notes", '#ajax-modal', data: { toggle: "modal", target: "#note-modal" }, class: 'btn btn-small btn-inverse' %>
<%= render 'layouts/note_modal', :call => call %>
<% end %>
Here is my modal app/views/layouts/_note_modal.html.erb
<div id="note-modal" class="modal hide fade" tabindex="-1">
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title"><%= call.incident_number %> Notes</h3>
</div>
<div class='modal-body'>
<div class="modal-body-content">
<%= form_for(#note, url: call_note_calls_path, html: {class: "form-inline"}) do |f| %>
<%= f.text_field :message, :maxlength => 255 %>
<%= f.hidden_field :call_id, value: call.id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.button "Add Note", class: 'btn btn-info btn-small', data: {disable_with: "<i class='icon-spinner'></i>Posting..."} %>
<% end %></div>
<div class="ajax-loader">
</div>
</div>
<div class='modal-footer'>
<button type="button" data-dismiss="modal" class="btn">Close</button>
</div>
</div>
When I load the page and there are several calls I click on the notes link, the partial renders in a modal and I can submit a note. The problem is if I have 10 calls on the screen no matter which notes link I click on it adds a note to the first call on the screen.
Am I passing locals incorrectly? I know this code is inside of the block so it should pull the call object and pass it as a local to the partial in the modal but it's not.
Any help is greatly appreciated.
I think the issue is that you render the modal each time for a note but they all have the same id. So you are always opening the first modal. Actually IMHO you just need to render the modal once and pass the note_id via an data attribute on the link which triggers the modal. So basically configure the modal via the caller.
I was able to figure this out on my own and still render the partial within the loop by calling an index as part of the target ID for the modal. Working code below.
<% #assigned.each_with_index do |call, index| %>
<%= link_to "Notes", '#note-modal', data: {toggle: "modal", target: "#note-modal#{index}" }, class: 'btn btn-small btn-inverse' %>
<%= render 'layouts/note_modal', call: call, index: index %>
<% end %>
<div id="note-modal<%= index %>" class="modal hide fade" tabindex="-1">
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title"><%= call.incident_number %> Notes</h3>
</div>
<div class='modal-body'>
<div class="modal-body-content">
<%= form_for(#note, url: call_note_calls_path, html: {class: "form-inline"}) do |f| %>
<%= f.text_field :message, :maxlength => 255 %>
<%= f.hidden_field :call_id, value: call.id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.button "Add Note", class: 'btn btn-info btn-small', data: {disable_with: "<i class='icon-spinner'></i>Posting..."} %>
<% end %></div>
<% call.notes.each do |n| %>
<li><%= n.message %> added by <%= n.user.username %></li>
<% end %>
<div class="ajax-loader">
</div>
</div>
<div class='modal-footer'>
<button type="button" data-dismiss="modal" class="btn">Close</button>
</div>
</div>

bootstrap grid system not formatting correctly without commenting out a class='col-md-6'

I would like to have user who have not created a profile to be directed to a page that instructs them to do so.
If user has not created a profile, I would like the bootstrap well to go across the page. I can only get it to work by commenting out line 7 (or the first: div class="col-md-6") , which messes up the interface if user has created a profile.
<div class="jumbotron text-center">
<h1>Welcome to Jr. Dev Mentoring</h1>
<h3>Harnessing the Power of Mentorship <br>To Build A Community of Work Ready Jr. Devs.</h3>
</div>
<div class="row">
<% if user_signed_in? %>
<div class="col-md-6">
<div class="well">
<h2 class="text-center">Your Profile</h2>
<% if current_user.profile %>
<%= link_to "Edit your profile", "#", class: 'btn btn-default btn-lg btn-block' %>
<%= link_to "View your profile", user_path(current_user), class: 'btn btn-default btn-lg btn-block' %>
</div>
</div>
<div class="col-md-6">
<% if current_user.plan.name == "mentor" %>
<%= render partial: "pages/mentor" %>
<% else %>
<%= render partial: "pages/mentee" %>
<% end %>
</div>
<% else %>
<div class='container'>
<div class='row'>
<div class='col-md-8 col-md-offset-2'>
<p class='text-center'>Create your profile so that you can share your information with the Jr. Dev Mentoring community.</p>
<%= link_to "Create your profile", new_user_profile_path(current_user), class: 'btn btn-default btn-lg btn-block'%>
</div>
</div>
</div>
<% end %>
<% else %>
<div class="col-md-6">
<div class="well">
<h2 class="text-center">Mentee</h2>
<h4 class="text-center">Sign up for free to gain access to our community of mentors.</h4>
<br/>
<%= link_to "Sign Up", new_user_registration_path(plan: #mentee_plan.id), class: 'btn btn-primary btn-lg btn-block' %>
</div>
</div>
<div class="col-md-6">
<div class="well">
<h2 class="text-center">Mentor</h2>
<h4 class="text-center">Sign up for free to lend your expertise and support!</h4><br>
<%= link_to "Sign Up", new_user_registration_path(plan: #mentor_plan.id), class: 'btn btn-success btn-lg btn-block' %>
</div>
</div>
<% end %>
</div>
Here you are: You had a slight mis-arrangement around line 7, :).
<div class="jumbotron text-center">
<h1>Welcome to Jr. Dev Mentoring</h1>
<h3>Harnessing the Power of Mentorship <br>To Build A Community of Work Ready Jr. Devs.</h3>
</div>
<div class="row">
<% if user_signed_in? %>
<% if current_user.profile %>
<div class="col-md-6">
<div class="well">
<h2 class="text-center">Your Profile</h2>
<%= link_to "Edit your profile", "#", class: 'btn btn-default btn-lg btn-block' %>
<%= link_to "View your profile", user_path(current_user), class: 'btn btn-default btn-lg btn-block' %>
</div>
</div>
<div class="col-md-6">
<% if current_user.plan.name == "mentor" %>
<%= render partial: "pages/mentor" %>
<% else %>
<%= render partial: "pages/mentee" %>
<% end %>
</div>
<% else %>
<div class='container'>
<div class='row'>
<div class='col-md-8 col-md-offset-2'>
<p class='text-center'>Create your profile so that you can share your information with the Jr. Dev Mentoring community.</p>
<%= link_to "Create your profile", new_user_profile_path(current_user), class: 'btn btn-default btn-lg btn-block'%>
</div>
</div>
</div>
<% end %>
<% else %>
<div class="col-md-6">
<div class="well">
<h2 class="text-center">Mentee</h2>
<h4 class="text-center">Sign up for free to gain access to our community of mentors.</h4>
<br/>
<%= link_to "Sign Up", new_user_registration_path(plan: #mentee_plan.id), class: 'btn btn-primary btn-lg btn-block' %>
</div>
</div>
<div class="col-md-6">
<div class="well">
<h2 class="text-center">Mentor</h2>
<h4 class="text-center">Sign up for free to lend your expertise and support!</h4><br>
<%= link_to "Sign Up", new_user_registration_path(plan: #mentor_plan.id), class: 'btn btn-success btn-lg btn-block' %>
</div>
</div>
<% end %>
</div>

how to refresh a partial after an edit has been made in rails

I am making an ecommerce website page.It consists of two parts.A sidebar having a list of all products and a right column where the details of the product is shown once the product is selected from the list.
I am making ajax calls to load the various partials of the application. The sidebar having all the products is index,the one on right having the details of products is show which shows the details of the product selected.
Now when I edit the product(through a modal) how do I automatically reload the respective partials so that the new changes are reflecte.For me to see the changes I have to refresh the pages currently,how do i ensure the partials are automatically loaded once I click submit on the edit modal.
My index.html.erb looks like
<div class="container">
<div class="row row-offcanvas row-offcanvas-left">
<div class="col-xs-8 col-sm-4 sidebar-offcanvas" id="sidebar" role="navigation">
<div class="well sidebar-nav">
<ul class="nav">
<div class="jumbotron well">
<h3>Product Listing Application</h3>
</div>
<%= link_to "New Product", new_product_path, remote: true, class: "btn btn-primary" %>
<div class="list-group">
<%= render "index" %>
</div>
</ul>
</div><!--/.well -->
</div><!--/span-->
<div class="col-xs-10 col-sm-8">
<div id="page-content-wrapper">
<div class="page-content">
<div class="col-md-12 product-info" id="product-details">
</div>
</div>
</div>
<div id="product-modal" class="modal fade"></div>
</div>
</div><!--/row-->
</div>
My _index.html.erb is
<% #products.each do |product| %>
<%= link_to product_path(product), remote: true, class: "list-group-item" do %>
<h4 class="list-group-item-heading"><%= product.name %></h4>
<p class="list-group-item-text"><%= number_to_currency product.price %></p>
<% end %>
<% end %>
My _edit.html.erb is
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3><%= "Editing #{#product.name}" %></h3>
</div>
<%= render "form" %>
</div>
</div>
My _form.html.erb is
<%= form_for #product, remote: true, html: { class: "form-horizontal", style: "display:inline;" } do |f| %>
<div class="modal-body">
<ul class="errors"></ul>
<div class="control-group">
<%= f.label :name, class:"control-label" %>
<div class="controls">
<%= f.text_field :name %>
</div>
</div>
<div class="control-group">
<%= f.label :price, class: "control-label" %>
<div class="controls">
<%= f.text_field :price %>
</div>
</div>
</div>
<div class="modal-footer">
<%= f.submit class: "btn btn-primary" %>
<%= link_to "Cancel", "#", class: "btn", data: {dismiss: "modal"} %>
</div>
<% end %>
You can use
location.reload();
on your js.erb for refresh your partial, or for your instance vaiable
you can directly use
#post = #post.reload # in palce of #post you can your instance variable
create a js file same name as your page
add below code in it
edit.js.erb
$("<%= escape_javascript render(:partial => 'ur_partial_page_name') %>").dialog();
$('#new_comment_link').hide();`
in your edit page form where u r calling modal dialog
<%= link_to "edit", edit_product_path (#product, :format => :js), :remote => true %>
In your product controller
def edit
#source = Product.find(params[:id])
respond_to do |format|
format.html # edit.html.erb
format.xml { render :xml => #product }
format.js
end
end
and in your partial form
<%= form_for (#product, :remote => true) do |f| %>

Rails Form in Bootstrap Modal

I'm trying to put a rails form in a bootstrap modal dialog. I'd like to use the modal-footer to hold the cancel/submit buttons, but this doesn't seem to work inside the form tag.
<div class="modal-body">
<%= simple_form_for [#state, #search] do |f| %>
<!-- long form here -->
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<%= f.button :submit, :class => 'btn btn-primary' %>
</div>
<% end %>
</div>
That's because you are putting the footer inside the body. Use this way instead:
<%= simple_form_for [#state, #search] do |f| %>
<div class="modal-body">
<!-- long form here -->
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<%= f.button :submit, :class => 'btn btn-primary' %>
</div>
<% end %>

Resources