Create an HTML element with Ruby - ruby-on-rails

I would like some pointers on how to rewrite the post to have links to hashtags. I need to have link_to( ..........) inside the post after I rewrite it and I can't really figure out how to do that in the backend application.
The current method I am trying to use is:
def twitify(tweet = '')
tweet.gsub!(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/) do |tag|
link_to("##{tag}", '#')
end
end
However this only gives me:
jdawiodwiajdaw #mergiCaTeCrap (which is not a link)
This is the HTML:
<li id="tweet-<%= tweet.id %>">
<%= link_to gravatar_for(tweet.user, size: 50), tweet.user %>
<span class="user"><%= link_to tweet.user.name, tweet.user %></span>
<span class="content">
<%= twitify(tweet.content) %>
<%= image_tag tweet.picture.url if tweet.picture? %>
</span>
<span class="timestamp">
Posted <%= time_ago_in_words(tweet.created_at) %> ago.
<% if current_user?(tweet.user) %>
<%= link_to "delete", tweet, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</span>
</li>
I would like it to not show me the href thing, how would I do that?

This is probably because Rails is escaping the html tags due to security reasons, in this case you just have to call the html_safe on the link_to like so:
def twitify(tweet = '')
tweet.gsub(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/) do |tag|
" " + link_to("#{tag.strip}", '#')
end.html_safe
end
You should be good to go!

Okay first of all there is nothing wrong with the way you are going about it.
def twitify(tweet = '')
tweet.gsub(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/) do |tag|
" " + link_to("#{tag.strip}", '#')
end
end
All I did was avoid modifying the original tweet (used gsub instead of the bang method gsub!), added a space before the #hash_tag,removed the extra # and space from the link.
As you can see
tweet = "This is a #tweet and it can make #hash_tags into #links"
twitify(tweet)
#=> "This is a #tweet and it can make #hash_tags into #links"
#your implementation
original_twitify(tweet)
#=> "This is a # #tweet and it can make # #hash_tags into # #links"
So I don't think there is really an issue here you pretty much had everything correct.

Related

Rails: most elegant way to render attributes of a record in a citation

