Ancillary files for view templates in a Rails application - ruby-on-rails

A very basic question on Rails. I would like to create a Rails application that, besides the "regular" html view, it can generate a set of XML files. I am aware that I can tailor the templating using the "respond_to" command and using ERB with the templates ???.xml.erb. My question is: suppose that the final document consists in several of these XML files (some are template and must be autoedited by the application but some others are "static" and do not need to be changed). In this scenario, which would be the best location in the application folder to put these ancillary files of the templates?
Thanks a lot in advance
Miquel

I hope I'm understanding your question...
If your responses are most static you should continue using the .xml.erb templates, but if you need something more dynamic maybe you could consider builder templates, which have a .builder or .rxml extension.
This is an example of what a builder template might look like:
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
xml.title(#feed_title)
xml.link(#url)
xml.description "Basecamp: Recent items"
xml.language "en-us"
xml.ttl "40"
for item in #recent_items
xml.item do
xml.title(item_title(item))
xml.description(item_description(item)) if item_description(item)
xml.pubDate(item_pubDate(item))
xml.guid(#person.firm.account.url + #recent_items.url(item))
xml.link(#person.firm.account.url + #recent_items.url(item))
xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)
end
end
end
end

Related

Linking to pdf in Rails

I have a rails app where I am providing summary information re: various legal opinions. The information about each opinion is called from MySQL. In addition to the information from the database, I would also like to provide a link to a PDF of that particular opinion. Currently the pdfs are all stored in a folder labeled "op_pdf" with in the "assets folder." Each pdf is named using the opinion.id for that opinion (opinion with id = 1 is 1.pdf, 2 is 2.pdf, etc).
I've researched this extensively but keep finding conflicting information.
The code I am currently using (that does not work) is:
'<%= link_to #opinion.name, asset_path "op_pdf/#opinion.id", :format => :pdf) %>'
In initializers/myme_types.rb I have:
Mime::Type.register "application/pdf", :pdf
The 3rd step is my issue. I have to do something in the controller and/or routes. I am working from this - Rails 4 - how to make a link to a PDF file (name.PDF)?
but it seems to be overkill for what I need. Can anyone help me?

Using components in admin-generator modules, it's possible? how?

I need to build a admin interface like this image show. In the past I use components for that purpose but now because the modules are generated trough admin-generator I don't know how to get this done. I check all this docs 1, 2, 3 but without any clue on how to do this. I also created a components.class.php under modules/sdriving_empresa/actions folder and include the component in the view include_component('sdriving_empresa') but get this error:
sfComponents initialization failed.
Any help?
Tabs and Partials, the easy way :)
One of the best possible javascripts for that purpose is Javascript Tabifier. Its easy
to install and play with it. You will find a lot of other Javascript and jQuery Tabbers, get the one you most like.
I would advise you to learn everything about symfony 1 partials in order to get the job easily done. Usually partials are a piece of code which is saved in an external file, and does is loaded later in any part of your code. Its like a variable with a lot of html and php code. Partials (the external files) allow also to receive input variables, so its easy to send them ids from related modules or tables.
Lets look at an example with Tabifier with two Tabs, information and Admin and two partials
editSuccess.php
$sModuleName = sfContext::getInstance()->getModuleName();
$sbasepathtabs = $sModuleName . '/tabs';
<div class='tabber' id='tabberglobal1'>
<div class='tabbertab' title='Information' >
<?php
include_partial($sbasepathtabs . '/_information/_information', array('form' => $form));
?>
</div>
<div class="tabbertab" title="Admin" >
<?php
include_partial($sbasepathtabs . '/_admin/_admin', array('form' => $form));
?>
</div>
</div>
Easily setup it:
Inside your module template folder, create the folder: /_tabs
Inside the folder /_tabs create the folder /_information and /_admin
Inside the folder /_tabs/_information create the file partial: _information.php
Inside the folder /_tabs/_admin create the file partial: _admin.php
Inside each one of those files partials write anything you want.
Those partials will receive the left variable form: array('form' => $form).
You can send to the partials more than one variable: array('form' => $form, 'variable2' => $formnumber2)
When you write a partial, in example the partial _information, you can easily get the form object and its values in the template with:
$id = $form->getObject()->getId();
For normal variables you wont need to call getObject.
Finally, take a deep look at the documentation of both things, symfony partials and Javascript Tabifier. They will solve you anything you need.
Backend Admin Generator:
Admin generator automatically generates all templates in the cache folder. Example:
cache\backend\prod\modules\autoTbPrueba1Backend\templates
cache\backend\prod\modules\autoTbPrueba1Backend\templates\indexSuccess.php
Most of its files are already partials, pay attention to the files who has the _ symbol in their name, they are partials. This means that most of the work is already done for you, and the only thing you will have to do is to override some of the partials (TbPrueba1Backend/list_header which is the file _list_header.php) or even the full template (indexSuccess.php) with the extended information you need.
In order to override backend generated templates and partials, you can copy those files to the template folder of your module:
apps\backend\modules\TbPrueba1Backend\templates
apps\backend\modules\TbPrueba1Backend\templates\indexSuccess.php
Set there any additional information you need, and if you dont see anything new while refreshing the web, remember to clear the symfony cache (symfony cc).
Once you have override the the templates and partials with the new information, the only thing you need now is to write/add those partials inside the div tabs created by your bootstrap framework as I described above.
For a good explanation of the admin generator:
Symfony 1.4 change admin generator actions or templates
http://www.slideshare.net/loalf/symfony-y-admin-generator
http://symfony.com/legacy/doc/jobeet/1_4/en/12?orm=Doctrine
You need the moduleName and the componentName in your include_component()
function include_component($moduleName, $componentName, $vars = array())
{
echo get_component($moduleName, $componentName, $vars);
}
Or maybe your module is in the wrong application. In that case, you may consider moving it in a plugin

mixing clientside javascript template with rails logic for backbone.js

I've worked a while now with Backbone.js, and one of the things I nowadays run into is; Sometimes you need to have serverside logic into a .eco.jst template
For example
an i18n translation (currently look at i18n.js gem for this)
a path a route without hardcoding it (somemodel_path(somemodel))
authorisation (for example, show a delete button if the user can destroy this model). Atm I solve this by passing in some rights object in the json that gets filled in.
Rendering a html helper like simple_form or S3_file_uploader (atm I solve this with rendering it serverside, and put the display on none)
As you know, .eco get parsed by node.js, so I can't call ruby in the eco files. Most of these problems I solve by basicly creating a "data" object in the head. Similar to this:
window.data = {
some_translation = "<%= t('cool') %>",
<%= "can_destoy_model = true," if can?('destroy', Model) %>
post_edit_link = "<%= post_path(#post) %>
}
Besides this being bulky (this is just an example, normally this would be more ordened or I add a html5 data attribute to some dom element), It's time consuming, sometimes you have to recreate complete business logic which otherwise would be a oneliner in rails (take for example the S3_file_uploader, which requires encoded amazon policyfile and a token)
What are your thoughts about this? Should I perhaps not use .eco (although I like templates in seperate files instead of poluting the view). Would I able to use serverside logic if I for instance used mustache or handlebars and which gem would you recommend if so?
My experience with Backbone.js is kind of limited, but I've managed to setup an environment with logic-less templates using the following gems:
handlebars_assets
haml_assets
And a bunch of other stuff, even a mini-framework I'm currently working on (you can find it here)
I picked this approach for building Single Page Applications using Backbone.
Basically, the haml_assets gem provides sprockets with the ability to parse .haml files, this is not needed but I love HAML syntax. The handlebars_assets gem provides means to parse Handlebars templates, both on the server-side and the client-side. You can use Ruby code inside the templates and you would solve both the i18n and the path methods problems you mentioned.
I've found these tools to be excellent to help DRY an application's templates, and it can really save you from adding logic inside templates. If you use Backbone Views to take, for example, decisions on whether to show a delete button or not, you can keep the logic inside the Backbone View, and use that logic to render the proper Handlebars template (or partial).
Using your example:
Coffeescript:
class ProjectShowView extends Backbone.View
template: (context) -> HandlebarsTemplates['projects/show'](context)
deleteButtonTemplate: (context) -> HandlebarsTemplates['projects/shared/delete_button'](context)
render: (canDelete = false) ->
#$el.html(#template(#model.toJSON()))
#$('.delete_button_container').append(#deleteButtonTemplate()) if canDelete
#
The example is quite primitive and basic, but can hopefully point in the right direction. I hope it helps!

What are the best practices to generate "widgetized" content in Rails

On my previous projects built with usage of Zend Framework I extensively used Zend_view's "Action View" helper. It basically allows to initiate a separate cycle of request->dispatch ti action->view_rendering from a view script.
Here is the link to an appropriate page of zend framework reference guide (search for "Action View Helper").
This helper is quite a convenient way to work with widgetized content for example on pages with portal layout where you can stuff a page with different widgets (like advertising blocks, currency informers etc).
Although such an approach negatively affects response time of the page as it involves a lot of additional routing/dispatching activity, it allows to organizes widget code and views scripts into a rational structure. One widget is just a controller action, with linked view script.
Unfortunatelly, I have not found any similar view helpers in Rails.
Is there any way to elegantly solve this task in Rails?
In Rails, the render method of ActionController takes a Hash as arguments and outputs a simple string. You can use this in your view like so:
<%= render :partial => "shared/widgets/_#{widget.widgettype.name}", :collection => #current_user.widgets %>
In this case Rails will iterate through the list of #current_user.widgets, find a widget partials in "app/views/shared/widgets/_widgettypename.html.erb", and call the partial for each attached widget.
For further reading on Rails partials, see the ActionView::Partials documentation.
It seems that I've found an answer to my questions myself. It is "render_component" rails plugin. There is also a fork which apparently supports Rails3.

Markdown to text/plain and text/html for multipart email

I’m looking for a solution to send DRY multipart emails in Rails. With DRY I mean that the content for the mail is only defined once.
I’ve thought about some possible solutions but haven’t found any existing implementations.
The solutions I’ve thought about are:
load the text from I18n and apply Markdown for the html mail and apply Markdown with a special output type for the text mail where
links are put in parenthesis after the link text
bold, italic and other formatting that doesn't make sense are removed
ordered and unordered lists are maintained
generate only the html mail and convert that to text according to the above conditions
Is there any available solution out there? Which one is probably the better way to do it?
In Chapter 4 of Crafting Rails Applications, Jóse Valim walks you through how to make a "merb" handler that uses markdown with interspersed erb and can compile to text and html. Then you make a mailer generator that generates a single merb template for each of your mail actions.
You can read an excerpt from that chapter on the page I linked you to. I highly recommend buying the book.
If you're interested in using my sorry version of what he describes in that book, you can slap this in your Gemfile:
gem 'handlers', :git => "git://github.com/chadoh/handlers.git"
Be warned that I barely know what I'm doing, that I'm not versioning that gem, and that I probably won't really even maintain it. Frankly, I wish I could find someone else who was doing a better job, but I've been unsuccessful in doing so. If you want to fork my project and be the person doing that better job, go for it!
This is a PITA, but is the only way to DRY mail such that you can support both HTML (multipart) & plaintext:
Put the html email copy in a partial file in your ActionMailer view directory with the following extension: _action.html.erb
Replace "action" with whatever action name you are using.
Then create 2 more files in the same directory:
action.text.html.erb and
action.text.plain.erb
In the text.html partial:
<%= render "action.html", :locals => {:html => true} %>
In the text.plain partial:
<% content = render "action.html", :locals => {:html => false} %>
<%= strip_tags(content) %>
That works for me, though it certainly makes me want to pay the monthly service for madmimi
Use the maildown gem.
This gems does the heavy lifting of allowing you to use email.md.erb instead of email.html.erb and email.text.erb. Write it once in a sane format and have it automatically display in HTML and in Plain Text. Win.
There are some intricacies here that you'll want to look at based on your use-case, but here's some of what we did to get it working well:
Create a maildown.rb initializer to setup some sane defaults:
Maildown.allow_indentation = true # Prevents code blocks from forming when using indentiation in markdown emails.
Maildown::MarkdownEngine.set_text do |text|
text.gsub( /{:.*}\n?/, "" ) # Removes Kramdown annotations that apply classes, etc. with `{: .class }`.
This allows you to use indents in your blocks, etc. But also precludes the ability to add indents in your Plain Text. It also removes Kramdown-specific annotation from Plain Text.
Then just replace your HTML and Plain Text files with a single .md.erb file and test it out to make sure it looks good in both versions.
Note, until you remove the .html.erb and .text.erb files, it will show those first before looking for a .md.erb file. This may actually be a nice feature if you ever needed to write separate formats for a specific email (maybe a marketing one that requires more complex formatting than Markdown can provide) without having to specify anything anywhere.
Works a treat.

Resources