Is there a pluralize function in Ruby NOT Rails? - ruby

I am writing some Ruby code, not Rails, and I need to handle something like this:
found 1 match
found 2 matches
I have Rails installed so maybe I might be able to add a require clause at the top of the script, but does anyone know of a RUBY method that pluralizes strings? Is there a class I can require that can deal with this if the script isn't Rails but I have Rails installed?
Edit: All of these answers were close but I checked off the one that got it working for me.
Try this method as a helper when writing Ruby, not Rails, code:
def pluralize(number, text)
return text.pluralize if number != 1
text
end

Actually all you need to do is
require 'active_support/inflector'
and that will extend the String type.
you can then do
"MyString".pluralize
which will return
"MyStrings"
for 2.3.5 try:
require 'rubygems'
require 'active_support/inflector'
should get it, if not try
sudo gem install activesupport
and then the requires.

Inflector is overkill for most situations.
def x(n, singular, plural=nil)
if n == 1
"1 #{singular}"
elsif plural
"#{n} #{plural}"
else
"#{n} #{singular}s"
end
end
Put this in common.rb, or wherever you like your general utility functions and...
require "common"
puts x(0, 'result') # 0 results
puts x(1, 'result') # 1 result
puts x(2, 'result') # 2 results
puts x(0, 'match', 'matches') # 0 matches
puts x(1, 'match', 'matches') # 1 match
puts x(2, 'match', 'matches') # 2 matches

I personally like the linguistics gem that is definitely not rails related.
# from it's frontpage
require 'linguistics'
Linguistics.use :en
"box".en.plural #=> "boxes"
"mouse".en.plural #=> "mice"
# etc

This works for me (using ruby 2.1.1 and actionpack 3.2.17):
~$ irb
>> require 'action_view'
=> true
>> include ActionView::Helpers::TextHelper
=> Object
>> pluralize(1, 'cat')
=> "1 cat"
>> pluralize(2, 'cat')
=> "2 cats"

require 'active_support'
require 'active_support/inflector'
inf = ActiveSupport::Inflector::Inflections.new
to get the inflector, not sure how you use it

my solution:
# Custom pluralize - will return text without the number as the default pluralize.
def cpluralize(number, text)
return text.pluralize if number != 1
return text.singularize if number == 1
end
So you can have 'review' returned if you call cpluralize(1, 'reviews')
Hope that helps.

I've defined a helper function for that, I use it for every user editable model's index view :
def ovyka_counter(array, name=nil, plural=nil)
name ||= array.first.class.human_name.downcase
pluralize(array.count, name, plural)
end
then you can call it from the view :
<% ovyka_counter #posts %>
for internationalization (i18n), you may then add this to your locale YAML files :
activerecord:
models:
post: "Conversation"

Related

ruby object to_s gives unexpected output

What is the correct way to view the output of the puts statements below? My apologies for such a simple question.... Im a little rusty on ruby. github repo
require 'active_support'
require 'active_support/core_ext'
require 'indicators'
my_data = Indicators::Data.new(Securities::Stock.new(:symbol => 'AAPL', :start_date => '2012-08-25', :end_date => '2012-08-30').output)
puts my_data.to_s #expected to see Open,High,Low,Close for AAPL
temp=my_data.calc(:type => :sma, :params => 3)
puts temp.to_s #expected to see an RSI value for each data point from the data above
Maybe check out the awesome_print gem.
It provides the .ai method which can be called on anything.
An example:
my_obj = { a: "b" }
my_obj_as_string = my_obj.ai
puts my_obj_as_string
# ... this will print
# {
# :a => "b"
# }
# except the result is colored.
You can shorten all this into a single step with ap(my_obj).
There's also a way to return objects as HTML. It's the my_obj.ai(html: true) option.
Just use .inspect method instead of .to_s if you want to see internal properties of objects.

ruby high use of memory, possibly leakage

