I'm looking to take an example of a model (in this case, Book), and render a specific instance of that model by ID.
The model is just a basic scaffold generated model - usual show method;
def show
#book = Book.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #book }
end
end
I'm looking to embed an instance of this inside of the view:
<div class="tab-pane active" id="tab1">
<%= render :template "books/show", :book => 1 %>
</div>
There's something I'm doing wrong here, I can tell. But I don't know where to proceed from here! Any help is really appreciated. I know I need to somehow pass the book ID, but I can't figure out how to do that. Thanks!
<%= render :template "books/show", :book => 1 %> only renders the partial, it doesn't load the page.
What you need to do is call the route "books/show/#{book_id}" from an iframe for example.
Maybe?
<div class="tab-pane active" id="tab1">
<%= render 'books/show', book: #book %>
</div>
The variable #book, you create in your controller is automatically made visible into the template. So, if your template show.html.erb is placed in the right place, then
<%= #book.title %>
should render the text (I assume the Book has an attribute title here).
I am not sure where the html you present is located. It does not make sense in show.html.erb, since you actually reference that file from there. If you would like to render a link to a book, then you should do
<%= link_to 'Link text', book_path(1) %>
Related
I have a page with a partial containing a form in my rails app (5.1.1)
I am using the simple_form gem.
This page is for showing details of a a Journey, which can contain many legs. Inside the journey view, we render a partial "_form" for the legs view. This view contains a form which creates a new leg to add to the journey, and in this case is being rendered from the 'show' view of journey.
journeys/show.html.erb
<div class="container">
<div class="col-xs-12">
<h3><%= #journey.name %></h3>
<h4><%= #journey.legs.count %> <%= "leg".pluralize(#journey.legs.count) %> covering <%= #journey.total_distance.round(1) %> <%="mile".pluralize(#journey.total_distance)%>!</h4>
<hr/>
<h4><%= (#journey.has_legs) ? 'Add another leg to the journey' : "Your journey has no legs, and we all know a journey can't go far without its legs! Quick...give it some legs..." %></h4>
<%= render partial: "legs/form", locals: {leg: #new_legs.first} %>
<%= link_to 'Edit', edit_journey_path(#journey) %> |
<%= link_to 'Back', journeys_path %>
</div>
When a validation error occurs on the leg that is being created, due to the leg's create action code - it renders the :new view of the leg, which works and shows all errors etc on the new view for the leg. This is due to the following action code on the legs controller:
create action of legs
def create
#leg = Leg.new(leg_params)
respond_to do |format|
if #leg.save
format.html { redirect_to #leg, notice: 'leg was successfully created.' }
format.json { render :show, status: :created, location: #leg }
else
format.html { render :new }
format.json { render json: #leg.errors, status: :unprocessable_entity }
end
end
end
However, I would like to render the journey's "show" view showing all errors as would be seen on the :new view of the leg.
I know you can do render "journeys/show" which renders the show view of the journey, however, it doesn't persist the validation errors in the rendered partial "legs/form".
How do I render the journey show view, making sure to pass it all validation errors on the included partial? I have tried using redirect_back(fallback_path=>root_url)but that does not persist the errors.
Please help!
The answer was relatively simple - thanks to the freenode #rubyonrails channel for helping.
Pass the partial a controller created instance of #leg, this #leg object will either be a new object, or it will be the old object with all errors in it.
Create that #leg in the journeys show controller, and in the leg create action, if it fails, create a #journey instance variable from #leg.journey and then render "journeys/show" et voila, everything works as expected.
Upd: it is not the best advise, but it can set you to right direction. i think it sounds as How to display Ruby on Rails form validation error messages one at a time
also here it describes http://guides.rubyonrails.org/v2.3.11/activerecord_validations_callbacks.html#errorsadd
in my case i use this feature without db validation:
controller:
def create
...
flash.now[:danger] = 'Invalid data'
render 'index'
end
view index.html.erb
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
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
I have a blogging application with comments.
Currently, the comments controller has a standard create action
def create
#comment = current_user.build(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to #comment.post }
end
end
After creation, the user is redirected to the blog post for which the comment was made. How do I redirect lower down in the page, to where the new comment is?
posts/show.html.erb
<div id="post_show">
<%= #post.content %>
<%= render #post.comments %>
</div>
comments/_comment.html.erb
<div id="comment_partial">
<%= comment.content %>
</div>
Is there something I can add to my HTML, then reference in my controller? Do I need to "save" the location somehow? Thanks for helping out a newbie!
You can use the anchor option in path helpers, e.g.
redirect_to post_path(#comment.post, anchor: 'some-id')
Sorry for a simple question but i am a bit confused trying to follow ruby on rails tutorial book
I am at the chapter 10 and confused, yes i trick a bit my version for learning purpose
So I have a controller called customer
customers_controller.rb
def show
#customer = Customer.find(params[:id])
#posts = #customer.posts
end
I then have the following folder
_post.html.erb
Welcome to a post
Which his called from the show customer file has follow
/view/customer/show.html.erb
<% provide(:title, #customer.name) %>
<aside class="customer_show_nav">
<h1><%= #customer.name %></h1>
<%= #customer.email %>
</aside>
<div class="events">
<%= render #posts %>
</div>
But when loading nothing his appearing not even Welcome to a post. What i am doing wrong?
Thanks in advance. I am following the tutorial http://ruby.railstutorial.org/chapters/user-microposts#top 10.22
if _post.html.erb is in view/customers
you do this in view/customers/show.html.erb
<%= render 'controller_where_post_lives/post' %> which will look for customers/_post.html.erb
Sometimes, you also need = in <%= %> with rails 3
Also, show is used to show one item, and index is used to show all items.
So to render you will do
<%= render :partial => "post", :collection => #posts %>
Edit:
When you call render you give it the view, no objects here. Unless like above passing a collection.
http://guides.rubyonrails.org/layouts_and_rendering.html
Also if you just want to render text you can do render :text => "OK"
Look for partials explanation.
Implementing Ajax requests in my rails 3 app has been one of the most frustrating things I've ever done. After days wasted trying to follow people's instructions online, the only thing that seems to work for me is ajax delete.
Users of my site have a profile page, which consists of some info at the top, then they have several different resumes, each of which is contained in a tab on the page. Within each resume are educations, which are what I'd like to be able to add and update dynamically. That is, User has_many resumes, and each resume has_many educations. I render each resume in a div with id equal to it's id. This is the div that I would like to have reload with ajax on form submission. Here's a little code.
user/show:
...
<%= render partial: 'shared/resume' %>
...
shared/resume:
<% if #resumes.any? %>
<div class="tab-content" id="tabResumes">
<%= render partial: 'shared/resume_item', collection: #resumes %>
</div>
<%= will_paginate #resumes %>
<% end %>
shared/resume_item:
<div class="tab-pane" id="<%= resume_item.id %>">
...
# here I render a few different partials which display the different elements of the resume, such as educations.
# I'd like to reload this area on form submission.
...
</div>
educations_controller:
def create
#resume = Resume.find(params[:resume_id])
#education = #resume.educations.build(params[:education])
respond_to do |format|
if #education.save
format.html { redirect_to(#student, :notice => 'Education created.') }
format.js
else
format.html {render :action => "new" }
format.js
end
end
end
views/educations/create.js.erb
$('#<%=#resume.id%>').html("<%= escape_javascript()%>"); //not sure what to call here, nothing I've tried has given me any success.
I'd also like to make updating refresh the same div, but I wanted to get create working first. Anybody have any advice for how to make this work? The ajax submit appears to be going through, as I am getting
Rendered educations/create.js.erb
Completed 200 OK in 52ms
in the console.
Try having your create.js.erb along the lines of:
$('#<%= #resume.id %>').replaceWith("<%= escape_javascript render(:file => 'shared/resume_item.html.erb') %>");
Alternatively you can also use the jquery .appendTo method instead of replaceWith, but, in this case I think replaceWith works better.