Redcloth extend with emoticons filter - ruby-on-rails

What would be a good way to implement emoticons/smiley's in a simple messaging system?
I came out on red cloth as a valuable solution.
The messages will be saved in the DB like ;), :) ;(
* like described here but this is old: http://flip.netzbeben.de/2008/07/smilies-in-rails-using-redcloth/ I try that any comments on that solution in safety etc?
UPDATE:
Created a helper method , this one works
def emoticons(text)
emoticons = { ":)" => "<img src='/assets/emoticons/smile.gif' class='emoticon'>",
":(" => "<img src='/assets/emoticons/cry.gif' class='emoticon'>"
}
[emoticons.keys, emoticons.values].transpose.each do |search, replace|
text.gsub!(search, replace)
end
return raw text
end
Any way to more improve this? the replacement works although the

This
emoticons = {":)" => "[happy/]", ":(" => "[sad/]"}
text = "test :) :("
[emoticons.keys, emoticons.values].transpose.each do |search, replace|
text.gsub!(search, replace)
end
p text
will output
test [happy/] [sad/]
you can play with gsub to get HTML output instead of pseudo BB code

Related

Markdown Render Newlines

I'm working on a Project and give an user the possibility to create a Post.
With loading the Post, i'm calling the markdown method, to extract links and format the text.
Now i got a Problem.
By writing "1. Example" the Output in the Post is a list.
By just writing "1.Example"_ without the whitespace between the point and the text, it'working fine.
My markdown method:
#preview = nil
options = {
autolink: true,
hard_wrap: true
}
begin
URI.extract(text, ['http', 'https', 'www']).each do |uri|
unless text.include?("<a")
text = text.gsub( uri, "#{uri}" )
#preview = LinkThumbnailer.generate(uri)
end
end
rescue OpenSSL::SSL::SSLError => e
end
renderer = Redcarpet::Render::HTML.new(options)
markdown = Redcarpet::Markdown.new(renderer)
markdown.render(text).html_safe
May you know, how to fix it.. I don't want the list, i just want the Output to be the same like the Input!
Thank you, for your time!
EDIT Added a photo to show the output.
You want to use a backslash escape in your Markdown source. As the rules explain:
Markdown allows you to use backslash escapes to generate literal characters which would otherwise have special meaning in Markdown’s formatting syntax.
Among the characters which backlash escaping supports is the dot (.). Therefore your source text should look like this:
1\. Example
Which results in this HTML:
<p>1. Example</p>
And renders as:
1. Example
By default you're going to get the list. Markdown is after all looking for syntax that it recognises in order to generate mark up.
In order to skip particular markdown features I think you're going to need to provide your own custom renderer.
If you define a new renderer:
class NoListRenderer < Redcarpet::Render::HTML
def list(contents, list_type)
contents
end
def list_item(text, list_type)
text
end
end
and use an instance of that instead of the default renderer class when you create your markdown instance it should skip the default list processing. (NB. I haven't tested this code):
renderer = NoListRenderer.new(options)
markdown = Redcarpet::Markdown.new(renderer)

Replacing html text based on database

I want to make app which will switch vocabulary in desired url of webpage Japanese to English.
But firstable I want start form just simply display desired url of webpage inline lust like Google Translate.(See here)
I got html data from desired url using code below,
and now I want to replace text in html all at same time based data on database.
def submit
require 'open-uri'
charset = nil
#html = open(params[:url]) do |f|
charset = f.charset
f.read
end
end
Database is undone, but I am going to contain Japanese vocabulary which should be switched, and English vocabulary which should be switched instead of Japanese vocabulary.
Any ideas or ways to do this?
Also, I just started learning Ruby on Rails recently so it would be nice if you explain it with some examples or detailed explanation :)
I just want to replace particular word in text based on item on database,I don't want to multilingualism.
EDIT:
For example i got following html below from desired webpage.
<html>
<head>
</head>
<body>
<p>I want to switch "aaa" this and "ccc"</p>
</body>
</html>
Lets say I want to switch(Replace) "aaa" to "bbb", "ccc" to "ddd".
Word that should be switched and be switched instead of previous word are in database.(Target:"aaa","ccc" Switch:"bbb","ddd")
since this html is the one i got it using open-uri, i can't implement code like #{target}.
Working based on the code in this answer and this answer, you could do something like this:
replacements = {'aaa' => 'ccc', 'bbb' => 'ddd' }
regex = Regexp.new(replacements.keys.map { |x| Regexp.escape(x) }.join('|'))
doc = Nokogiri::HTML::DocumentFragment.parse(html)
doc.traverse do |x|
if x.text?
x.content = x.content.gsub(regex, replacements)
end
end
I've also tested that:
replacements = {'こんにちは' => 'Good day', 'bbb' => 'ddd' }
regex = Regexp.new(replacements.keys.map { |x| Regexp.escape(x) }.join('|'))
"こんにちは Mr bbb".gsub(regex, replacements)
Gives the expected:
Good day Mr ddd
You might also want to use:
regex = Regexp.new(replacements.keys.map { |x| '\\b'+Regexp.escape(x)+'\\b' }.join('|'))
to prevent "aaardvark" being changed into "cccrdvark".

Rails 4: How to render a method with multiple returns

A method with multiple returns
def savings_for(id)
payments = Payment.user_of(id).all
savings = 0
num = 0
payments.each do |payment|
item = Item.find(payment.id)
num = num+1
savings += item.price
end
return savings, num
end
I´m using this helper in a view. Like this
<p>You´ve save <b><%=savings_for(current_user)%>$</b></p>
But I don´t know how render correctly:
You´ve save [#<BigDecimal:108289ca0,'0.13E3',9(27)>, 3]$
Update: Changed the return method:
return "<b>#{savings}€</b> en #{num}"
How i can render the html bold tag?
So, a helper method that is supposed to return something to render on a page, should return a string, not an array of multiple values.
You should decide yourself how you want the multiple values to display. How do you want them to display? Maybe just separated by a comma? Okay, so format it like that yourself inside the helper method:
...
return "#{savings}, #{num}"
end
updated answer for updated question
Update: Changed the return method:
return "<b>#{savings}€</b> en #{num}"
How i can render the html bold tag?
I'd do this:
def render_savings_for(savings, num)
safe_join(
content_tag("b", "#{savings}€"),
" en ",
num
)
end
Writing your own html-rendering helpers can look a bit confusing, but there are really just a few simple concepts around html safety to understand. I've previously tried to explain some of them here: https://bibwild.wordpress.com/2013/12/19/you-never-want-to-call-html_safe-in-a-rails-template/
Another alternative would be using a view partial instead of a helper method, which wouldn't require you to pay attention to html_safety tricks it would just take care of it for you, but for something this simple I think a helper method is simpler.
Next, you're going to start asking about i18n... make a new question! :)
I am thinking something like this;
<p>You´ve save <b><%=savings_for(current_user).to_f.round(2)%>$</b></p>
if you decide to return savings only like this;
...
return savings
end
otherwise if you want both you should do this;
...
return "#{savings.to_f.round(2)}, #{num}"
end
and in the view;
<p>You´ve save <b><%=savings_for(current_user) %>$</b></p>

How to identify and make a link out of '#' in user comments like they do on Youtube

I want to look into making functionality like Youtube has on their website when a user types in a comment and if they have something like '#username' the system recognizes the '#' sign and makes a link to the username's comments. I'm developing using Rails 3 but any information regarding about the logic required for this feature would be appreciated, thanks.
EDIT: Additonal question: Where's the best place to put the logic for this? I would feel like the controller would be so if a client doesn't have javascript it'll still work.
I am sure there are multiple (and even better) ways of doing this. How I did it was -
A function to parse the input string: I wrote a helper function -
It traversed every word in the post and for all words starting with an '#'
For every such word it checked if the user existed in the application.
If yes then replace the word with a link to the user profile.
Write the new post (one with the links) to the database.
def mention_users_and_tags(post)
post_with_user_links = ""
words = post.message.split
words.each do |word|
if word[0] =~ /^#.*/ and word.length > 1
if extract_user_if_exists(word[1,word.length-1])
post_with_user_links << "#{link_to "#{word}", :controller => "users", :action => "show", :id => #mentioned_user.id} "
else
post_with_user_links << word << " "
end
end
end
end
EDIT - I think this method should be written in the model and called in the controller. This was the first time I was coding in rails, so I wasn't very sure where everything goes and I wrote this as a helper function. But now I know all business logic goes in the Model. Since mentioning users in posts can be considered part of the business logic, I'd write a function for it in the model.

Evaluating string templates

I have a string template as shown below
template = '<p class="foo">#{content}</p>'
I want to evaluate the template based on current value of the variable called content.
html = my_eval(template, "Hello World")
This is my current approach for this problem:
def my_eval template, content
"\"#{template.gsub('"', '\"')}\"" # gsub to escape the quotes
end
Is there a better approach to solving this problem?
EDIT
I used HTML fragment in the sample code above to demonstrate my scenario. My real scenario has set of XPATH templates in a configuration file. The bind variables in the template are substituted to get a valid XPATH string.
I have thought about using ERB, but decided against as it might be a overkill.
You can do what you want with String's native method '%':
> template = "<p class='foo'>%s</p>"
> content = 'value of content'
> output = template % content
> puts output
=> "<p class='foo'>value of content</p>"
See http://ruby-doc.org/core/classes/String.html#M000770
You can render a string as if it were an erb template. Seeing that you're using this in a rake task you're better off using Erb.new.
template = '<p class="foo"><%=content%></p>'
html = Erb.new(template).result(binding)
Using the ActionController methods originally suggested, involves instantiating an ActionController::Base object and sending render or render_to_string.
I can't say I really recommend either of these approaches. This is what libraries like erb are for, and they've been throughly tested for all the edge cases you haven't thought of yet. And everyone else who has to touch your code will thank you. However, if you really don't want to use an external library, I've included some recommendations.
The my_eval method you included didn't work for me. Try something like this instead:
template = '<p class="foo">#{content}</p>'
def my_eval( template, content )
eval %Q{"#{template.gsub(/"/, '\"')}"}
end
If you want to generalize this this so you can use templates that have variables other than content, you could expand it to something like this:
def my_eval( template, locals )
locals.each_pair{ |var, value| eval "#{var} = #{value.inspect}" }
eval %Q{"#{template.gsub(/"/, '\"')}"}
end
That method would be called like this
my_eval( '<p class="foo">#{content}</p>', :content => 'value of content' )
But again, I'd advise against rolling your own in this instance.
This is also a nice one:
template = "Price of the %s is Rs. %f."
# %s - string, %f - float and %d - integer
p template % ["apple", 70.00]
# prints Price of the apple is Rs. 70.000000.
more here
To late but I think a better way is like ruby-style-guide:
template = '<p class="foo">%<content>s</p>'
content_text = 'Text inside p'
output = format( template , content: content_text )

Resources