Rails partial renders in console network response but not in view - ruby-on-rails

I am trying to have my partial display search results in a rails view. When I check my console > network > preview, I see my partial rendered with the data I need but it doesn't display in my view.
Here's my app/controllers/searchs_controller.rb
def nearby_guides
#address = params[:address]
initial_array = #address.split(',')
city = initial_array[0]
state = initial_array[1].split(' ')
final_state = state[0]
country = initial_array[2]
#result = User.where("city = ?", city)
respond_to do |format|
format.html {render :partial => '/searchs/result', object: #result}
end
end
Here's my views/searchs/_result.html.erb
<h1>HELLO WORLD</h1>
<% if #result %>
<% #result.each do |r| %>
<p><%= r.firstname %></p>
<% end %>
<% end %>
Then in my views/searchs/new.html.erb
<%= render 'result' %>
This is the response I see in my console > network > preview
HELLO WORLD
Kevin
Which is exactly the response I expected but again, it doesn't display in the view. I've looked over stack overflow with no luck. Thanks so much for any and all help!

I think that this is your issue: format.html {render :partial =>
When you are rendering the result of an action as html - it needs to be a whole view, not just a partial.
Rendering partials is generally reserved for AJAX queries - where you need only part of the page and your javascript will insert it into the page in the right place. so either you need javascript, or you need to do something like: render :new

Related

Clarity on response formats and page reload for html response in Rails

I would like to understand the response format actions in Rails. Suppose I have a link_to in my partial which is rendered in show page like below:
show.html.erb
<%= render partial: 'my_partial', locals: { stage: #stage } %>
my_partial.html.erb
<% case 'stage' %>
<% when 'beginning' %>
<%= link_to 'Submit', { controller: 'my_controller', action: 'update_model' } %>
<% when 'ongoing' %>
<%= render partial: 'another_partial' %>
<% end %>
my_controller.rb
def update_model
#do something
respond_to do |format|
format.json { render json: { some_key: some_value } }
format.js { render partial: 'path_to_partial/partial.js' }
format.html { redirect_to action: 'show' }
end
end
Here whenever show page is loaded for the first time #stage will be beginning and then on clicking link_to 'Submit' then before the response from controller the #stage will be changed to ongoing.
Now Whenever I click on link_to, the page reloads and the response is in html so format.html is sent. If I add remote: true then the response is in js and the page does not reload because it is remote.
So the exact functionality that I want is to re render the show page and then inside the my_partial it should go to when ongoing and then render the another_partial page without reloading. This happens in the same url.
What I am trying to understand is why does the page reload when it is the same url? Is that how format.html works? What should I do to render the show page again but without reloading the page?
What the respond_to do |format| does it looks which response the incoming http request is expecting.
Normally, if you click on a link or submit a form, it expects html. But, as you state correctly, if you add remote: true the http request issued by the link is expecting javascript.
Now you want to rerender only the partial, not the whole page. You can do it like so
in the controller
def update_model
...
respond_to do |format|
...
format.js
...
end
end
Don't give a block to format.js this will automatically render a file in the views which - like always - should be named like the controller action.
So update_model.js.erb
And here you can decide what to do.
So for example find the div that holds your partial and then rerender it. Thanks to .erb you can write embedded ruby code in this js file too. And this is where you decide which part to rerender or whatever to do (toggle classes,...)
const container = document.querySelector("#container-for-partial")
const partial = "<%= j render 'some_partial' %>"
// Inject HTML to partial
container.innerHTML = partial

removing specific content from a feed with ajax js.erb when a user is unfollowed

I have a follow form that is rendered in numerous areas of my app. There is a feed view, where content of followed users is shown. When a user is unfollowed I need that page to be updated to remove the content of the unfollowed user. So one solution would be to put all the feed content into a partial and render that partial after a relationship is destroyed through the destroy.js.erb ajax file that is triggered from the Relationships Controller.
UsersController
def feed
#user_feed_items = current_user.photo_feed.order('created_at desc').paginate(page: params[:page])
end
class User
def photo_feed
following_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
Photo.approved.where("user_id IN (#{following_ids})", user_id: id)
end
feed.html.erb
<%= render 'shared/feed' %>
end
_feed.html.erb
<% if #user_feed_items.any? %>
<% #user_feed_items.each do |feed| %>
<div class="feed-content">
<%= render partial: "users/usersforfeed", locals: { feed: feed } %>
</div>
<% end %>
<% end %>
Now the Relationships Controller looks like this:
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
All that is being passed to the relationships controller through the follow form are the user.id's of the followed and follower users.
So in destroy.js.erb:
$('.feed-content').html("<%= escape_javascript(render(partial: 'users/usersforfeed', locals: { feed: ???? ))
I cannot render the partial because I have nothing to match up with the feed variable??
I put a wrapper around each object and then simply removed it with javascript if the user is unfollowed. This is easier than rendering the feed again and nothing is gained in rendering the feed anew.

ActionView::Template::Error (undefined local variable or method...or no error

I wanted to use create action with ajax on 'index' page. I found some similiar problems here on SO, tried to use it, but no help for me so far. HTML works fine, only JS is a problem.
walls_controller:
def items
#item = Item.new
#items = current_user.items
find_items
#ads = #items_ads
end
def create
#items = current_user.items
find_items
##items_ads via find_items method
#ads = #items_ads
#item = current_user.items.build item_params
current_user.save
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end
items.html.erb:
<div id="items1">
<div class="row">
<div class="col-md-3">
<h3>Wall of user <%= current_user.name %></h3>
<div>
<%= render 'item_form', item: #item %>
</div>
Currently you are looking for these items:
<div>
<%= render 'items_list', items: #items %>
</div>
</div>
<div>
<%= render 'ads/ads_list', ads: #ads %>
</div>
</div>
</div>
_item_form.html.erb:
<%= form_for(item, url: wall_items_path, remote: true) do |f| %>
...
First I had error:
ActionView::Template::Error (undefined local variable or method `items' for #<#<Class:...
then I changed create.js.erb from
$("#items1").html("<%= render 'items_list', locals: {items: #items} %>");
$("#items1").html("<%= render 'ads_list', locals: {ads: #ads} %> ");
to
$("#items1").html("<%= render 'items_list', items: #items %>");
$("#items1").html("<%= render 'ads/ads_list', ads: #ads %>");
and now it doesn't show me any error, but no visible change when trying JS on browser. Thanks for help.
Rendering Partials
You can render a partial with local data in two ways:
Option 1
The shortcut version
<%= render "my_partial", local_var_1: some_var, local_var_2: another_var %>
The shortcut version takes the partial name as the first argument and a hash of local variables as the second parameter.
Option 2
The long form version
This form takes only a single argument in the form of a Hash with all the options.
Don't mix-and-match forms
Doing the following will yield unexpected results
<%= render "my_partial", locals: { local_var_1: some_var, local_var_2: another_var } %>
Technically here you are using the shortcut version (Option 1), rendering a partial named "my_partial" with a single local variable called locals.
You would expect to be able to use local_var_1 and local_var_2 within the partial, however you actually only get a single local variable called locals.
Rendering Partials in an SJR template
escape_javascript GOTCHA
In a server-generated JavaScript template (SJR), you must remember to use escape_javascript whenever you are rendering content which contains HTML.
$("#my-selector").html("<%= escape_javascript render('my_partial') %>");
Regardless of how you choose to render the partial (i.e. either Option 1 or Option 2 above), you must remember to wrap it in an escape_javascript (or its alias j) call.
Helpful Resources
Working With JavaScript in Rails
When to Use escape_javascript in an SJR Template

Rails render partial from controller

I'm trying to render different partials into my index view from the controller, depending on the params I receive.
I have a simple unless-else condition inside my controller that checks the params
def index
unless params[:check].nil?
render :partial => /layout/check
else
render :partial => /layout/not_check
end
end
And I have the files _check.html.erb and not_check.html.erb into the folder layout/
Now, how can I show that partials inside my index view?
At the moment I can just visualize the partial alone as a single view, but not inside the requested view.
The better way would be to call the partials from index.html.erb
<% unless params[:check].nil? %>
<%= render :partial => '/layout/check' %>
<% else %>
<%= render :partial => '/layout/not_check' %>
<% end %>
so your def index would look like this
def index
respond_to do |format|
format.html
end
end
I did not understand what you are trying to do but partial which are related to controller/actions should not be in layout unless they are serving some layout.
If you're trying to render a layout (and not actual view information) try using render layout
def index
if params[:check].nil?
render layout: "not_check"
else
render layout: "check"
end
end

Rails flash[:notice] always nil

I cannot figure out why my rails views are not recognizing flash[:notice] or flash[:error]. I keep getting the following error regarding the partial view being rendered. The specific error is:
ActionView::Template::Error (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]):
In my controller I have
def index
#organisms = Organism.all
flash[:error] = "test"
flash[:notice] = "test"
respond_to do |format|
format.html
format.json { render :json => #organisms }
end
end
In my index.html.erb file I render out a partial through:
<%= render "shared/flash" %>
The partial has the following code.
<div id="flashes">
<% if flash[:notice] %>
<p id="flash_notice" class="messages notice"><%= flash[:notice] %></p>
<%= javascript_tag "$('#flash_notice').effect('highlight',{},1000);" %>
<% end %>
<% if flash[:error] || flash[:errors] %>
<p id="flash_errors" class="messages errors"><%= flash[:error] || flash[:errors] %></p>
<%= javascript_tag "$('#flash_errors').effect('highlight',{},1000);" %>
<% end %>
<% flash[:error] = flash[:errors] = flash[:notice] = nil %>
</div>
However, if instead of rendering the partial I throw in <%= notice %> it renders out the notice.
If I take the partial code and stick it in the top of the index.html.erb file it renders correctly. Thus, I assume that I am rendering the partial view wrongly?
Any help is much appreciated. Thanks!
Don't name your partial flash. Ruby on Rails creates a local variable with the same name as the partial. In your case, a flash local variable is being created.
Rename your partial to something other than flash and it should work.
Also, you shouldn't need to set flash to nil at the bottom of your partial. Let Rails take care of that for you.
You have to pass the flash to the partial:
<%= render 'shared/flash', flash: flash %>
Or a bit longer:
<%= render partial: 'shared/flash', locals: { flash: flash } %>

Resources