Yii difference between rendering functions - view

I sometimes get messed up by the three rendering methods:
Controller::render()
Controller::renderPartial()
Controller::renderFile()
Please could you explain. Thank you!

render() is commonly used to render a view that corresponds to what a user sees as a "page" in your application. It first renders the view you have specified and then renders the layout for the current controller action (if applicable), placing the result of the first render into the layout. It then performs output processing (which at this time means automatically inserting any necessary <script> tags and updating dynamic content) and finally outputs the result.
renderPartial() is commonly used to render a "piece" of a page. The main difference from render() is that this method does not place the results of the render in a layout. By default it also does not perform output processing, but you can override this behavior using the $processOutput parameter.
renderFile() is a low-level method that does the grunt work of rendering: it extracts the data variables in the current scope and then runs the view code. The other two methods internally call this one, but you should practically never need to call it yourself. If you do, keep in mind that you need to pass in a file path (not a view path).

Render File:
Will run the rendering methods on a given file with the set rendering engine. This is fairly low level within Yii and only really used internally or in console commands.
Render Partial:
This takes the alias given and converts it into a file path using all the local variables such as current running controllers and modules and alias definitions. It then pretty much just uses render file.
Render:
This is combination of render partials to make our lives easier. It will render the layout on the currently active contoller, or the defined one, render all the content within it, handle caching of renders, and process the output for client scripts.
Hope that clears it up.

renderPartial() is really useful for displaying ssi components in a page - ie, headers, footers, widgets etc.

Related

a rails partial but used by multiple views

