nested rails partial doesn't draw - ruby-on-rails

I have a table in a partial _measures_findings_list.html.erb where I want to replace the table row with another partial, which I can reuse elsewhere. MeasuresFinding is a model, so I first created a partial _measures_finding.html.erb, and tried:
<% render #measures_findings %>
then I tried
<% #measures_findings.each do |measures_finding| %>
<% render 'measures_finding', measures_finding: measures_finding %>
<% end %>
Nothing. Then
<% #measures_findings.each do |measures_finding| %>
<% render 'measures_finding/measures_finding', measures_finding: measures_finding %>
<% end %>
What am I doing wrong? Putting the code of the partial into the each loop works of course.

You miss '=', it should be
<%= render #measures_findings %>

Related

Rails view not displaying partial - "response has no matching <turbo-frame id="events"> element"

I've got an index page with a search which mostly works, aside from when there are no results, which is when I get the error:-
response has no matching <turbo-frame id="events"> element
I don't get this when there are search results. Do I need to specify a partial to render in my index action, when results are empty? Why isn't this being evaluated in my view?
index.html.erb
<div id="events-wrapper">
<% if #events.any? %>
<%= render "events", events: #events %>
<% else %>
<%= render "no_events" %>
<% end %>
</div>
_events.html.erb
<%= turbo_frame_tag "events" do %>
<%= render collection: #events, partial: 'event' %>
<%= raw pagy_bootstrap_nav(#pagy) %>
<% end %>
_no_events.html.erb
<div class="no-events-notice alert alert-primary">
No events found
</div>
events_controller.rb index action
def index
#pagy, #events = pagy(find_events(filter_params))
end
Basically my search works fine, but when there are no results - my no_events partial doesn't get rendered, unless I refresh the page. What am I missing?
I've removed the partial from the equation and just replaced that line with a simple div instead and it's still not displayed.
The solution was to wrap the results in a turbo frame with an id of "events" like so:-
<turbo-frame id="events">
<% if #events.any? %>
<%= render "events", events: #events %>
<% else %>
<%= render "no_events" %>
<% end %>
</turbo-frame>

Ruby on Rails if/unless statment for AJAX destroy when cart is empty

I am building webstore. I added a bit of AJAX functionality to add, update and remove items from my cart without refreshing.
It works perfect as long as there are no items in a cart and render cart_empty partial properly.
The problem is when I add few items, and I can update/remove them without refreshing and
finally I remove the last one, and it do not switch to the cart_empty partial and there are only empty table headers left from cart-items partial.
Can I add some logic to destroy.js.erb?
destroy.js.erb
$("#cart-item").html("<%= j render 'carts/cart_items' %>");
the show.html.erb contains this unless function:
<% unless current_order.order_items.empty? %>
<div id="cart-item">
<%= render 'cart_items' %>
</div>
<% else %>
<div id="cart-empty">
<%= render 'cart_empty' %>
</div>
<% end %>
Maybe should I modify somehow my controller to check if there are order_items in a current_order?
Thank you!
A JS.erb template is evaluated in exactly the same way as a HTML template. So you can just add a condition:
<% if current_order.order_items.any? %>
$("#cart-item").html("<%= j render 'carts/cart_items' %>");
<% else %>
$("#cart-item").html("<%= j render 'carts/cart_empty' %>");
<% end %>
None that this implies that current_order is either a helper or a local passes to the view.
But you might want to refactor this and push the condition down to the partial:
# carts/cart_items.html.erb
<% if cart_items.none? %>
<% render :cart_empty %>
<% else %>
# ...
<% end %>
Which will let you just write:
<%= render 'carts/cart_items', cart_items: current_order.order_items %>
See:
Layouts and Rendering in Rails - passing local variables

Rails 5 ActionView::Helpers capture method

I'm new in ruby on rails, and I want to practice it.
I'm stuck when I want to include a view into antoher view.
I want by doing that to have my posts into another view than of posts/index
posts/index
method:
def index
#Posts = Post.all
end
view:
<% #posts = capture do %>
<% #posts.each do |post| %>
<h3>
<%= post.title %>
</h3>
<p>
<%= post.content %>
</p>
<% end %>
<% end %>
pages/index
<h1> Index Of another pages </h1>
<%= #posts %>
If you want to force your index action to render another view, then go with follow code:
def index
#Posts = Post.all
render 'pages/index'
end
Correct me if I haven't get you
It sounds to me like you need to save the reusable view code as a partial, and render it all places it's required.
To use a partial, save it down with an underscore prefix, i.e. _posts.html.erb.
This can then be rendered using:
<%= render 'path/to/posts' %>
You'll likely need to pass in the posts variable to the partial, as in the following:
<%= render 'path/to/posts', posts: #posts %>
And the change your view to use posts rather than #posts.
Update:
The result of capture is assigned to #posts, although this variable still wouldn't be available in another template - rather to be used again on the same page
Based on what you're saying about the project's structure, it sounds like you'd need the following:
in app/views/posts/_posts.html.web
<% #posts.each do |post| %>
<h3>
<%= post.title %>
</h3>
<p>
<%= post.content %>
</p>
<% end %>
In both controllers' index action:
#posts = Post.all
In the posts/index view:
<%= render 'posts' %>
In the pages/index view:
<%= render 'posts/posts' %>
I don't want to confuse things, but Rails has a little magic in there where -
alternatively - you can define a partial _post.html.erb as follows:
<h3>
<%= post.title %>
</h3>
<p>
<%= post.content %>
</p>
And simply call <%= render #posts %> in each view. This would be the best 'Railsy' way of doing things.
Let me know how you get on!

Rails: How to make small changes in different views

Is it possible to make small changes in different views?
The same partial is rendered in index.html.erb and show.html.erb as below.
index.html.erb
<%= render #schedules %>
show.html.erb
<%= render #schedules %>
What I'd like to do is not to display some value in the index.html.erb. (and display some value in both erb)
For example, I'd like to display start_at and end_at only in show.html.erb and display title in both erb.
_schedule.html.erb
<% schedule.rooms.each_with_index do |a, idx| %>
<% a.events.each do |e| %>
<%= l(e.start_at) %>-<%= l(e.end_at) %> # display only show.html.erb
<%= e.title %> #display both erb
...
<% end %>
...
<% end %>
Althogh I come up with idea which I create two partials, it contradicts the DRY policy.
It would be appreciated if you could give me any idea.
You can use controller.action_name.
<% if controller.action_name == 'show' %>
<%= l(e.start_at) %>-<%= l(e.end_at) %> # display only show.html.erb
<% end %>
The params hash also contains the action_name.
action_name is enough and do the trick but personally I don't like this. I'd do two separate partials.
Can check current action and current controller on page. So we can call single partial from different actions and can customize as per action name or action and controller name.
eg.
<% schedule.rooms.each_with_index do |a, idx| %>
<% a.events.each do |e| %>
<% if #current_controller == "events" and #current_action == "show" %>
<%= l(e.start_at) %>-<%= l(e.end_at) %> # display only show.html.erb
<% end %>
<%= e.title %> #display both erb
...
<% end %>
...
<% end %>
Also need to update Application Controller.
class ApplicationController < ActionController::Base
before_filter :instantiate_controller_and_action_names
def instantiate_controller_and_action_names
#current_controller = controller_name
#current_action = action_name
end
end
You could use CSS to hide/show the content based on context.
In practice, I have found this a good way to reuse partials that have small differences. Especially when those differences don't cost anything to compute i.e. printing a date
You can cache the partials without worrying about where they are rendered
Reduce conditional logic
Remove duplication
<% if controller.action_name == 'show' %> is fine for a simple use case. If/When you come to have multiple places where the partial needs to be rendered, it will become unwieldy. The CSS solution would only require another wrapper <div class="schedules--whatever"> and the related CSS style.
show.html.erb
<div class="schedules--show">
<%= render #schedules %>
</div>
index.html.erb
<div class="schedules--index">
<%= render #schedules %>
</div>
_schedule.html.erb
<% schedule.rooms.each_with_index do |a, idx| %>
<% a.events.each do |e| %>
<div class="event__date">
<%= l(e.start_at) %>-<%= l(e.end_at) %>
</div>
<%= e.title %>
...
<% end %>
...
<% end %>
schedules.css
.schedules--show .event__date {
display: block;
}
.schedules--index .event__date {
display: none;
}

check if Rails partial is empty

I have a main page that is responsible for HTML/CSS styling, but some of the contents come from partials. A partial receives some locals or params, i.e. current_user or person, and displays information if any.
Is there a way for me to check if a partial rendered anything? My end goal is something like this:
<% if my_partial can render something %>
<div class="css_for_something">
<%= render(partial: 'my_partial', locals: {...} ) %>
<% else %>
<div class="css_for_no_info">
<%= render something else %>
<% end %>
I do not want the partials to handle styling logic; they just need to display content if any. Conversely, the main page should not know anything about the logic in the partial(s), such as checking values or querying the database.
Thank you
Unfortunately, Chris Peter's solution did not work for me on rails 4.2.4, as render_to_string seems to not be available in views.
However, the following worked (rails 4.2.4):
<% partial_content = render partial: 'my_partial' %>
<% if partial_content.present? %>
<%= partial_content %>
<% else %>
<%# rendered if partial is empty %>
<% end %>
Be aware that the present? check really only checks if what was rendered is empty. If, something, e.g. a HTML comment, is returned, the check returns false.
Try storing the value generated by render_to_string in a variable:
<% partial_content = render_to_string(partial: 'my_partial', locals: {...} ).strip %>
Then you can see if it contains any content:
<% if partial_content.present? %>
<%= partial_content %>
<% else %>
<div class="css_for_no_info">
<%= render something else %>
</div>
<% end %>

Resources