Rails I18n: Better way of interpolating links? - ruby-on-rails

Is there a cleaner, content_tag-ish way of doing this? (I don't want HTML in my YML)
en.yml:
expert_security_advice: "Go <a href='{{url}}'>here</a> for expert security advice."
layout.html.erb:
<%= t(:expert_security_advice, :url => "http://www.getsafeonline.org") %>

The best I could come up with:
en.yml:
expert_security_advice: "Go *[here] for expert security advice."
layout.html.erb:
<%= translate_with_link(:expert_security_advice, "http://www.getsafeonline.org") %>
application_helper.rb:
include ActionView::Helpers::TagHelper
def translate_with_link(key, *urls)
urls.inject(I18n.t(key)) { |s, url|
s.sub(/\*\[(.+?)\]/, content_tag(:a, $1, :href => url))
}
end

No, there isn't a cleaner way of dealing with this. If you want pull the url out of the string then you're stuck breaking the sentence into four pieces:
"Go.
...
'here'
'for expert security advice.'
These four pieces are easy to put back together in English but the order might change in other languages and that can change the capitalization of here and cause other problems. To get it right, you'd have to structure things like this:
here = "#{t(:expert_security_advice_here)}"
whole_thing = t(:expert_security_advice, :here => here)
and the two separate strings in your YAML:
expert_security_advice_here: "here"
expert_security_advice: "Go {{here}} for expert security advice."
You'd also have to tell the translators that those two pieces of text go together.
If that sort of thing seems cleaner to you then go for it but I wouldn't worry about small bits of HTML in text that needs to be translated, any translator worth talking to will be able to handle it. Never try to take shortcuts with I18N/L10N issues, they will always lead you astray and cause problems: non-DRY code (WET code?) is always better than broken code.
As an aside, I'd recommend that you drop the standard Rails I18N string handling tools in favor of gettext, keeping everything synchronized with gettext is much easier and the code ends up being much easier to read.

Related

Validate field in multiple languages

I have the next form:
<%= form_for :user, url: "#" do |f| %>
<%= f.text_field :name %>
<%= f.submit "send" %>
<% end %>
and I need to validate the name field, but the page is working in multiple languages: chinese, portuguese, spanish and so on.
then I can't restrict the field just to alphanumerical values.
how can I validate just the dangerous special characters?
Let me try to break it down to several problems
1) how can I validate just the dangerous special characters?
It depends on what you do with the input date. Do you build a SQL query with it, do you
show it on your web page, do you send it to 3rd party web app, do you run some command line tool on the server and pass the data to it as an argument.
All of these things may have different notion of "dangerous special characters" and handling them.
So, there is no one perfect answer.
Probably, you need to specify how do you use this data.
2) where can I get more information on all kind os such problems?
I really hope that you are asking this question, because if you protect your application from SQL injection, but left wide open some other usual security holes, it won't do you too much good.
There is a very good security good for rails app, which is must read for security conscious developer:
http://guides.rubyonrails.org/security.html
3) ok. How do I handle multi language page
The default encoding is UTF-8 for Ruby 2.0 and up (which most likely you are using). This mean that you don't have to do anything special to handle other characters(languages which use them). However, you are right, you will need to add some kind of escaping for special characters (which depends on question #1).

How the url should be stored in records?

I have a question.
I have comment model, in which it has body column that users can type anything in there.
obviously user might type the url link to other website.
In my guess, I think it should be replaced with < a href > tag when it is being saved.
Is there any good gem or something to handle this kind of thing?
If you don't want to use a full-blown markdown parser (Redcarpet), use Rinku. It's super fast and safe. Do not use any regex based solutions as you would most likely open yourself to security risks.
text = "Hello! Check this out: https://github.com/vmg/rinku"
Rinku.auto_link(text, mode=:all, link_attr=nil, skip_tags=nil)
Produces:
=> "Hello! Check this out: https://github.com/vmg/rinku"
Preserving for posterity's sake, but I feel it's important to note that this is NOT a secure way to solve the problem. Unless you want to figure out all the security implications for yourself, don't follow this advice. Jiří Pospíšil's answer is better. =D
You don't really need a gem to do that (I personally try to avoid gems for something so simple). Write a regular expression that is reasonably reliable for your purposes, and then use something like
input.gsub(regex, 'some text')
to convert the links into their html equivalent. Note that you'll need to use raw to display the results of this, otherwise rails will escape the output for you. This also means users will be able to put other arbitrary markup in, unless you escape it as it goes into the database. Make sure you do that.
Alternately, you could do the same thing as you display it, with slightly different considerations/steps necessary.

ActiveRecord: Produce multi-line human-friendly json

