Rails application with regular expression validation - ruby-on-rails

I have created an application like users app using rails. In this app, the text file is imported to DB. In which, i need to validate the mobile number, that means, it should not contains + or * or any other special characters, suppose if it presence it should neglect this special characters and print the rest. I have used the following code to store the text file in array.
File.open('text file') do |f|
while line = f.gets
array = line.split(',')
user = User.new
user.user_name = array[0]
user.email_id = array[1]
user.mobile_number = array[2]
user.save
end

Use global substitute using regex, to remove the non-number part.
user.mobile_number = array[2].gsub(/[^0-9]/,'')

Related

Simpler Way to Add a new Field to Object in Rails

I have a field in animal_food (a json object) called treats and I want to add a field in treats called time_eaten and then return everything from the field treats.
def addTime(time)
animal_food["treats"]["time_eaten"] = time
animal_food["treats"]
end
Is there a way I can do the code above in 1 line (using merge or other ruby syntax?)
Yes:
animal_food['treats'].merge!({'time_eaten' => time})
does the same thing as those two lines. (Note the exclamation mark.) You could also say
animal_food['treats'].tap { |treats| treats['time_eaten'] = time }
Or, in Ruby 2.7 preview, using numbered parameters:
animal_food['treats'].tap { #1['time_eaten'] = time }

Cleaning scraped <a href> rails

I have scraped data from a website and entered it into an array using the code below:
def process_course_details(course_details)
details_array =[]
details_link = true
entry_link = true
details_info = {}
# Sets all data in hash
details_info[:url] = clean_link(course_details.search('div.coursedetails_programmeurl a'))
details_array.push(details_info)
print_details_info(details_info)
entry_link = course_details.search('ul.details_tabs').first
end
The code above stores the element being pulled as such:
View course details on provider's website
But I'd like to clean the above to the below:
http://www.abdn.ac.uk/study/courses/undergraduate/C8R1/
or failing that remove the apostrophe and have this:
View course details on providers website`
You can extract the href with Nokogiri like this:
html = Nokogiri::HTML('View course details on provider\'s website')
html.xpath("//a/#href").to_s # => "http://www.abdn.ac.uk/study/courses/undergraduate/C8R1/"
Based on your comment:
When storing other data I've scraped into the database the apostrophe
provided errors and stopped it. Once I had cleaned the apostrophe and
it no longer was part of the array the code worked and the table was
created.
db = SQLite3::Database.open('ahhh.sqlite3')
db.execute "INSERT INTO aahah (uname, cname, duration, qualification, url, entry) VALUES ('#{#uni_name}', #{#course_name}', '#{#course_duration}', '#{#course_qual}', '#{#details_entry}', '#{#requirements}')"
You are inserting the values via string interpolation:
db.execute("INSERT INTO table_name (foo, bar) VALUES ('#{#foo}', '#{#bar}')")
Apparently, if the interpolated strings contain an apostrophe, your SQL string likely becomes invalid. Even worse, this code is prone to SQL injection.
Instead you should use parameter markers and let the SQLite gem handle the escaping:
db.execute("INSERT INTO table_name (foo, bar) VALUES (?, ?)", [#foo, #bar])
This allows you to safely insert apostrophe and other special characters.

Extract params values from link, Rails 4

I have link like this:
http://localhost:3000/sms/receive/sms-id=7bb28e244189f2cf36cbebb9d1d4d02001da53ab&operator-%20id=1&from=37126300682&to=371144&text=RV9+c+Dace+Reituma+0580913
I want to extract all diferent variable values from this link. For example sms-id,operator,from, to and text.
So far I have like this:
routes.rb
get 'sms/receive/:params', to: 'sms#receive'
SMS#RECEIVE controller
def receive
query = params[:params]
sms_id= query[/["="].+?[&]/]
flash[:notice] = sms_id
end
This gives me : =7bb28e244189f2cf36cbebb9d1d4d02001da53ab& but I need without the first = and last characher & .
If I try to add strings like :query[/["sms-id"].+?[&operator]/] that could allow me to extract all variables smoothly, it gives me error : empty range in char class: /["sms-id"].+?[&operator]/
But I believe there is other way to extract all these variable values in different way?
Thanks in advance!
The error in your regular expression is because the - is a reserved character when in-between square brackets. In this context, it must be escaped with a backslash: \-.
To parse your query string, you can do this:
sms_id = params[:params].match(/sms-id=([^&]*)/)[1]
or parse it with the more generic method:
parsed_query = Rack::Utils.parse_nested_query(params[:params])
sms_id = parsed_query['sms-id']
(quoted from this answer)
If you have control over the initial URL, change the last / for a ? for an even easier solution:
http://localhost:3000/sms/receive?sms-id=7bb28e244189f2cf36cbebb9d1d4d02001da53ab&operator-%20id=1&from=37126300682&to=371144&text=RV9+c+Dace+Reituma+0580913
and you will have sms-id in params:
sms_id = params['sms-id']
You need
get 'sms/receive/', to: 'sms#receive'
path in routes.rb and get params in the controller
Try this
matches = params[:params].scan(/(?:=)([\w\+]+)(?:\&)?/)
# this will make matches = [[first_match], [second_match], ..., [nth_match]]
# now you can read all matches
sms_id = matches[0][0]
operator_id = matches[1][0]
from = matches[2][0]
to = matches[3][0]
text = matches[4][0]
# and it will not contatin = or &
I suggest for you to make method in model or helper, and not to write whole code in controller.

Ruby, gsub and regex

Quick background: I have a string which contains references to other pages. The pages are linked to using the format: "#12". A hash followed by the ID of the page.
Say I have the following string:
str = 'This string links to the pages #12 and #125'
I already know the IDs of the pages that need linking:
page_ids = str.scan(/#(\d*)/).flatten
=> [12, 125]
How can I loop through the page ids and link the #12 and #125 to their respective pages? The problem I've run into is if I do the following (in rails):
page_ids.each do |id|
str = str.gsub(/##{id}/, link_to("##{id}", page_path(id))
end
This works fine for #12 but it links the "12" part of #125 to the page with ID of 12.
Any help would be awesome.
Instead of extracting the ids first and then replacing them, you can simply find and replace them in one go:
str = str.gsub(/#(\d*)/) { link_to("##{$1}", page_path($1)) }
Even if you can't leave out the extraction step because you need the ids somewhere else as well, this should be much faster, since it doesn't have to go through the entire string for each id.
PS: If str isn't referred to from anywhere else, you can use str.gsub! instead of str = str.gsub
if your indexes always end at word boundaries, you can match that:
page_ids.each do |id|
str = str.gsub(/##{id}\b/, link_to("##{id}", page_path(id))
end
you only need to add the word boundary symbol \b on the search pattern, it is not necessary for the replacement pattern.

Truncate Markdown?

I have a Rails site, where the content is written in markdown. I wish to display a snippet of each, with a "Read more.." link.
How do I go about this? Simple truncating the raw text will not work, for example..
>> "This is an [example](http://example.com)"[0..25]
=> "This is an [example](http:"
Ideally I want to allow the author to (optionally) insert a marker to specify what to use as the "snippet", if not it would take 250 words, and append "..." - for example..
This article is an example of something or other.
This segment will be used as the snippet on the index page.
^^^^^^^^^^^^^^^
This text will be visible once clicking the "Read more.." link
The marker could be thought of like an EOF marker (which can be ignored when displaying the full document)
I am using maruku for the Markdown processing (RedCloth is very biased towards Textile, BlueCloth is extremely buggy, and I wanted a native-Ruby parser which ruled out peg-markdown and RDiscount)
Alternatively (since the Markdown is translated to HTML anyway) truncating the HTML correctly would be an option - although it would be preferable to not markdown() the entire document, just to get the first few lines.
So, the options I can think of are (in order of preference)..
Add a "truncate" option to the maruku parser, which will only parse the first x words, or till the "excerpt" marker.
Write/find a parser-agnostic Markdown truncate'r
Write/find an intelligent HTML truncating function
Write/find an intelligent HTML truncating function
The following from http://mikeburnscoder.wordpress.com/2006/11/11/truncating-html-in-ruby/, with some modifications will correctly truncate HTML, and easily allow appending a string before the closing tags.
>> puts "<p><b>Something</p>".truncate_html(5, at_end = "...")
=> <p><b>Someth...</b></p>
The modified code:
require 'rexml/parsers/pullparser'
class String
def truncate_html(len = 30, at_end = nil)
p = REXML::Parsers::PullParser.new(self)
tags = []
new_len = len
results = ''
while p.has_next? && new_len > 0
p_e = p.pull
case p_e.event_type
when :start_element
tags.push p_e[0]
results << "<#{tags.last}#{attrs_to_s(p_e[1])}>"
when :end_element
results << "</#{tags.pop}>"
when :text
results << p_e[0][0..new_len]
new_len -= p_e[0].length
else
results << "<!-- #{p_e.inspect} -->"
end
end
if at_end
results << "..."
end
tags.reverse.each do |tag|
results << "</#{tag}>"
end
results
end
private
def attrs_to_s(attrs)
if attrs.empty?
''
else
' ' + attrs.to_a.map { |attr| %{#{attr[0]}="#{attr[1]}"} }.join(' ')
end
end
end
Here's a solution that works for me with Textile.
Convert it to HTML
Truncate it.
Remove any HTML tags that got cut in half with
html_string.gsub(/<[^>]*$/, "")
Then, uses Hpricot to clean it up and close unclosed tags
html_string = Hpricot( html_string ).to_s
I do this in a helper, and with caching there's no performance issue.
You could use a regular expression to find a line consisting of nothing but "^" characters:
markdown_string = <<-eos
This article is an example of something or other.
This segment will be used as the snippet on the index page.
^^^^^^^^^^^^^^^
This text will be visible once clicking the "Read more.." link
eos
preview = markdown_string[0...(markdown_string =~ /^\^+$/)]
puts preview
Rather than trying to truncate the text, why not have 2 input boxes, one for the "opening blurb" and one for the main "guts". That way your authors will know exactly what is being show when without having to rely on some sort of funkly EOF marker.
I will have to agree with the "two inputs" approach, and the content writer would need not to worry, since you can modify the background logic to mix the two inputs in one when showing the full content.
full_content = input1 + input2 // perhaps with some complementary html, for a better formatting
Not sure if it applies to this case, but adding the solution below for the sake of completeness. You can use strip_tags method if you are truncating Markdown-rendered contents:
truncate(strip_tags(markdown(article.contents)), length: 50)
Sourced from:
http://devblog.boonecommunitynetwork.com/rails-and-markdown/
A simpler option that just works:
truncate(markdown(item.description), length: 100, escape: false)

Resources