I am using Ruby 1.9.3p0. The program that I wrote uses a lot of Memory when I run it for more than 4 hours. I am using the following gems:
require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'cgi'
require 'domainatrix'
This following code is run for more than 10.000 times, and I suspect it may cause a leak.
File.open('output.txt', 'a') do |file|
output.each_line do |item|
item = item.match(/^[^\s]+/)
item = item.to_s
if item = item.match(/[a-zA-Z0-9\-_]+\..+\.[a-zA-Z]+$/)
item = item.to_s
if item.length > 1
#puts "item: #{item}"
#item = item.to_s
item = Domainatrix.parse(item)
puts "subdomain: #{item.subdomain}"
if (item.domain == domain)
file.puts item.subdomain
puts item.subdomain
end
end
end
end
end
On the other hand, I am using a hash table to store every link.
What do you think may cause the Ruby to use a lot of memory?
UPDATE
Also I believe File.open should be closed after it is used. Is it true?
first don't require 'rubygems' not required in ruby 1.9.
you forgot to use ')' after if condition.
if (item.domain == domain
yes File.open closes the file.
It shall cause a syntax error before running.

Creating a thread-safe temporary file name

When using Tempfile Ruby is creating a file with a thread-safe and inter-process-safe name. I only need a file name in that way.
I was wondering if there is a more straight forward approach way than:
t = Tempfile.new(['fleischwurst', '.png'])
temp_path = t.path
t.close
t.unlink
Dir::Tmpname.create
You could use Dir::Tmpname.create. It figures out what temporary directory to use (unless you pass it a directory). It's a little ugly to use given that it expects a block:
require 'tmpdir'
# => true
Dir::Tmpname.create(['prefix-', '.ext']) {}
# => "/tmp/prefix-20190827-1-87n9iu.ext"
Dir::Tmpname.create(['prefix-', '.ext'], '/my/custom/directory') {}
# => "/my/custom/directory/prefix-20190827-1-11x2u0h.ext"
The block is there for code to test if the file exists and raise an Errno::EEXIST so that a new name can be generated with incrementing value appended on the end.
The Rails Solution
The solution implemented by Ruby on Rails is short and similar to the solution originally implemented in Ruby:
require 'tmpdir'
# => true
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-wyouwg-YOUR_SUFFIX"
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-140far-YOUR_SUFFIX"
Dir::Tmpname.make_tmpname (Ruby 2.5.0 and earlier)
Dir::Tmpname.make_tmpname was removed in Ruby 2.5.0. Prior to Ruby 2.4.4 it could accept a directory path as a prefix, but as of Ruby 2.4.4, directory separators are removed.
Digging in tempfile.rb you'll notice that Tempfile includes Dir::Tmpname. Inside you'll find make_tmpname which does what you ask for.
require 'tmpdir'
# => true
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname("prefix-", nil))
# => "/tmp/prefix-20190827-1-dfhvld"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], nil))
# => "/tmp/prefix-20190827-1-19zjck1.ext"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], "suffix"))
# => "/tmp/prefix-20190827-1-f5ipo7-suffix.ext"
Since Dir::Tmpname.make_tmpname was removed in Ruby 2.5.0, this one falls back to using SecureRandom:
require "tmpdir"
def generate_temp_filename(ext=".png")
filename = begin
Dir::Tmpname.make_tmpname(["x", ext], nil)
rescue NoMethodError
require "securerandom"
"#{SecureRandom.urlsafe_base64}#{ext}"
end
File.join(Dir.tmpdir, filename)
end
Since you only need the filename, what about using the SecureRandom for that:
require 'securerandom'
filename = "#{SecureRandom.hex(6)}.png" #=> "0f04dd94addf.png"
You can also use SecureRandom.alphanumeric
I found the Dir:Tmpname solution did not work for me. When evaluating this:
Dir::Tmpname.make_tmpname "/tmp/blob", nil
Under MRI Ruby 1.9.3p194 I get:
uninitialized constant Dir::Tmpname (NameError)
Under JRuby 1.7.5 (1.9.3p393) I get:
NameError: uninitialized constant Dir::Tmpname
You might try something like this:
def temp_name(file_name='', ext='', dir=nil)
id = Thread.current.hash * Time.now.to_i % 2**32
name = "%s%d.%s" % [file_name, id, ext]
dir ? File.join(dir, name) : name
end

Ruby+Anemone Web Crawler: regex to match URLs ending in a series of digits

