I'm following the #322 RailsCasts and in the last part he comments a way to embebed json into html
<div id="articles" data-articles="<%= render(template: "articles/index.json.rabl") %>" >
In my project I have a rabl template: app/views/places/show.json.rabl
object #place
attributes :id, :name, :desc, :address
node(:type) { |place| place.type_place.name }
child :photos do
attributes :id, :desc
node(:url) { |photo| photo.image.url(:square) }
end
If I render /places/21.json it shows:
{"id":21,"name":"foo","desc":"bar","address":"some address","type":"baz",
"photos":[{"id":26,"desc":"foofoo","url":"/uploads/photo/image/26/square_conmemorativo-1920x1080.jpg"}]}
well it's working but if I try to embebed json data into html I'm doing this:
<article id="show_place" data-place="<%= render(template: "places/#{#place.id}.json.rabl") %>" >
error log
Missing template places/21.json with {:locale=>[:en],
:formats=>[:html], :handlers=>[:erb, :builder, :coffee, :rabl]}.
Searched in: * "/home/ed/projects/rails_projects/final_u/app/views"
What Am I doing wrong?
UPDATE
I just found the solution
<article id="show_place" data-place="<%= render(template: "places/show.json.rabl") %>" >
And it works but I don't know why.. and here I have another question
There is a way to pass a single object to the render(template: "") ??
Thanks in advance.... and sorry for my English
The reason behind this is convention for render. The function expects the template itself to render, not the route (which is what you're typing into your URL bar).
If you enter /places/21.json into your URL bar in your browser, it will call the places controller with the parameters of id = 21 and format = json.
It will then render the appropriately named view (Which in this case will be your RABL template) at the end of the function defined in your controller.
That template then renders it's data from the value of the #place variable defined on the first line.
I'm assuming your controller sets the #place variable with params[:id] or something similar.
When you call render you are essentially manually doing the last part that the controller function automatically does for you: Displaying a template.
You then should specify what template you wish to render, making sure any variables are set before hand.
So the reason why places/show.json.rabl works is simply because you are rendering the appropriately named template. This will render the show template under your places folder inside views.
It will then use the #place variable I assume you've defined in earlier in your controller or view.
TL;DR
You did the right thing at the end by rendering the template. You can render a different object by changing the variable the template uses on it's first line.
Related
I am trying to build a demo app like square space. I have a preview page where an iframe loads the template that was selected. So I decided that I wont be needing the default layout (application.html.erb). I created a new folder called Design1 in views and inside it created another folder called partials. I made _header.html.erb inside of it. I created another file called home.blade.php inside the Design1 folder and tried to include the 'layouts/header' in it and it gives me this err
Missing partial Design1/_header with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in: * "/usr/share/nginx/html/fuitter-test/app/views"
this is how I am rendering the header file in home.html.erb
<%= render 'layouts/header' %>
my forlder structuer
views
-Design1
-layouts
- _header.html.erb
-home.html.erb
-other folders
And I have also done
layout false
in the controller
First of all - always downcase on file names! Never use Design or MyCoolStory, in rails we use convention over configuration and that means snake_case which is everything downcased and separated with _under_scores
To your render issues:
There is a great documentation where you'll find anything you need: http://guides.rubyonrails.org/layouts_and_rendering.html
Let me help you a little.
Rails is looking for a Layout. By default it will be expected in /app/views/layouts/application.html.erb (there is nothing wrong with keeping it named as application). A Layout is the whole HTML Frame you will need. Within the Layout there (should) always be a yieldblock.
A YieldBlock in rails is where your templates are rendered into.
so basically a layout-file can look like this (i use haml for easier reading)
%html
%head
=render "shared/head"
%body
.wrapper
%nav.navigation=render "shared/navigation"
.main_content
=yield
%footer.foot=render "shared/footer"
This means you are having 3 partial-templates in /app/views/shared named _head.html.erb, _navigation.html.erb and _footer.html.erb
That's the rails way.
Further informations
If you are planning to have a multi-design app, you should structure your views in total like
/app/views/design1
/app/views/design2
/app/views/design3
/app/views/shared
and set the lookup path in your controller like this
prepend_view_path "#{Rails.root}/app/views/#{design_path}"
def design_path
current_page.design_name
end
By then, all views will be looked up into their specified folder (Spree multi_store engine, is doing like this, for an example)
You put your layouts folder in Design1 folder, thus you should use following path to render your layout:
<%= render 'Design1/layouts/header' %>
The render structure should be starting from the /views folder.
<%= render 'Design1/layouts/header' %>
I have a polymorphic Review model. The namespaced model User::Library::Publication is reviewable. The reviews are created properly, but when I try to display them through a partial, Rails looks up the wrong directory.
In my view:
<%= render #review %>
I get this error:
Missing partial user/library/reviews/review with {:locale=>[:en], :formats=>[:js, :html], :handlers=>[:erb, :builder]}
Rails is apparently looking for the review partial within the namespace's directory views/user/library instead of the /views/reviews. Any idea why this is happening?
If you want to remove namespacing from the partial template path, you can set the prefix_partial_path_with_controller_namespace variable in your config/application.rb:
# config/application.rb
config.action_view.prefix_partial_path_with_controller_namespace = false
This will load partial paths as you define them (without the namespace).
You can see the original Pull Request here.
If you use name spaces you have to create folders/sub folders so Rails is not looking at the wrong place.
If you want to force the partial path just use:
render :partial => "review"
And create rename the review.html.erb file to _review.html.erb
I have a problem when trying to render a controller action. Following the documentation I should be able to use:
render 'user/new' or
render template: 'user/new' or
render :action => "new", :controller => "users"
Although I get a template missing exception and I'm not shure, why. Using a form for works, but it's stupid to copy exactly the same form.
I'm pretty messed, so I'm shurely missing something, but I don't get it.
Any hints?
EDIT: I'm calling from the GroupsController where I want to render the new-user-form. Did a test with only scaffolded models and I get the same error.
ActionView::Template::Error (
Missing partial users/new with {:locale=>[:de], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "/Users/rob/Development/projects/test/app/views"
* "/Users/rob/.rvm/gems/ruby-1.9.3-p362/gems/oembed_provider_engine-0.2.0/app/views"
* "/Users/rob/.rvm/gems/ruby-1.9.3-p362/gems/devise-2.2.3/app/views"
):
Partial templates' filename always begins with an underscore. So you need a "_new.html.erb" file in your "user" view to render.
If I'm not mistaken, the default scaffolding creates a "_form.html.erb" for each model to render it in new and edit actions both. You can just render that instead of the whole "new" view.
I have a rails app (rails 3.1.3) that has a shopping cart model. I wanted to show a summary of the shopping cart in the layout so I created the partial views/carts/_cart.html.haml. My app was working fine and rendering the cart partial in every view. But when I installed devise 2.0, the partial could no longer be found for devise views. Instead, I would see the following error code when I tried to call a devise view:
ActionView::Template::Error (Missing partial views/carts/cart with {:handlers=>[:erb, :builder, :coffee, :haml], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
* "/Users/cameronnorgate/Web Development/Practice Apps/1-Camerons Tea/pgktea/app/views"
* "/Users/cameronnorgate/.rvm/gems/ruby-1.9.2-p290#pgktea/gems/devise-2.0.4/app/views"
As you can see, it searches for the partial in app/views, but doesn't go all the way into the 'carts' folder in order to find the 'cart' partial. This is weird, because the code I had in the layout view specified the exact path (see below):
%body{:class => params[:controller]}
.master_container
.master_header
.inner_header
.cart
= render :partial => 'views/carts/cart', :object => #cart
Can anyone help me understand why my call to render the partial is not being found when inside a devise view?
The short term fix I've made for this is to bring the partial code back into the full layout file - so now devise doesn't have to go searching and everything works... but that's not ideal and it's cluttering up my code.
Thanks!
You should be able to specify the partial with just:
= render :partial => 'carts/cart', :object => #cart
The views/ part of your definition is probably throwing it off. app/views is implied, so when you specify views/carts/cart, it's probably not finding a views directory under app/views.
If this page can be access from other pages . then
= render :partial => '/carts/cart', :object => #cart
Is the correct way , because if this page open in other models then 'carts/cart' will not be available like if url is ex. 'localhost:3000/products' this page will give missing partial error so / will solve the issue and as other answers, 'views' is not needed
I am trying to render a partial on a collection with <%= render #posts %> which returns the error:
Missing partial posts/post with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}
However it works if i use <%= render :partial => 'post', :collection => #posts %>
I have _post.html.erb in the same folder which uses post variable (from posts)
Why would the former example way of rendering a partial on a collection not work, but the latter example does work?
EDIT: I should specify I'm using Rails 3.2.1
The default of to_partial_path for your objects is always scoped under a view folder for the class, so your partial must be in the posts view folder.
When you use the form render :partial => 'post' it looks in the folder of the controller you are currently under.
I suspect that you are not working in the PostsController view folder, which would explain the behavior you are seeing. If you are working in the posts view folder, then something else must be going on so if you could provide more detail that would help diagnose it further