Iterate through array using Map and Select method Together in Ruby - ruby-on-rails

I am developing an application where I'm stuck with the following code.
I have an array of links which is holding some links posted by a user in a form.
say for example my array is bunch1 = ["google.com","http://yahoo.com"]
Now, before I store them into database I need to make sure that each link has "http://" added at the beginning because I have 'validate:' logic in my ActiveRecord object.
So my logic is that I will iterate through the array and check if "http://" string segment present before each link in the array. So clearly I have to add "http://" string segment before "google.com" in my array.
So I have written a code like this:
bunch2=bunch1.map { |y| y="http://"+y }
But it creates a bunch2 array like bunch2=["http://google.com","http://http://yahoo.com"]
As you can see it adds an extra "http://" before "http://yahoo.com" .
To solve this problem I modified the above code like this:
bunch2 = bunch1.select { |x| x !~ /http/ }.map { |y| y="http://"+y }
but it's generating a array like
bunch2 = ["http://google.com"] because the regular expression with select method is eliminating the yahoo.com
Can somebody please give me solution for this problem. Thanks in advance...

Why not test in the call to map?
bunch2 = bunch1.map {|y| y !~ /^http/ ? "http://#{y}" : y }

Ok, guys I have found the solution to this problem. So the code don't need a select method at all. It just needs a ternary operator for this. So my one liner code goes like this:-
#bunch2=#bunch1.map { |x| x.match(/http:/) ? x : "http://"+x }
The above code using the match method for matching with regular expression. If it finds a match then the element is unchanged otherwise the "httP://" string is added at the beginning.

Related

Rails Plain Text Asset Extract String

Sorry, I am just learning how to use Rails.
I've got a simple .txt file asset which I would like to pull random Strings from to display on my landing page.
Is there an easy way in Rails to do this?
Assuming each string is in a separate line, you can do this:
strings = File.readlines('path/to/file.txt')
Then, to get a random string use sample, like this:
strings.sample
If you wan't more than one random string, just use sample with an argument, for example:
strings.sample(3)
This will return an array with 3 random lines from strings array.
Finally, you can do all in one line, for example, try this in the controller:
#string = File.readlines('path/to/file.txt').sample
And you will have #string available to use in the view.
So you are not giving me much. but I am going to assume that you want to get 1 line of a text file.
This is how I would do it
File.readlines("my/file/path.txt").sample
I hope that get you started :)

How to format a text area sent as an array via JSON?

I'm pretty new to Ruby, and I'm using it work with an API. Text area's sent over the API are converted to the format below before being sent to me via a JSON POST request:
"Comment": [
"hdfdhgdfgdfg\r",
"This is just a test\r",
"Thanks!\r",
"- Kyle"
]
And I'm getting the value like this:
comments = params["Comment"]
So each line is broken down into what looks like an array. My issue is, it functions just like one big string instead of an array with 4 values. I tried using comments[0] and just printing comments but both return the same result, it just displays everything as a string, ie
["hdfdhgdfgdfg\r", "This is just a test\r", "Thanks!\r", "- Kyle"]
But I need to display it as it appears in the text area, ie
hdfdhgdfgdfg
This is just a test
Thanks!
- Kyle
I know I could just strip out all the extra characters, but I feel like there has to be a better way. Is there a good way to convert this back to the original format of a text area, or at least to convert it to an array so I can loop through each item and re-format it?
First, get rid of those ugly \rs:
comments.map!(&:chomp)
Then, join the lines together:
comment = comments.join("\n") # using a newline
# OR, for HTML output:
comment = comments.join('<br>')
You should be able to parse the JSON and populate a hash with all of the values:
require 'json'
hash = JSON.parse(params["Comment"])
puts hash
=> {"Comment"=>['all', 'of', 'your', 'values']}
This should work for all valid json. One of the rules of json syntax is that
Data is in name/value pairs
The json you provided doesn't supply names for the values, therefore this method might not work. If this is the case, parsing the raw string and extracting values would do the job as well (although more messy).
How you might go about doing that:
json = params["Comment"]
newArray = []
json.split(" ").each do |element|
if element.length > 1
newArray << element
end
end
This would at least give you an array with all of your values.

How to output html_safe within <%=%> block while concatenating strings?