I have a #story record with the following attributes:
author
author_title
year
source
source_link
I'm rendering it in the view so it comes out like this:
James Joyce (author), 1882, Wikipedia
I am hoping there is a less convoluted way to generate the DOM for the citation than this (which is imperfect, as I explain below):
<%= #story.author %><% if !#story.author_title.blank? %> (<%= #story.author_title %>)<% end %><% if !#story.year.blank? %>, <%= #story.year %><% end %><% if !#story.source_link.blank? %>, <%= link_to #story.source, #story.source_link, target: "_blank" %><% end %>
As none of the fields are mandatory, the if-field-not-nil-then-you-may-need-a-comma issue is what I suspect could be handled more elegantly. For example, if author is blank, then I don't want to display the author_title or the trailing comma.
You can try the below code
create a two helper method
def author_story(author)
[#story.author_title, #story.year].compact.join(',')
end
def author_link
link_to(#story.source_link, text: 'testing')
end
and in view
<% if #story.author.present? %>
<div>
<span>
<%= author_story(#story) %>
</span>
<span>
<%= author_link(#story) %>
</span>
</div>
<% end %>
See my comments, Decorators is the way to go. You'll learn to love it and never go back.
If you think it is too much overhead for only a one-time simple task... then create a model method for this:
class Story < ApplicationRecord
.... #other stuff
def author_with_title_and_year
"#{author} #{author_title}, #{year}".squish
end
end
And add the link manually behind it:
<p><%= #story.author_with_title_and_year %> <%= link_to source, source_link %></p>

Converting an image_tag into a link that goes to the destroy route

I would like to convert this line of code into a link that goes to the destroy route in my routes table. When this picture is pressed it will delete the current photo.
<%= image_tag #user.avatar.avatarpic %>
The route is as follows:
user_avatar DELETE /users/:user_id/avatars/:id(.:format) avatars#destroy
The Avatar controller is as follow:
class AvatarsController < ApplicationController
def create
#user = User.find(params[:user_id])
#avatar = Avatar.new(avatar_params)
#avatar.user = #user
#avatar.save
# Three lines above can be replaced with
# #user.create_avatar(params)
redirect_to user_path(#user)
end
private
def avatar_params
params.require(:avatar).permit(:avatarpic)
end
end
Currently I have an if/else statement that will display a default image if an avatar photo isn't available:
<% if #user.avatar.present? %>
<%= image_tag #user.avatar.avatarpic %>
<% else %>
<%= image_tag 'user.png' %>
<a href="#" class="add-image" data-toggle="modal" data-
target="#avatarpic">
Add a Picture
</a>
<% end %>
I would also like for a message to display once the mouse is hovering over the current avatar photo. It will say something to the effect of "Upload a different image". Once pressed, there should be a warning that asks the user "Are you sure you would like to delete this image?". Thank you for your help.
Following the route you give above, please try this:
<%= link_to user_avatar_path, method: :delete, data: { confirm: 'Are you sure' } do %>
<%= image_tag #user.avatar.avatarpic %>
<% end %>
I'm not in front of my PC but this should work:
<%= link_to destroy_path, method: :delete, data: { confirm: 'Are you sure?' } do %>
<%= image_tag #user.avatar.avatarpic %>
<% end %>
Please try and let me know if it does.

Link to with icon in front on same line

So I have this code that I want to convert to rails using link_to:
<a href="#">
<i class="icon-caret-right"></i>
<span>Home</span>
</a>
Giving a nice formatted space in between: > Home
the closest code to get the same result that I have tested with is:
<%= link_to "Factcars", root_path, class: "icon-caret-right" %>
Which gives me (without a space in between): >Home
<i class="icon-caret-right" ><%= link_to content_tag(:span, "Factcars"), root_path %></i>
Gives same result: >Home
Is there a correct way to format this code?
pass block in link_to
<%= link_to "#" do %>
<i class="icon-caret-right"></i>
<span>Home</span>
<% end %>
depending upon link and name , modify the above method.
navigation helper defines a simple method for link_to_with_icon in the module of Spree::Admin gem
#link_to_with_icon(icon_name, text, url, options = {}) ⇒ Object
you can redefine the method in your own helper
def link_to_with_icon(icon_name, text, url, options = {})
options[:class] = (options[:class].to_s + " fa fa-#{icon_name} icon_link with-tip").strip
options[:class] += ' no-text' if options[:no_text]
options[:title] = text if options[:no_text]
text = options[:no_text] ? '' : raw("<span class='text'>#{text}</span>")
options.delete(:no_text)
link_to(text, url, options)
end

Fully escaping a multiline erb segment

I'm trying to create a simple partial that allows me to display code blocks without going through weird contortions in my code.
So I did this in the partial:
<% lang ||= "" %>
<% language = "lang='#{lang}'" %>
<div class="codebox">
<% if title %>
<h3><%= title %></h3>
<% end %>
<pre <%= language %>><%=text.unindent%></pre>
</div>
And this in lib for unindenting strings (thanks to a very nice SO suggestion):
class String
def unindent; gsub(/^#{scan(/^\s+/).min}/, "") end
end
Then, I can just do this, and get a very pretty little code box:
<%= render partial: 'pre', locals: { title: "example.html", lang: 'html', text: "
<div class='cl' style='text-align:center'>
<div class='collapse-group'>
<!-- Title, always viewable -->
<a class='bundle' href='#'>'Click here to expand'</a>
<div class='collapse'>
<!-- The content to be hidden or shown -->
</div>
</div>
</div>
"} %>
This turns into this:
Works like a charm, unless I put in a bunch of erb, in which case it goes nuts and starts erroring all over the place. Ex of an error-producer (contents not super relevant. I made sure that all quotes within are double, while the "string" is in single quotes):
<%= render partial: 'pre', locals: { title: "example.html", lang: 'html', text: '
<% sub ||= "" %>
<% term ||= "(expand)" %>
<% style ||= "" %>
<div class="cl" style="text-align:center">
<div class="collapse-group">
<<%=tag%> class="squeeze" style=<%="#{style}"%>>
<%=title%>
<% if sub != "" %>
<small><%= sub %></small>
<% end %>
<a class="bundle" href="#"><%= term %></a>
</<%=tag%>>
<div class="collapse">
' } %>
Any way I can just tell html that what I'm putting inside those quotes is 100% literal characters? I've tried individually escaping ">"s and ">"s and "%"s and all that, and it's a messy (and ineffectual) path I'm hoping not to go down.
EX of what I want the above to look like:
I think a nice approach in this would be to use #capture, for example in a helper (not tested, just a hint of what to do) :
def code_block( title = nil, lang = nil, &block )
output = capture( &block ) # this is the answer to all your problems
output = output.unindent # optional, escape it as you want, too
# rendering a partial is still possible,
# but i'd recommend using an absolute path :
render partial: 'my_html_bits/code_block',
locals: {title: title, lang: lang, text: output }
end
then you could do :
<%= code_block( 'example.html', 'html' ) do %>
<%# whatever code here will be captured %>
<p>Even plain old html.</p>
<% end %>
As a side note :
your #unindent method more or less mimicks an existing ActiveSupport monkey-patch on String, #strip_heredoc
in those cases, using #content_tag can also save you a lot of hassle, i.e :
<<%=tag%> class="squeeze" style=<%="#{style}"%>>
# more code...
could become :
<%= content_tag tag, class: 'squeeze', style: style do %>
# more code...

For the first x in array?

I imagine this has a rather simple answer
<% for user in #users %>
<li>
<%= link_to user.username, user %>
</li>
<% end %>
Taking my simple example above, how would I apply a class to my <li> to the first three instances returned?
Secondly, how could I just have the the second two items have a different class from the first one? as in 1..2
Either you could count manually (which is kinda ugly):
<% i = 0 %>
<% for user in #users %>
<li class=<%= (i < 3 ? "foo" : "bar") %>>
<%= link_to user.username, user %>
</li>
<% i = i.next %>
<% end %>
or use each_with_index
<% #users.each_with_index do |user, i| %>
<li class=<%= (i < 3 ? "foo" : "bar") %>>
<%= link_to user.username, user %>
</li>
<% end %>
Once you get to more complex things than i < 3 (like your 1..2 issue) you should think about a helper_method (in helpers) like class_by_position(pos) so that you can write
<li class=<%= class_by_position(i) %>>
The :first-child pseudoselector might be a better way to go, but you'll need to have a counter variable that keeps track of the iterations to do it your way.
Your question is a little vague. I can't tell if you want to stop processing the array after the first x, or not.
If you're just looking to stop after the first x items, or just looking for the 2nd and 3rd items the solution is to use a slice.
Example: just the first 3:
#user[0,3].each do |user|
... # only executed for user = #user[0],user = #user[1] and user = #user[3]
end
Example: just the second and third:
#user[1,2].each do |user|
... #only only executed for user = #user[1] and user = #user[3]
end
And here's a more specific answer to your question using these new concepts and the content_tag to programatically decide the class of the list item. If you're going to be doing this often, makes a great candidate for a function.
<% first = true %>
<% #user[0,2].each do |user| %>
<% content_tag :li,
:class => first ? "class-for-first-item" : "class-for-2nd-&-3rd" do %>
<%= link_to user.username, user %>
<% end %>
<% first = false %>
<% end %>
<!-- Now to do the rest of them:-->
<% #user[3,-1].each do |user| %>
<% content_tag :li, :class => "class-for-rest" do %>
<%= link_to user.username, user %>
<% end %>
<% end %>

Resources