Poltergeist and phantom render partial with respond_to in controller - ruby-on-rails

I have a problem executing my rails app feature files headless. I use phantom as webkit and poltergeist as javascript driver.
My feature starts like this:
#javascript
Scenario: Create a customer
Given I am on the "/customers" page
When I click on element having id "new_customer"
Then I should see "Customer data"
The message I get running it is:
Then I should see "Customer data"
features/step_definitions/feature_steps.rb:16
expected to find text "Customer data" in "LOGOTIMAX :: adminTicketsProjectsCustomersUsermanagementProfileSettingsLog out Listing Customers Show entriesSearch: Id Name 1 Heine 2 IKEA 3 Coca Cola 4 Lufthansa AG 5 Daimler AGShowing 1 to 5 of 5 entriesPrevious1Next New Customer TIMAX - Ruby on Rails application by UniCorp BLOGJIRA" (RSpec::Expectations::ExpectationNotMetError)
It seems as if the partial where the text "Customer data" should be displayed does not get rendered by phantom. When I do the same by hand in my browser, it works.
Here are the other corresponding files:
customers/index.html.erb:
<h1>Listing Customers</h1>
<div class="grid">
<div class="row cells3 ">
<div class="cell" id="customers_list">
<%= render partial: 'customers/list', locals: { customers: #customers } %>
</div>
<div class="cell colspan2 " id="current_customer"></div>
</div>
</div>
<br>
<%= link_to 'New Customer', new_customer_path, class: "button", id: "new_customer", remote: true %>
customers_controller.rb (new)
def new
respond_to do |format|
format.js {render layout: false}
end
end
customers/new.html.erb
<h1>New Customer</h1>
<p>Customer data</p>
<%= render 'form' %>
customers/new.js.erb
$("#current_customer").html("<%= escape_javascript(render partial: 'customers/new' ) %>");

Related

rails turbo frame load new pages instead of showing " Response has no matching" error

i am on rails 7 trying out the turbo frame.
supposedly my code should fire a Response has no matching error because i do not have the similar id in the new page after clicking the new link. however it just loads the new page as usual, contradict with a tutorial. any idea how do i get the error logged instead of loading a new page? thanks.
# app/views/quotes/index.html.erb
<main class="container">
<%= turbo_frame_tag "first_turbo_frame" do %>
<div class="header">
<h1>Quotes</h1>
<%= link_to "New quote", new_quote_path, class: "btn btn--primary" %>
</div>
<% end %>
<%= render #quotes %>
</main>
# app/views/quotes/new.html.erb
<h1>New quote</h1>
<%= render "form", quote: #quote %>

Javascript don't substitute html in rails + Ajax

Still learning how to use Ajax in Rails.
I have a simple controller:
class PagineController < ApplicationController
def cerca
end
def trova
respond_to do |format|
format.js {render layout: false }
end
end
end
routes.rb:
get '/cerca', to: 'pagine#cerca'
post '/cerca', to: 'pagine#trova'
This is trova.js.erb:
$('#search_table').html("<%= escape_javascript(render partial: 'search_result') %>");
This is cerca.html.erb:
<%= form_tag '/cerca', remote: true do %>
<%= text_field_tag :name, params[:name], placeholder: 'Inserisci parte
del nome del gioco' %>
<%= submit_tag 'Cerca' %>
<% end %>
<h1> Results </h1>
<div id="search_table">
<p>Here the partial</p>
</div>
and this is the _search_result.html.erb
<p> I'm running well </p>
I'm expecting that, when i submit a search with the button, "Here the partial" will be substituted with "I'm running well".
But this is not happens.
In the log i see that _search_result.html.erb is correctly rendered, so all should run.
Why don't?
Ok. I've resolved (for future references if someone needs), using different js:
document.getElementById("search_table").innerHTML = "<%= j render 'search_result' %>"

rails: redirect_to rendering but not reloading new page

I would like my application to show a list of all associated objects when one is updated, so I would like to load the index action after an update is completed.
I have tried formatting the block, removing the format, render, and redirect_to. All of them just remain on the edit page
Update action:
def update
respond_to do |format|
if #business_category.update_attributes(business_category_params)
format.html {redirect_to admin_business_categories_path}
return
end
end
end
edit view:
<div class="container">
<div class="row">
<div class="col-xs-12">
<%= link_to 'Back to categories', admin_business_categories_path %>
</div><!-- .col -->
<%= simple_form_for(#business_category, url: admin_business_category_path(#business_category), remote: true, html: { class: '' }) do |f| %>
<%= render 'form', f: f %>
<% end %>
</div><!-- .row -->
</div><!-- .container -->
_form partial:
<div class="col-xs-12 col-sm-10 col-md-10">
<%= f.input :name, label: 'Category Name' %>
</div>
<div class="col-xs-12 col-sm-2 col-md-2">
<div class="btn-group-vertical" role="group" aria-label="...">
<button id="businessCategoryCancelButton" class="btn btn-warning">CANCEL</button>
<%= f.submit 'SAVE', class: 'btn btn-success' %>
<br>
</div>
</div>
at the redirect_to a message appears in the console:
No template found for Admin::BusinessCategoriesController#update, rendering head :no_content
Completed 204 No Content in 1505ms (ActiveRecord: 1.0ms)
I don't know why it is looking for the update template or why it is not redirecting to the index action
I am trying to understand how format works and if/why it would be conflicting with the redirect. Any advice would be helpful
Because you are issuing an AJAX call (remote: true on your form).
You have the following options:
Add format.js to the controller
Remove remote: true from the form definition and the respond_to from the controller:
def update
if #business_category.update_attributes(business_category_params)
redirect_to admin_business_categories_path
else
render :edit
end
end
simple_form_for(#business_category, url: admin_business_category_path(#business_category), remote: true, html: { class: '' })
In your form you've mentioned remote: true. It process your request as a JS request. In your controller you've mentioned format.html {redirect_to admin_business_categories_path} but it will process it as format.js and look for update.js.erb file to handle the response because your format of request is 'JS' instead of 'HTML', hence it's showing an error.
You'll have to send the request as an HTML request.
According to your implementation. I think you just want to redirect in case of success and render edit page again in case of error.
You'll have to make 2 changes.
Remove remote: true from form as it doesn't match your requirement
Add the line format.html { render :edit } in else case of update_attributes()

Rails partial not refreshing with create action

I realize there are dozens of similar questions here on this topic, I have looked through many of them and tried to duplicate the solutions and nothing has worked for me.
I have a list of tasks displayed in the index view as a partial, when the user adds a task I would like list to show the newest task (as well as all the others already there).
Here is the create controller:
def create
#task = current_user.tasks.build(task_params)
if #task.save
flash[:success] = "Task added"
respond_to do |format|
format.js
end
else
flash[:error] = "Task not added"
render 'new'
end
The _new partial:
<%= form_for(#task, method: :post, remote: true) do |f| %>
<%= f.label :comments %>
<%= f.text_field :comments, id: "task-comments" %>
<%= f.submit "Insert" %>
<% end %>
Index.html.erb
<div id="new-task-form">
<%= render 'new' %>
</div>
<div id="current-tasks">
<%= render partial: 'show_list', locals: {tasks: #tasks} %>
</div>
create.js.erb
console.log("create.js.erb called");
document.getElementById("task-comments").value = "";
document.getElementById("current-tasks").html('<%= j(render partial: "show_list") %>');
I have been able to get the console to log the message and even been able to clear the input box but the partial does not render, I have tried this in a few different ways and the script always seems to stop executing when it gets to the escape javascript line.
There are no JS errors, as stated above, the console logs the message when the "submit" button is pressed. There is a warning [Violation] Forced reflow while executing JavaScript took 114ms but I don't think that is relevant to this issue.
Here is the partial that I am trying to render _show_list.html.erb
<% unless #tasks.nil? %>
<ul>
<% tasks.each do |tsk| %>
<li><%= tsk.comments %></li>
<% end %>
</ul>
<% end %>
def create
#task = current_user.tasks.build(task_params)
if #task.save
flash[:success] = "Task added"
#respond_to do |format|
#format.js
#end
else
flash[:error] = "Task not added"
render 'new'
end
end
It's always good practice to use local variable in partial
1) => Index.html.erb
<div id="new-task-form">
<%= render 'new' %>
</div>
<div id="current-tasks">
<%= render partial: 'show_list', locals: {tasks: #tasks} %>
</div>
2) => If you are using jquery (create.js.erb)
console.log("create.js.erb called");
$("#task-comments").val('');
$("#current-tasks").html('<%= j render "show_list", tasks: #tasks) %>');
3) => _show_list.html.erb(Use tasks instead of #tasks)
<% unless tasks.blank? %>
<ul>
<% tasks.each do |tsk| %>
<li><%= tsk.comments %></li>
<% end %>
</ul>
<% end %>
ok you have some problem here with your validation on the show_list partial.
you have this line
<% unless #tasks.nil? %>
try to use something more readable like
<% if #tasks.present? %>
and on your controller create action, you don't fill the #tasks variable, so that's the problem in reality, add on you controller the load for all the tasks after saving the new one.
if #task.save
#tasks = Task.all
flash[:success] = "Task added"
and that will make it work, but I recommend to load just the created one and add just one column to the table and not update the complete list again if you have all the others on the client already.

Ruby on Rails: Deleting a post with Ajax in navigation and showing the following

Thanks for reading!
So I'm relatively new to RoR (Rails 5) and I try to render posts of a user in a partial (_posts_panel.html.erb) which contains another partial: the navigation (_posts_navigation.html.erb). I'm using ajax to show the posts when clicked on in the navigation which is working fine.
Now I want to use it for deleting a post. The post is destroyed when I click on the button and I managed to remove it in navigation.
What is not working:
the next post should be shown in the panel after the deletion
when there is no post left I want to reload the panel because another partial (_posts_empty.html.erb) should be rendered
My Code:
_posts_panel.html.erb: (it is rendered in show.html.erb of user)
<% if #user.simple_posts.empty? %>
<%= render 'simple_posts/shared/posts_empty' %>
<% else %>
<div id="post-navigation">
<%= render 'simple_posts/shared/posts_navigation' %>
</div>
<%= simple_posts_edit_button(current_user, #simple_post)%>
<%= simple_posts_delete_button(current_user, #simple_post)%> #button helper
<div id="show_post">
<%= render #simple_post %>
<%= yield %>
</div>
<%end %>
_posts_navigation.html.erb
<div class="bootstrap-vertical-nav">
<ul class="nav flex-column">
<% #user.simple_posts.reverse_each do |post|%>
<li class="nav-item" id="<%= #simple_post.id %>">
<%= link_to post.title, user_simple_post_path(#user, post), remote: true, class:"nav-link text-dark" %>
</li>
<% end %>
</ul>
</div>
<% if #user.id == current_user.id %>
<%= link_to "+ New Post", new_user_simple_post_path(current_user), class: "btn btn-info w-100", role: "button" %>
<% end %>
destroy.js.erb
$('li#<%= #simple_post.id %>').remove();
simple_posts_controller.rb
def destroy
#simple_post.destroy
#simple_post =current_user.simple_posts.first
respond_to do |format|
# format.html { redirect_to simple_posts_url, notice: 'Simple post was successfully destroyed.' }
format.js
end
end
I tried to append in destroy.js.erb the same code from showing the post $('#show_post').html("<%= escape_javascript render #simple_post %>"); but it's not working correctly. When deleting the first post (but only that one) the next one is shown but the post is not removed from the navigation. I also tried $('#post-navigation').html("<%= escape_javascript render partial: 'simple_posts/shared/posts_navigation' %>"); and it nothing happens.
Also I tried to reload the whole panel with $('#post-panel').html("<%= escape_javascript render partial: 'simple_posts/shared/posts_panel' %>");in show.html.erb of user but again: nothing. I'm not sure if I have to specify in which view or partial exactly it has to render the partial.
I don't really know how to approach this further.
Edit 1
ButtonHelper.rb
def simple_posts_delete_button(current_user, simple_post)
if(current_user.id == #user.id)
link_to svg('x-square'), [current_user, simple_post], remote: true, method: :delete, class:"btn"
end
end
Edit 2
show-action from simple_posts_controller.rb
def show
#user = User.find{params[:id]}
#simple_post = SimplePost.find(params[:id])
respond_to do |format|
format.js
format.html # show.html.erb
end
end
show.js.erb
$('#post-actions').html("<%= j render partial: 'simple_posts/shared/posts_actions', locals: {simple_post: #simple_post, user: #user} %>");
$('#show-post').html("<%= j render #simple_post %>");
There are several problems with your partials:
First, to remove the post from your navigation you just need to update the partial, the post is already destroyed/removed at this point.
After destroy, #simple_post in your button helper is not updated with ajax and still comes from the users_controller (where you set it the first time i presume)
You can put your action buttons inside a new partial and specify the locals.
You can also wrap the html inside a main div for the last update (when all the posts are deleted)
_posts_panel.html.erb:
<div id="panel">
<% if #user.simple_posts.empty? %>
<%= render 'simple_posts/shared/posts_empty' %>
<% else %>
<div id="post-navigation">
<%= render partial: 'simple_posts/shared/posts_navigation', locals: { simple_post: #simple_post } %>
</div>
<div id="post-actions"> #<-- new partial
<%= render partial: 'simple_posts/shared/posts_actions', locals: { simple_post: #simple_post } %>
</div>
<div id="show_post">
<%= render #simple_post %>
<%= yield %>
</div>
<% end %>
</div>
_posts_actions.html.erb:
<%= simple_posts_edit_button(current_user, simple_post)%>
<%= simple_posts_delete_button(current_user, simple_post)%>
Note that you are not using the instance variable #simple_post anymore but the local one.
Now you can write your js like this:
destroy.js.erb:
<% if #simple_post %> //<-- check if "#simple_post = current_user.posts.first" still exists after destroy
$('#post-navigation').html("<%= j render partial: 'simple_posts/shared/posts_navigation', locals: { simple_post: #simple_post } %>");
$('#post-actions').html("<%= j render partial: 'simple_posts/shared/posts_actions', locals: { simple_post: #simple_post } %>");
$('#show_post').html("<%= j render #simple_post %>");
<% else %>
$('#panel').html("<%= j render partial: 'simple_posts/shared/posts_empty' %>");
<% end %>

Resources