Consider this:
<%
str = "http://domain.com/?foo=1&bar=2"
%>
Now these cases:
<%=str%>
# output:http://domain.com/?foo=1&bar=2
<%=str.html_safe%>
# output:http://domain.com/?foo=1&bar=2
<%="#{str.html_safe}"%>
# output:http://domain.com/?foo=1&bar=2
<%=""+str.html_safe%>
# output:http://domain.com/?foo=1&bar=2
I need to output the URL with other strings. How can I guarantee that the ampersand will be unescaped? For reasons beyond my control I can't send &.
Please help! Pulling my hair here :\
EDIT: To clarify, I actually have an array like so:
#images = [{:id=>"fooid",:url=>"http://domain.com/?foo=1&bar=2"},...]
I am creating a JS array (the image_array var) to use in my app this way:
image_array.push(<%=#images.map{|x|"{id:'#{x[:id]}',url:'#{x[:url].html_safe}'}"}.join(",")%>);
This generates:
image_array.push({id:'fooid',url:'http://domain.com/?foo=1&bar=2'},...);
Which does not work in my specific case. I need the url without the amp; part.
When you write:
"#{foo.bar}"
this is ~equivalent to writing
foo.bar.to_s
So what you are actually doing is:
<%=str.html_safe.to_s%>
…which Rails no longer sees as being safe, and so it hits your resulting string with a round of HTML escaping.
I don't know the internals of Rails, but I assume that the html_safe method extends the string object with an instance variable flagging it as OK, but when you wrap that in another string via interpolation you are getting a new string without that flag.
Edit: To answer your needs, use raw or call html_safe on your final string:
<%=raw "foo#{str}"%>
<%="foo#{str}".html_safe%>
or in your case:
image_array.push(<%=raw #images.map{…}.join(',')%>);
image_array.push(<%=#images.map{…}.join(',').html_safe%>);
See also this question.
Use this
<%=str.html_safe.to_s%>
or
<%=raw(str)%>
give you better results
image_array.push(<%= #images.map{|x| "{id:'#{x[:id]}',url:'#{x[:url]}'}".html_safe }.join(",") %>);
what you would do to be safe is:
image_array.push(<%= #images.map { |image| image.as_json(only: [:id, :url]) }.to_json } %>)
this will escape the <, >, etc. properly like this:
[{"name":"\u003ch1\u003eAAAA\u003c/h1\u003e"}]
and for people coming here like me who want to concatenate strings, it's just not safe to do it, the best way is to concatenate tags, e.g.
content_tag(:p) do
content_tag(:span, "<script>alert(1)</script>") +
link_to("show", user)
end
will work fine and properly escape the first string

How to get regex to ignore URL strings?

I have the following Regexp to create a hash of values by separating a string at a semicolon:
Hash["photo:chase jarvis".scan(/(.*)\:(.*)/)]
// {'photo' => 'chase jarvis'}
But I also want to be able to have URL's in the string and recognize it so it maintains the URL part in the value side of the hash i.e:
Hash["photo:http://www.chasejarvis.com".scan(/(.*)\:(.*)/)]
// Results in {'photo:http' => '//www.chasejarvis.com'}
I want, of course:
Hash["photo:chase jarvis".scan(/ ... /)]
// {'photo' => 'http://www.chasejarvis.com'}
If you only want to match up to first colon you could change (.*)\:(.*) to ([^:]*)\:(.*).
Alternatively, you could make it a non-greedy match, but I prefer saying "not colon".
How do figure out a person's family name and first name?
Changing chasejarvis to chase and jarvis might not be possible unless you have a solution for that.
Do you already know everyone's name in your project? Nobody is having the initial of a middle name like charvisdjarvis (assuming the name is "Charvis D. Jarvis".)?

I am creating a Twitter clone in Ruby On Rails, how do I code it so that the '#...''s in the 'tweets' turn into links?

I am somewhat of a Rails newbie so bear with me, I have most of the application figured out except for this one part.
def linkup_mentions_and_hashtags(text)
text.gsub!(/#([\w]+)(\W)?/, '#\1\2')
text.gsub!(/#([\w]+)(\W)?/, '#\1\2')
text
end
I found this example here: http://github.com/jnunemaker/twitter-app
The link to the helper method: http://github.com/jnunemaker/twitter-app/blob/master/app/helpers/statuses_helper.rb
Perhaps you could use Regular Expressions to look for "#..." and then replace the matches with the corresponding link?
You could use a regular expression to search for #sometext{whitespace_or_endofstring}
You can use regular expressions, i don't know ruby but the code should be almost exactly as my example:
Regex.Replace("this is an example #AlbertEin",
"(?<type>[##])(?<nick>\\w{1,}[^ ])",
"${type}${nick}");
This example would return
this is an example <a href="http://twitter.com/AlbertEin>#AlbertEin</a>
If you run it on .NET
The regex (?<type>[##])(?<nick>\\w{1,}[^ ]) means, capture and name it TYPE the text that starts with # or #, and then capture and name it NAME the text that follows that contains at least one text character until you fin a white space.
Perhaps you can use a regular expression to parse out the words starting with #, then update the string at that location with the proper link.
This regular expression will give you words starting with # symbols, but you might have to tweak it:
\#[\S]+\
You would use a regular expression to search for #username and then turn that to the corresponding link.
I use the following for the # in PHP:
$ret = preg_replace("#(^|[\n ])#([^ \"\t\n\r<]*)#ise",
"'\\1<a href=\"http://www.twitter.com/\\2\" >#\\2</a>'",
$ret);
I've also been working on this, I'm not sure that it's 100% perfect, but it seems to work:
def auto_link_twitter(txt, options = {:target => "_blank"})
txt.scan(/(^|\W|\s+)(#|#)(\w{1,25})/).each do |match|
if match[1] == "#"
txt.gsub!(/##{match.last}/, link_to("##{match.last}", "http://twitter.com/search/?q=##{match.last}", options))
elsif match[1] == "#"
txt.gsub!(/##{match.last}/, link_to("##{match.last}", "http://twitter.com/#{match.last}", options))
end
end
txt
end
I pieced it together with some google searching and some reading up on String.scan in the api docs.

Resources