I have a piece of code that I would like to have show up on several areas... from two different views. Which is to say handled by two different controllers (all the data comes from a helper though) what is the best way to break this up, should these partials be rendered then as lay outs? Though they use the twitter bootstrap modal and I have had huge issues getting those to show correctly when called from a layout (most the reason why I have to break up this code into a partial, one that comes from one index.erb.html and another that comes from a partial of its own _document_header.erb.html good time to ask, can you stuff one partial within another...
so just trying to get some pointers. This code is really common to two views.
(and is not always needing to be rendered or displayed)...so want to do this the best way.
You can reference a partial that is anywhere in your views folder.
It's common to make a "shared" folder in your views and reference the partial like: <%= render 'shared/my_partial' %>

With regards to Html helpers, does data access code go into the helper class too?

I am writing a helper class to query my Zenfolio feed, return and display the images. Right now this code is split between a viewmodel and code in my controller. I want to pack it up into a helper class. Would all the code go into the helper or do i still split the code among different class with the helper only responible for generating the html? I have googled but not found an answer to my question.
Within the MVC pattern there is a clear separation between Model (data), View (html) and Controller (what gives the Model to the View).
To answer your question, No. Load your models in your Controller. Display them in your View. Html Helpers should only generate html for your view.
You may want to consider using a DisplayTemplate, which allows you use the same View template for every model of a particular type.
I wouldn't do any data access from the view. This sounds like a good use case for an action, and reusing code via the RenderAction method. You can mark the action as a child action using the [ChildActionOnly] attribute, which ensures it can't be invoked directly from the HTTP request, and return a PartialView result.
HTML helpers should really be used to generate HTML tags from data taken from the ViewData or Model (i.e. your view model in this case).
Data access in an HtmlHelper is only pain.
I've had the misfortune to inherit a project that had ad-hoc SQL placed into the HtmlHelpers by the 2nd developer on a project. The HtmlHelpers were beautifully written by the first developer, and the ad-hoc SQL pretty much nullified all of the time and effort put into having an service oriented architecture, having an ORM (the 2nd level cache became worthless), the unit of work pattern(transactions, worthless), and every aspect of design. Eventually, this 2nd developer had to make larger and larger HtmlHelpers so that different elements could share access to the data.
This was originally done for a display mode, and editing was accomplished through a pile of ugly custom javascript. All told, when the page rendered, it made 600 synchronous calls to the database.

How to render partials from unrelated controllers in one view....almost Amazon style

How can we render many partials from different controllers into one view?
The local variables of each partial are calculated separately in different and independent controllers.
What I really have to make things more specific, is a home layout, and in that layout that has dynamic content, there's a partial that only handles site wide news announcements, and these are independently updated.
I know a quick hack such like:
render :partial => '/news', :locals=> {#news = News.last}
but I want something more "correct". Like I've been reading about :templates rendering but i'm not sure how it works exactly in Rails 3.1.
Any help would be highly appreciated!
2.2.3 Rendering an Action’s Template from Another Controller
What if you want to render a template from an entirely different controller from the one that contains the action code? You can also do that with render, which accepts the full path (relative to app/views) of the template to render. For example, if you’re running code in an AdminProductsController that lives in app/controllers/admin, you can render the results of an action to a template in app/views/products this way:
render 'products/show'
Rails knows that this view belongs to a different controller because of the embedded slash character in the string. If you want to be explicit, you can use the :template option (which was required on Rails 2.2 and earlier):
render :template => 'products/show'
Sources: http://guides.rubyonrails.org/layouts_and_rendering.html#using-content_for
Should have read in more details.

Views Attach-Node Content alternate block region output

I am using the 'Node Content' output format from the Views Attach module to display nodes referenced to a parent node.
The referenced nodes output as part of the $content variable but I really need it to output in a block separate from the content.
Regular views blocks can't access agruments, but I guess you might try a panels module and a content pane view display. This way you would get some freedom of arranging the results.
Thanks Dmitry Vyal,
I have never used the Panels module and when I tried your suggestion I had problems with Views Panel which made your suggestion unworkable.
However, what I ended up doing was calling my view programatically from page.tpl.php.
Basically, I created the view as a regular block with arguments. We know blocks do not work with arguments but that's if you output it in a region as you would normally do.
My views generated block is only output by printing it from php which is where I also dynamically provide it with arguments.
It works.

Use cases for the different Padrino haml helpers

I read http://www.padrinorb.com/guides/application-helpers but I'm unclear as to what are the use cases for each of the view helpers. Specifically, how do content_for/yield_content, render/partial, capture_html, and concat_content all fit together?
Right now I've been using render 'my/view' in my controllers and throwing in some =partial 'my/partial' within 'my/view' just to break apart the main template file into smaller chunks.
Is the right way to go about it? And when/where would I want to use the other helper functions?
Let's go through the use cases.
content_for/yield_content
This is for injecting content into a layout file that might be useful. Example is adding additional css/scripts into a layout from another template. The example on the guide is the same, showing how to add CSS files to your layout from any template that requires them. You can also use it for adding content onto sidebars, additional links, etc. It is for things that do not require their own template but need to pass information back to a layout based on the view being shown.
render/partial
render is for showing a given template associated with a route. render should be used for the main actions after a route is processed. partial is like a 'method' in a view. It can be reused and variables can be passed to change the output. You use partials in main templates to break up code and reuse pieces of views that otherwise might seem redundant.
capture_html/concat_content
This is usually used to create your own helpers that take blocks of content. For instance let's create a helper that takes a haml block and wraps it in a div. Usage is as follows:
# template.haml
# NOTE the equals so the content is returned
# and added to the view directly
= div_wrapper do
%h1 Some heading
%p This is now wrapped in a div
To implement this and use it in a template, you need to be able to 'capture' the haml passed into the block in order to process and then wrap a div around it. This is where capture_html comes in:
def div_wrapper(&block)
nested_content = capture_html(&block)
content_tag(:div, nested_content)
end
This will take the content and spit it out into the view wrapped in a div. Now, lets presume we want this helper to be more complex and so you want the use to be more like this:
# template.haml
# NOTE the dash so the content is not outputted directly
- div_wrapper do
%h1 Some heading
%p This is now wrapped in a div
but it also works in other helpers:
# some_helper.rb
def example(name)
div_wrapper { "<h1>Test</h1>" }
end
In order to properly print out the wrapped content from the helper in both a template AND straight ruby, we can use concat_content and check to see if we need to 'concat' the result to the template or simply return it.
def div_wrapper(&block)
nested_content = capture_html(&block)
tag_result = content_tag(:div, nested_content)
block_is_template?(block) ? concat_content(tag_result) : tag_result
end
I hope this works as a basic overview. The functions can overlap but generally it becomes clear when to use which based on specific context.

Resources