Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How can I avoid this boring code?

1 view
Skip to first unread message

Sam Kong

unread,
Nov 1, 2005, 9:12:58 PM11/1/05
to
Hi!

I'm creating a class.
I wonder if there's a better way.

require 'dbi'

class Person
attr_accessor :person_id,
:last_name,
:first_name,
:home_phone,
:work_phone,
:address,
:city,
:state,
:zip

def initialize(row=nil)
if row.class == DBI::Row then
@person_id = row.by_field("person_id")
@last_name = row.by_field("last_name")
@first_name = row.by_field("first_name")
@home_phone = row.by_field("home_phone")
@work_phone = row.by_field("work_phone")
@address = row.by_field("address")
@city = row.by_field("city")
@state = row.by_field("state")
@zip = row.by_field("zip")
end
end
end

The code in initialize method is very boring.
How could I make it simpler?

Thanks in advance.

Sam

Marcel Molina Jr.

unread,
Nov 1, 2005, 9:24:16 PM11/1/05
to

You could use Active Record.

class Person < ActiveRecord::Base
end

>> some_person = Person.new
>> some_person.last_name = 'Kong'
>> some_person.save

etc

Though ActiveRecord is known for being a component of Rails, it can be used
entirely discreetly from Rails.

e.g.

require 'active_record'

ActiveRecord::Base.establish_connection(:adapter => 'sqlite', :database => ':memory:')

class Person < Active::Record::Base
end

All set.

marcel
--
Marcel Molina Jr. <mar...@vernix.org>


nobuyoshi nakada

unread,
Nov 1, 2005, 9:42:23 PM11/1/05
to
Hi,

At Wed, 2 Nov 2005 11:17:08 +0900,
Sam Kong wrote in [ruby-talk:163688]:
> require 'dbi'
>
Person = Struct.new(:person_id, :last_name, :first_name,
:home_phone, :work_phone,
:address, :city, :state, :zip)

class Person
def self.load_fields(row)
members.collect {|n| row.by_field(n)}
end

# may be preferable.
def self.load(row)
new(*load_fields(row))
end

def initialize(*args)
if args.size == 1 and DBI::Row === (row = args[0])
args = self.class.load_fields(row)
end
super(*args)
end
end

I'm uncertain if DBI may have more convenient method.

--
Nobu Nakada


Daniel Sheppard

unread,
Nov 1, 2005, 9:49:01 PM11/1/05
to
You could do:

class Person
FIELDS = :person_id, :last_name, :first_name, :home_phone,


:work_phone, :address, :city, :state, :zip

attr_accessor *FIELDS
def initialize(row=nil)
FIELDS.each { |f| instance_variable_set("@#{f}",
row.by_field(f.to_s)) } if row == DBI::Row
end
end

(though I'd advise against using the row == DBI::ROW - use
row.respond_to?(:by_field) instead, otherwise you'll probably have fun
when it comes time to unit tests...).

or if you want to make it a general case:

class DatabaseObject
def self.db_field(*args)
attr_accessor(*args)
(@__db_fields||[]).concat(args)
end
def self.db_fields
(@__db_fields||[]) + superclass.db_fields if
superclass.respond_to?(:db_fields)
end
def initialize(row=nil)
self.class.db_fields.each { |f| instance_variable_set("@#{f}",
row.by_field(f.to_s)) } if row.respond_to?(:by_field)
end
end

class Person < DatabaseObject
db_field :person_id, :last_name, :first_name, :home_phone,


:work_phone, :address, :city, :state, :zip

end

Which is pretty much what you'll get from any of the ORM libraries,
though they'll usually get the list of fields by querying the database,
so you don't even have to do that in your code.

(all code is untested - that's your job).

> -----Original Message-----
> From: Sam Kong [mailto:sam.s...@gmail.com]
> Sent: Wednesday, 2 November 2005 1:17 PM
> To: ruby-talk ML
> Subject: How can I avoid this boring code?
>
> Hi!


>
> I'm creating a class.
> I wonder if there's a better way.
>
> require 'dbi'
>
> class Person

> attr_accessor :person_id,


> :last_name,
> :first_name,
> :home_phone,
> :work_phone,
> :address,
> :city,
> :state,

> :zip
>
> def initialize(row=nil)
> if row.class == DBI::Row then
> @person_id = row.by_field("person_id")
> @last_name = row.by_field("last_name")
> @first_name = row.by_field("first_name")
> @home_phone = row.by_field("home_phone")
> @work_phone = row.by_field("work_phone")
> @address = row.by_field("address")
> @city = row.by_field("city")
> @state = row.by_field("state")
> @zip = row.by_field("zip")
> end
> end
> end
>
> The code in initialize method is very boring.
> How could I make it simpler?
>

> Thanks in advance.
>
> Sam
>
>
>
>
#####################################################################################
This email has been scanned by MailMarshal, an email content filter.
#####################################################################################


Ara.T.Howard

unread,
Nov 1, 2005, 9:44:20 PM11/1/05
to

class Person
FIELDS = %w(
person_id last_name first_name home_phone work_phone address city state zip
)
def initialize r = nil
FIELDS.each{|f| send "#{ f }=", r.by_field(f)} if row.class == DBI::Row
end
end

if the Person class can dynamically set FIELDS by inspecting a table - so much
the better.

hth.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| anything that contradicts experience and logic should be abandoned.
| -- h.h. the 14th dalai lama
===============================================================================

gabriele renzi

unread,
Nov 2, 2005, 5:10:08 AM11/2/05
to
Sam Kong ha scritto:

I think I'd do the initialize method like this:
def initialize(row=nil)
if row.is_A? DBI::Row
row.each_with_name do |value,name|
send name.to_s+"=", value
end
end
end

And I'd make Person a Struct to get getters/setters for free.

Trans

unread,
Nov 2, 2005, 7:42:20 AM11/2/05
to
Doesn't a DBI::Row respond to #to_h? If not teach it and be sure to
add:

class Hash
def to_h
self
end
end

You can define an attr method


module AttrDBI
def attr_dbi( *args )
@dbi_fields |= args
attr_accessor( *args )
end

def dbi_fields
@dbi_fields
end
end

class Person
extend AttrDBI

attr_dbi :person_id,
:last_name
...

def initialize(row)
row = row.to_h
self.class.dbi_fields.each {|f| send("#{f}=", row[f] }
end

T.

0 new messages