Search objects

I can use some help here:

I’ve set up this class and objects and would like to “search” it
similar to the way I would search a database. At this point I’m not
concerned with adding regex for more liberal searches.
Any suggestions ?

class Composer
def initialize( lname, country )
@lname = lname
@country = country
end
attr_accessor(:lname, :country)
end

comp1 = Composer.new(“Beethoven”, “Germany”)
comp2 = Composer.new(“DeFalla”, “Spain”)
comp3 = Composer.new(“Debussy”, “France”)

I’m assuming that you are just implementing this for its educational
value and not seriously considering implementing a data base with
this approach. Ruby has built-in and third-party libraries to help
you implement a data bases application.

I’ve modified your posting just enough to make a shallow scratch on
the surface of what can be done to organize and search data. I hope
it’s enough to help you along. Although you said you didn’t want to
consider regular expressions yet, I use them because it makes life
much simpler to use at least simple regexes.

#! /usr/bin/ruby -w

class Composer

@@composers = []

def Composer.find(attrib, regex)
   @@composers.select do |c|
      c.respond_to?(attrib) &&
      c.send(attrib) =~ regex
   end
end

def initialize( lname, country )
    @lname    = lname
    @country  = country
    @@composers << self
end

attr_accessor :lname, :country
alias :to_s :inspect

end

Composer.new(“Beethoven”, “Germany”)
Composer.new(“DeFalla”, “Spain”)
Composer.new(“Debussy”, “France”)
Composer.new(“Bach”, “Germany”)
Composer.new(“Rodrigo”, “Spain”)
Composer.new(“Ravel”, “France”)

puts Composer.find(:country, /^Ger/)
puts Composer.find(:lname, /^R/)

=>

#<Composer:0x24a18 @country=“Germany”, @lname=“Beethoven”>

#<Composer:0x24964 @country=“Germany”, @lname=“Bach”>

#<Composer:0x24928 @country=“Spain”, @lname=“Rodrigo”>

#<Composer:0x248ec @country=“France”, @lname=“Ravel”>

Regards, Morton

Well a few things. For some reason, in the past I’ve attempted to use
‘find’ in Ruby and irb has sent back a nomethod error. So perhaps t
was syntax errors (though I don’t believe it was) not sure. I’m about
to run out so I’ll check it in a while.

And yes, this is for educational purposes though I think I may have
not seen some options. Particularly the ability in Rails to play with
models and controllers in the console. I know this is not the Rails
list and I’ve gone ahead posted my errors while attempting to load the
console using the NAME or DESCRIPTION option.

Stuart

On Aug 13, 2006, at 12:54 PM, Dark A. wrote:

def initialize( lname, country )
@lname = lname
@country = country
end
attr_accessor(:lname, :country)
end

comp1 = Composer.new(“Beethoven”, “Germany”)
comp2 = Composer.new(“DeFalla”, “Spain”)
comp3 = Composer.new(“Debussy”, “France”)

Well, if we had those composers in an Array, we could use normal
iterators like:

composers.find { |c| c.country == “Germany” }

and:

composers.select { |c| c.lname =~ /^De/ }

Hope that gives you some fresh ideas.

James Edward G. II

On Mon, 14 Aug 2006, Dark A. wrote:

  @country  = country

end
attr_accessor(:lname, :country)
end

comp1 = Composer.new(“Beethoven”, “Germany”)
comp2 = Composer.new(“DeFalla”, “Spain”)
comp3 = Composer.new(“Debussy”, “France”)

harp:~ > cat a.rb
require ‘weakref’

class Composer
(ATTRIBUTES = %w( lname country )).each{|a| attr_accessor a}

INDEX = Hash.new{|h,k| h[k] = []}

def self.find arg
pattern =
case arg
when Hash
ATTRIBUTES.map{|a| arg[a] || arg[a.to_s] ||
arg[a.to_s.intern]}
when Array
arg
else
raise ArgumentError
end

 n = pattern.size

 keys = INDEX.keys.select do |key|
   match = []
   n.times do |i|
     pat, k = pattern[i], key[i]
     match <<
       if pat.nil?
         true
       elsif pat.respond_to? 'call'
         pat.call(k) ? true : false
       elsif pat.respond_to? '==='
         pat === k
       elsif pat.respond_to? '=='
         pat == k
       else
         false
       end
   end
   match.all?
 end

 INDEX.values_at(*keys).map{|list| list.map{|weakref| 

weakref.getobj}}.flatten
end

def initialize *argv
ATTRIBUTES.each{|a| send “#{ a }=”, argv.shift}
key = ATTRIBUTES.map{|a| send a}
val = WeakRef.new self
INDEX[key] << val
end

def to_hash
ATTRIBUTES.inject({}){|h,k| h.update k => send(k)}
end

def inspect
to_hash.inspect
end

def to_s
inspect
end
end

comp1 = Composer.new “Beethoven”, “Germany”
comp2 = Composer.new “DeFalla”, “Spain”
comp3 = Composer.new “Debussy”, “France”

found = Composer.find ‘lname’ => ‘Beethoven’
p found

found = Composer.find ‘lname’ => %r/^bee|^defal/io
p found

found = Composer.find :country => lambda{|c| c.upcase === ‘SPAIN’}
p found

class CaseOf < ::Array
def ===(other) flatten.compact.map{|pat| pat === other}.any? end
end
def caseof(*a, &b) CaseOf.new(*a, &b) end

found = Composer.find :lname => %r/y$/, :country => caseof(%w[ Spain
France ])
p found

harp:~ > ruby a.rb
[{“country”=>“Germany”, “lname”=>“Beethoven”}]
[{“country”=>“Germany”, “lname”=>“Beethoven”}, {“country”=>“Spain”,
“lname”=>“DeFalla”}]
[{“country”=>“Spain”, “lname”=>“DeFalla”}]
[{“country”=>“France”, “lname”=>“Debussy”}]

food for thought.

-a

That’s a lot of food :slight_smile:

Stuart