Can't get pluralize/singularize working with ActiveSupport::Inflector (in irb) - ruby

irb(main):001:0> require 'active_support'
=> true
irb(main):002:0> require 'active_support/inflector/inflections'
=> true
irb(main):003:0> ActiveSupport::Inflector.pluralize('test')
=> "test"
irb(main):004:0> ActiveSupport::Inflector.singularize('tests')
=> "tests"
irb(main):005:0> ActiveSupport::Inflector.titleize('hat simulator')
=> "Hat Simulator"
<ort::Inflector.tableize("america's number one hat simulator")
=> "america's number one hat simulator"
Well, basically, that's the question. It's confusing me that methods such as titleize seem to work fine, but tableize, pluralize and singularize don't.
Have I forgotten to require something?
(On a separate note, I notice this page provides examples like "post".pluralize, which when I tried, resulted in NoMethodError: undefined method 'pluralize' for "post":String. But maybe that's something to save for another question.)

Access to #pluralize without adding new methods to the String class:
require 'active_support/inflector'
ActiveSupport::Inflector.pluralize('test')
#=> "tests"
For String class:
require 'active_support/core_ext/string'
"test".pluralize
#=> "tests"
which actually calls ActiveSupport::Inflector.pluralize underneath:
def pluralize
ActiveSupport::Inflector.pluralize(self)
end

Related

Ruby NameError: uninitialized constant

Just started with Ruby - and already stuck :)
I have a module like this:
module Simple
Env = AppEnv::Environment.new { |env, src|
env.test = src.test
}
class Application < Rails::Application
config.autoload_paths += [
"#{config.root}/app/lib/"
]
end
end
Then a class named simplex.rb in the folder /app/lib
class Simplex
def initialize(some)
puts(some)
end
end
Finally a rake task that looks like:
task(:simple => 'simple:default')
namespace(:simple) {
desc('Run simple, first task')
task(:default => :load) do
Simplex.new('okok')
end
}
However I keep getting the error: NameError: uninitialized constant Simplex
I would have thought the autoload_paths would allow Simplex to be found.
Any ideas what I'm doing wrong - seems really trival but I cant see what.
At the top of your Rake file try adding require "#{Rails.root}/lib/simplex" to bring in your Simplex class. Autoload works like this:
mylibrary.rb
puts "I was loaded!"
class MyLibrary
end
IRB
irb(main):001:0> require 'mylibrary'
I was loaded!
=> true
irb(main):001:0> autoload :MyLibrary, 'mylibrary'
=> nil
irb(main):002:0> MyLibrary.new
I was loaded!
=> #<MyLibrary:0x0b1jef>
I would highly recommend reading this article on what the difference between require and autoload is. More importantly, autoload is in the process of being deprecated because of pitfalls regarding it's lazy loading.

Achieving java enum like behaviour in ruby

Can I create something in my model to do something like:
MyModel::TYPE::ONE
MyModel::TYPE::TWO
where ONE and TWO are strings? I placed them in a constant in my model like:
class MyModel
TYPE = ['ONE', 'TWO']
end
so I can access MyModel::Type and get the array, but how do I get one more level?
You can get the syntax you desire with:
[~]$ irb
irb(main):001:0> module MyModel
irb(main):002:1> module TYPE
irb(main):003:2> ONE = 1
irb(main):004:2> TWO = 2
irb(main):005:2> end
irb(main):006:1> end
=> 2
irb(main):007:0> MyModel::TYPE::ONE
=> 1
irb(main):008:0> MyModel::TYPE::TWO
=> 2
This has the disadvantage, or maybe the advantage, of allowing extra "attributes" on the enum, not unlike what Java gives you. You can make the values of ONE and TWO be maps if you like, which is similar to Java's enum objects.
EDIT: You can also get the values like this:
irb(main):009:0> MyModel::TYPE::constants
=> [:ONE, :TWO]

How to write a Ruby UnitTest for a class- or module-level constant?

How does one write a test to verify a constant is present in a class or module?
Example:
module MyModule
VERSION = "0.3.1"
end
I tried
require 'test/unit'
require 'shoulda'
require "my_class"
class MyModuleTest < Test::Unit::TestCase
should "have a Version constant" do
# next two lines crash
assert_respond_to MyModule, :VERSION
assert_respond_to 'VERSION', MyModule
end
end
Would you consider to use Specular for more natural workflow, meant you can use any method that works in plain Ruby, thus you do not need to remember lot of extra unneeded stuff.
require 'specular'
module MyModule
VERSION = "0.3.1"
end
Spec.new do
check(MyModule).const_defined? :VERSION
end
puts Specular.run
# => check(MyModule).const_defined? :VERSION
# => - passed
# => Specs: 1
# => Tests: 0
# => Assertions: 1
So with plain Ruby you do: MyModule.const_defined? :VERSION
and with Specular: check(MyModule).const_defined? :VERSION
not really big difference thus nothing to learn/remember/recall again and again.

Storage of variables without initializing an object? Ruby Gem 'Mail'