Suppose I was trying crawl a website a skip a page that ended like so:
http://HIDDENWEBSITE.com/anonimize/index.php?page=press_and_news&subpage=20060117
I am currently using Anemone gem in Ruby to build the crawler. I am using the skip_links_like method but my pattern never seems to match. I am trying to make this as generic as possible so it isn't dependent on subpage but just =2105925 (the digits).
I have tried /=\d+$/ and /\?.*\d+$/ but it doesn't seem to be working.
This similar to Skipping web-pages with extension pdf, zip from crawling in Anemone but I can't make it worth with digits instead of extensions.
Also, testing on http://regexpal.com/ with the pattern =\d+$ will successfully match http://misc.com/test/index.php?page=news&subpage=20060118
EDIT:
Here is the entirety of my code. I wonder if anyone can see exactly what's wrong.
require 'anemone'
...
Anemone.crawl(url, :depth_limit => 3, :obey_robots_txt => true) do |anemone|
anemone.skip_links_like /\?.*\d+$/
anemone.on_every_page do |page|
pURL = page.url.to_s
puts "Now checking: " + pURL
bestGuess[pURL] = match_freq( manList, page.doc.inner_text )
puts "Successfully checked"
end
end
My output something like this:
...
Now checking: http://MISC.com/about_us/index.php?page=press_and_news&subpage=20110711
Successfully checked
...
Anemone.crawl(url, :depth_limit => 3, :obey_robots_txt => true, :skip_query_strings => true) do |anemone|
anemone.on_every_page do |page|
pURL = page.url.to_s
puts "Now checking: " + pURL
bestGuess[pURL] = match_freq( manList, page.doc.inner_text )
puts "Successfully checked"
end
end
Actually the /\?.*\d+$/ works:
~> irb
> all systems are go wirble/hirb/ap/show <
ruby-1.9.2-p180 :001 > "http://hiddenwebsite.com/anonimize/index.php?page=press_and_news&subpage=20060117".match /\?.*\d+$/
=> #<MatchData "?page=press_and_news&subpage=20060117">

Automatically Map JSON Objects into Instance Variables in Ruby

I would like to be able to automatically parse JSON objects into instance variables. For example, with this JSON.
require 'httparty'
json = HTTParty.get('http://api.dribbble.com/players/simplebits') #=> {"shots_count":150,"twitter_screen_name":"simplebits","avatar_url":"http://dribbble.com/system/users/1/avatars/thumb/dancederholm-peek.jpg?1261060245","name":"Dan Cederholm","created_at":"2009/07/07 21:51:22 -0400","location":"Salem, MA","following_count":391,"url":"http://dribbble.com/players/simplebits","draftees_count":104,"id":1,"drafted_by_player_id":null,"followers_count":2214}
I'd like to be able to do this:
json.shots_count
And have it output:
150
How could I possibly do this?
You should definitely use something like json["shots_counts"], but if you really need objectified hash, you could create a new class for this:
class ObjectifiedHash
def initialize hash
#data = hash.inject({}) do |data, (key,value)|
value = ObjectifiedHash.new value if value.kind_of? Hash
data[key.to_s] = value
data
end
end
def method_missing key
if #data.key? key.to_s
#data[key.to_s]
else
nil
end
end
end
After that, use it:
ojson = ObjectifiedHash.new(HTTParty.get('http://api.dribbble.com/players/simplebits'))
ojson.shots_counts # => 150
Well, getting what you want is hard, but getting close is easy:
require 'json'
json = JSON.parse(your_http_body)
puts json['shots_count']
Not exactly what you are looking for, but this will get you closer:
ruby-1.9.2-head > require 'rubygems'
=> false
ruby-1.9.2-head > require 'httparty'
=> true
ruby-1.9.2-head > json = HTTParty.get('http://api.dribbble.com/players/simplebits').parsed_response
=> {"shots_count"=>150, "twitter_screen_name"=>"simplebits", "avatar_url"=>"http://dribbble.com/system/users/1/avatars/thumb/dancederholm-peek.jpg?1261060245", "name"=>"Dan Cederholm", "created_at"=>"2009/07/07 21:51:22 -0400", "location"=>"Salem, MA", "following_count"=>391, "url"=>"http://dribbble.com/players/simplebits", "draftees_count"=>104, "id"=>1, "drafted_by_player_id"=>nil, "followers_count"=>2214}
ruby-1.9.2-head > puts json["shots_count"]
150
=> nil
Hope this helps!

Resources