Using ActiveRecord::Base.to_json I do:
user = User.find_by_name 'Mika'
{"created_at":"2011-07-10T11:30:49+03:00","id":5,"is_deleted":null,"name":"Mika"}
Now, what I would like to have is:
{
"created_at":"2011-07-10T11:30:49+03:00",
"id":5,
"is_deleted":null,
"name":"Mika"
}
Is there an option to do this?
It would be great to have a global option, so that the behaviour be set depending on dev/live environment.
I'll go out on a limb and say "no, there is no such option".
AFAIK, the JSON encoding is actually handled by ActiveSupport rather than ActiveRecord. If you look at lib/active_support/json/encoding.rb for your ActiveSupport gem, you'll see a lot of monkey patching going on to add as_json and encode_json methods to some core classes; the as_json methods are just used to flatten things like Time, Regexp, etc. to simpler types such as String. The interesting monkey patches are the encode_json ones, those methods are doing the real work of producing JSON and there's nothing in them for controlling the final output format; the Hash version, for example, is just this:
# comments removed for clarity
def encode_json(encoder)
"{#{map { |k,v| "#{encoder.encode(k.to_s)}:#{encoder.encode(v, false)}" } * ','}}"
end
The encoder just handles things like Unicode and quote escaping. As you can see, the encode_json is just mashing it all together in one compact string with no options for enabling prettiness.
All the complex classes appear to boil down to Hash or Array during JSONification so you could, in theory, add your own monkey patches to Hash and Array to make them produce something pretty. However, you might have some trouble keeping track of how deep in the structure you are so producing this:
{
"created_at":"2011-07-10T11:30:49+03:00",
"id":5,
"is_deleted":null,
"name":"Mika"
"nested":{
"not":"so pretty now",
"is":"it"
}
}
Would be pretty straight forward but this:
{
"created_at":"2011-07-10T11:30:49+03:00",
"id":5,
"is_deleted":null,
"name":"Mika"
"nested": {
"not":"so pretty now",
"is":"it"
}
}
would be harder and, presumably, you'd want the latter and especially so with deeply nested JSON where eyeballing the structure is difficult. You might be able to hang a bit of state on the encoder that gets passed around but that would be getting a little ugly and brittle.
A more feasible option would be an output filter to parse and reformat the JSON before sending it off to the browser. You'd have to borrow or build the pretty printer but that shouldn't be that difficult. You should be able to conditionally attach said filter only for your development environment without too much ugliness as well.
If you're just looking to debug your JSON based interactions then maybe the JSONovich extension for Firefox would be less hassle. JSONovich has a few nice features (such as expanding and collapsing nested structures) that go beyond simple pretty printing too.
BTW, I reviewed Rails 3.0 and 3.1 for this, you can check Rails 2 if you're interested.
Have you considered the JSON gem? I believe it does exactly what you're looking for.
e.g.
JSON.pretty_generate(user)
Have a look at the detail here...
http://apidock.com/ruby/JSON/pretty_generate

SEO urls in rails: .html ending vs. none. What's best?

I'm thinking about a good SEO Url strategy for a blog application. I'm not sure - and maybe it's just the same - but what is better? With or without .html
/blog/entry_permalink_name.hml
VS
/blog/entry_permalink_name
What do you think?
To answer directly you question, without the HTML is better SEO-wise. The search engines take keywords from the url into account. Now the more words or characters there are in the url the weaker the power of a given keyword.
It follows logically that there is no SEO advantage in adding '.html' at the end of the url.
Similarly removing the blog bit would enhance the power of the keywords in the title but if you want to use 'blog' as a valuable keyword, leave it.
Keep in mind that the url is just one of many factors of optimization of a page for SEO, and not the most powerful at that. The common thinking here is that none of these optimization tricks make a substantial difference by themselves but they do cumulatively.
I would suggest removing /blog/ from the url and making it as follows:
/entry-permallink-name
word 'blog' introduces extra irrelevant term to your URL
.html would be mostlikely ignored by search engines, but it's absence makes it a bit more user-friendly, so do dashes instead of underscores.
I disagree about not having the blog entry in there. I don't think 'blog' is an irrelevant term since you are writing a 'blog' application and good has a search 'blog' section.
As for your question, look in your address bar when you view this question. Stack overflow seems like a good site to emulate.
I do agree with xelurg about the dashes instead of underscores.
I would keep the unique id in the name just like stackoverflow. It's a lot simpler that way.

Sanitize output in Rails

What is the best solution to sanitize output HTML in Rails (to avoid XSS attacks)?
I have two options: white_list plugin or sanitize method from Sanitize Helper http://api.rubyonrails.com/classes/ActionView/Helpers/SanitizeHelper.html . For me until today the white_list plugin worked better and in the past, Sanitize was very buggy, but as part of the Core, probably it will be under development and be supported for a while.
I recommend http://code.google.com/p/xssterminate/.
I think the h helper method will work here:
<%= h #user.profile %>
This will escape angle brackets and therefore neutralize any embedded JavaScript. Of course this will also eliminate any formatting your users might use.
If you want formatting, maybe look at markdown.
Personally I think it's not a small decision to accept any HTML entry in any web app. You can test for white/blacklisted tags as much as you like, but unless you're testing for correct nesting, someone could enter a series of closing tags, for example
</td></tr></span></div>
and really mess with your layout.
I'd usually give people something like Textile to enter their markup, since I'd rather spend my time working on business logic than HTML parsing.
Of course, if this text entry is more fundamental to your app (as for example it is for stackoverflow) then you probably should give more attention to hand-rolling your own.

Resources