where in rails to put common text used by lots of files? - ruby-on-rails

We have lots of templates that use a common paragraph of text (the description of our company services). The paragraph is currently duplicated among 10 different view templates.
Where should I create a variable like 'company_services_description' that I can use in all the different templates (to DRY it up).
Would defining it in application_controller.rb be the way to go?
Or perhaps would config/application.rb would be the right spot?

It depends how long the text it. I would suggest either storing the text in a partial and using it in your templates as follows:
<%= render "shared/company_services_description_partial" %>
or using an application helper method that you can call wherever you need it.
module ApplicationHelper
def company_services_description
"This is our company services description"
end
end

Related

Rails Model method that builds a string of links

I have a method on a model called Photo. I have it finding a selection of things from elsewhere in my app. All I need it to do at the end is to create a string of links that I can then output later on when the method is called on an instance.
My code is:
cars.map { |c| link_to(c.name, c) }.join(" AND ")
But i'm hitting this error:
undefined method `link_to' for #<Photo
Any ideas how to fix this?
link_to is a view helper which means it's only available in Rails views by default because it's a router / request concern.
If you specifically want to use link_to you have to include it or reference it directly.
See this SO answer
include ActionView::Helpers::UrlHelper
...
cars.map { |c| link_to(c.name, c) }.join(" AND ")
There are other ways of getting paths than using link_to that I would recommend you consider:
It's arguable that the Rails team would tell you to use UrlFor as the tip in that link suggests:
Tip: If you need to generate URLs from your models or some other place, then ActionController::UrlFor is what you're looking for. Read on for an introduction. In general, this module should not be included on its own, as it is usually included by url_helpers (as in Rails.application.routes.url_helpers).
UrlFor also allows one to access methods that have been auto-generated from named routes.
class User < ActiveRecord::Base
include Rails.application.routes.url_helpers
def base_uri
# named_route method that uses UrlFor
user_path(self)
end
end
User.find(1).base_uri # => "/users/1"
create your own concern to bring in route helpers via ActionMailer as this article suggests
As you may see if you scroll through other SO questions about including view helpers in models, there is pushback on using router and request -based methods outside of controllers and views because it violates the principles of MVC.
I think your use case can give you some peace of mind about this, but it's worth knowing the water is murky and some people may advise you otherwise.
The traditional Rails wisdom (and what I'm about to give you here) is that models should not be creating HTML. They also shouldn't have methods that return HTML. Creating HTML <a> tags should be done much closer to the user interface: in a view template or maybe in a view helper. One reason is that the particular way the hyperlink should be generated is a concern of the view. (Does it need a nofollow attribute? class attributes? This will change, even from one view to another.) And the model should not have any knowledge of these details.
When you do generate links in the views, then you have access to all the helpers such as link_to.
Instead, as I understand it, a model should be responsible for returning its own data. Maybe in your case that'd be an array of dicts of :label, :url. I.e., pure data that'd be easy to pass to link_to.
Hope that helps!

Embedded Ruby not being read when calling html_safe

I'm developing a simple app that teaches people english. The app is based on 5 modules of 34 classes each - 170 total. Each class has its own html page.
Since i dont want to create a view for each class, i scaffolded an Aula model ("class" in portuguese) and saved the html of each class in the model's DB, so i could use only the standard Show view paths to show the classes using their individual id's.
Controller code:
def show
#aula = set_aula
end
These HTML pages are being stored in the database as strings and then being outputted on the Show view using the html_safe method.
#show view code:
<%= #aula.aula.html_safe %>
#"aula" is the DB attribute with the html of each class
It rendered the HTML with no problems, and i got what i wanted. But since i'm creating a rails app, i decided to use embedded Ruby code like <%= link_to %> and <% image_tag %> mixed with the HTML of the classes to create links and show images, and the problem is that these links are being outputted as strings as well, just like any other line, instead of being read and executed as actual Ruby code.
I've been doing a lot of research, but so far I can't find exactly how to make the ERB code be read properly.
Maybe I need to save the HTML in the DB using another data type, or I need to use another method to render the HTML.
First, I'll answer your question, then make a suggestion that you think very carefully before using this approach.
The answer in the post https://stackoverflow.com/a/14351129/483133 shows how to render ERB directly from stored HTML text. Modifying this, here is some code you could use:
def show_html
html = #aula.aula
template = ERB.new(html)
template.result.html_safe
end
# Run this from your controller action, for example, with
def show
#aula = set_aula
end
# inside your view show.erb.html
<%= show_html %>
Warning
I would strongly recommend against finding a solution that allows Ruby code stored in the database to be run. If the pages are able to be written in any way by end users, rather than trusted software developers, then you have opened a huge security hole. Any Ruby code could be run on your server.
I would suggest you consider using a client-side rendering solution (such as Handlebars: http://handlebarsjs.com/ ), which allows for basic rendering of data dynamically in HTML, while not allowing code to be run on your server.

Rails: form generation based on conditions

I've got a form to build a Document. That form needs adjusting depending on what type of Document a user has chosen. At this point I've got a deferring kind of method in new.html.erb that goes like this:
<%= render 'form_'+#template.label.downcase.parameterize.underscore %>
Which works fine but it's kinda difficult to manage though because when new types of documents are added I need to create actual HTML files and upload them.
Is there a better way to manage this kind of form generation? A view with hundreds of if statements in it feels cumbersome too.
You can push it to document_helper or decorator like :
module DocumentHelper
def form_render
return 'form_#{type}'
end
end

Where to store editable content?

I am building a Rails app that is intended to be eventually used by non-technical people. It consists of a few pages with blocks of text and a special page with interactive canvas drawings.
I want to allow them to easily edit any piece of text contained in the application. What are the best ways to achieve that? Currently, text is written in the different views of the application, which does not allow them to edit it without having to connect via FTP or similar and search for the right file.
I am thinking of three solutions:
Store all blocks of text in the database. On each page, fetch the requires blocks and insert them before rendering. Build a page that lists all blocks in the database in editable areas with a save button.
Store all blocks of text in a json file. Create a model that can read the file and fetch the blocks required by the views. Build a page that lets you edit each block and save it in the file.
Create some kind of password-protected admin interface that fetches all file in the views directory, use regexp to find blocks of text and allow the users to edit each block and save.
From my point of view, all of my three solutions look pretty bad. It does not feel okay to do so many calls to the database? Store your entire website text in a file? Parse HTML with regexps?
What are the usual approaches used to solve this problem?
There's a great book out there: Crafting Rails 4 Applications. Here's the link to source code from the book. You will find example in templater folder. Basically, you will be able to create custom templates based on the request parameters (just like Rails does).
Update. Here's a couple of links:
Default views in Rails 3.0 with custom resolvers by José Valim (author of the book, by the way).
Implementing a Rails 3 View Resolver.
Also, here's 5 coins from me. Basically, it works like this. You need to define your own resolver and connect it to your ApplicationController (or any other controller you want):
class Resolver < ActionView::Resolver
# some code here
end
class ApplicationController < ActionController::Base
append_view_path Resolver.new
end
During the rendering process, Rails will ask your controller's resolvers to provide a template (it will go through each of them, until it finds template or until there won't be any resolvers left). In order to provide template, your resolver needs a find_templates method:
def def find_templates(name, prefix, partial, details)
# some processing here
end
So, based on this method parameters, you're going to provide some database records. But even if you have some kind of model already, Rails expects this method to return ActionView::Template instance. It can be initialized like this:
ActionView::Template.new(source, identifier, handler, details)
So, that's how your find_templates should look like:
def find_templates(name, prefix, partial, details)
template = DatabaseTemplate.find... # your custom model for DB templates
ActionView::Template.new... # initializing actual template
end
Both model and resolver in detail are presented in the book's source code (templater/3_final/app/models/sql_template.rb).
I have done that a couple times with awesome user satisfaction by using this:
http://jejacks0n.github.io/mercury/
There is also a Railscast available which gives you a good overview and step by step instructions:
http://railscasts.com/episodes/296-mercury-editor
Hope it helps. It looks good and is easy to use for end users.

Dividing text article to smaller parts with paging in Ruby on Rails

This time I've got problem with dividing text article into smaller parts. I don't need to figure out "automatic" algorithm based on words counting or something. All I need is something similar to function which is build-in Wordpress WYSIWYG editor (special breaking page tag).
I thought out only one solution so far. I don't want to divide specific article inside my database. I just want to place some tag inside article and divide it to array in show method.
Sample code:
#controller
#art = Article.find(:id)
if #art.value.contains?('<breaker>')
#parts = art.value.split('<breaker'>)
end
session[:current_part] = params[:current_part] ? params[:current_part] : #parts.first
...
render
#view
<%=h #parts[session[:current_part]] %>
How it sounds for you? It makes any sense? Cant wait for some advices.
It may be better to use an HTML comment so it does not affect the validation of the page.
In your Rails views, in the templates that show text before the breaker, you can split your content like what you have in the example code. I would perform this in a Rails helper module so it can be reused.
To view the full article, your helper method will return the full content if the parameter "more" is passed. The code may look something like this:
# controller
def show
#article = 'Before the break<!--more-->After the break'
end
# app/helpers/application_helper.rb
def show_more(article)
params[:more] ? article : article.split('<!--more-->').first
end
# show.html.erb
<%= show_more(#article) %>
It is generally good practice to keep the application logic in the model and helper files, and keep your controllers as simple as possible.

Resources