Working with the Ruby Gem 'Mail', I am confused as to how variables are able to be stored without initializing an object? For example:
Mail.defaults do
retriever_method :pop3, :address => "pop.gmail.com",
:port => 995,
:user_name => '<username>',
:password => '<password>',
:enable_ssl => true
end
After which you are able to call methods such as Mail.first and have it return the first message in the mailbox with the configured defaults.
I realize everything in Ruby is an object, even a class, so when require 'mail' is called, does an object containing the the class Mail actually get created and mad available to the program? What exactly is happening here?
The contents of mail.rb are loaded into the file that has the require 'mail' statement.
After having a look in the gem, mail.rb contains the Mail module, which in turn contains many other require statements.
mail.rb
module Mail
## skipped for brevity
# Finally... require all the Mail.methods
require 'mail/mail'
end
mail/mail.rb
module Mail
## skipped for brevity
# Receive the first email(s) from the default retriever
# See Mail::Retriever for a complete documentation.
def self.first(*args, &block)
retriever_method.first(*args, &block)
end
end
So then the methods are made available to your program.

When is a Ruby class not that Ruby class?

I have this code in my controller for a Rails app:
def delete
object = model.datamapper_class.first(:sourced_id => params[:sourced_id])
if object.blank?
render :xml => "No #{resource} with sourced_id #{params[:sourced_id]}", :status => :not_found and return
end
object.destroy
render :xml => "", :status => :no_content
rescue MysqlError => e
puts "raised MysqlError #{e.message}"
render :xml => e.message, :status => :unprocessable_entity and return
rescue Mysql::Error => e
puts "raised Mysql::Error #{e.message}"
render :xml => e.message, :status => :unprocessable_entity and return
rescue Exception => e
puts "not a MysqlError, instead it was a #{e.class.name}"
render :xml => e.message, :status => :unprocessable_entity and return
end
When I run my spec to make sure my foreign key constraints work, I get this:
not a MysqlError, instead it was a MysqlError
What could be going on here?
Some ancestor information: When I change the rescue to give me this:
puts MysqlError.ancestors
puts "****"
puts Mysql::Error.ancestors
puts "****"
puts e.class.ancestors
This is what I get:
Mysql::Error
StandardError
Exception
ActiveSupport::Dependencies::Blamable ...
****
Mysql::Error
StandardError
Exception
ActiveSupport::Dependencies::Blamable ...
****
MysqlError
StandardError
Exception
ActiveSupport::Dependencies::Blamable ...
Could there be an alias in the global namespace that makes the MysqlError class unreachable?
Ruby classes are just objects, so comparison is based on object identity (ie, the same pointer under the hood).
Not sure what's happening in your case, but I'd try debugging in a few locations and seeing what object ids and ancestors you get for MysqlError. I suspect that there's two such objects in different modules and your catch clause is referencing the wrong one.
Edit:
That is quite strange. My guess now is that MysqlError or one of it's ancestors has been included at two different points along your controllers own class chain, and that's somehow tripping up the exception catching.
Theory #2 would be that since rails redefines const_missing to do auto-requires, where you'd expect to get an UndefinedConstant exception in the exception handling clauses is instead finding something by that name god knows where in the source tree. You should be able to see if that's the case by testing with the auto requiring off (ie do some debugs in both dev and prod mode).
There is a syntax for forcing your reference to start from the root which may be of some help if you can figure out the right one to be referencing:
::Foo::Bar
Rant:
This sort of thing is where I think some of the flaws of ruby show. Under the hood Ruby's object model and scoping is all object structures pointing to each other, in a way that's quite similar to javascript or other prototype based languages. But this is surfaced inconsistently in the class/module syntax you use in the language. It seems like with some careful refactoring you could make this stuff clearer as well as simplify the language, though this would of course be highly incompatible with existing code.
Tip:
When using puts for debugging, try doing puts foo.inspect as this will display it in the way you're used to from irb.
This was a simple class redefinition bug. Ruby lets you redefine a top-level constant, but it doesn't destroy the original constant when you do it. Objects that still hold references to that constant can still use it, so it could still be used to generate exceptions, like in the issue I was having.
Since my redefinition was happening in dependencies, I solved this by searching for the original class in the Object space, and hanging on to a reference to it to use when catching exceptions. I added this line to my controller:
ObjectSpace.each_object(Class){|k| ##mysql_error = k if k.name == 'MysqlError'}
That gets a reference to the original version of MysqlError. Then I was able to do this:
rescue ##mysql_error => e
render :xml => e.message, :status => :unprocessable_entity and return
This happens because the mysql gem is getting loaded after MysqlError has already been defined. Here is some test console joy:
Loading test environment (Rails 2.3.2)
>> MysqlError.object_id
=> 58446850
>> require 'mysql'
C:/Ruby/lib/ruby/gems/1.8/gems/mysql-2.7.3-x86-mswin32/ext/mysql.so: warning: already initialized constant MysqlError
=> true
>> MysqlError.object_id
=> 58886080
>> ObjectSpace._id2ref(MysqlError.object_id)
=> Mysql::Error
You can do this in IRB without a require pretty easily; here's a trick that works because irb doesn't look up Hash by name every time you declare a Hash literal:
irb(main):001:0> Hash = Class.new
(irb):1: warning: already initialized constant Hash
=> Hash
irb(main):002:0> hash = {:test => true}
=> {:test=>true}
irb(main):003:0> hash.class
=> Hash
irb(main):004:0> hash.is_a? Hash
=> false
I can see why you might want to do this, it could be used like alias_method_chain for the global namespace. You could add a mutex to a class that isn't threadsafe, for example, and not need to change old code to reference your threadsafe version. But I do wish RSpec hadn't silenced that warning.

Resources