[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Application Design

daywalk

6/17/2006 3:20:00 AM

Hey,

I have a system that I am trying to design, it contains news articles,
events, etc... There is model representing articles, one representing
events, etc...

Articles or events can be active or inactive, so I can do a query to
return all active articles, all articles or all inactive articles.

The question that I have is what would be the best way to design this.
Right now I have each method (such as recent articles, featured
articles, etc...) taking an 'active' parameter. This requires littering
the code with method calls taking this parameter.

I have also thought about setting a class variable on the models to set
whether active/inactive/all articles are returned, so that anytime you
want to set the type returned you set this class variable and then call
your functions (recent_articles, etc...).

What I would like to know is if there are any suggestions as to a good
practice to follow in how to implement this functionality, one of the
ways I have stated or some other way that I haven't considered.

I hope I have been clear. Thanks for the help in advance.

P.S. The application is done in ruby on rails.

4 Answers

Robert Klemme

6/17/2006 8:57:00 AM

0

daywalk@gmail.com wrote:
> Hey,
>
> I have a system that I am trying to design, it contains news articles,
> events, etc... There is model representing articles, one representing
> events, etc...
>
> Articles or events can be active or inactive, so I can do a query to
> return all active articles, all articles or all inactive articles.
>
> The question that I have is what would be the best way to design this.
> Right now I have each method (such as recent articles, featured
> articles, etc...) taking an 'active' parameter. This requires littering
> the code with method calls taking this parameter.

It's not fully clear to me where these methods reside. Do you have a
central repository class that will yield records as per request? If
it's a general query thing then having a hash as argument may be an
option, too. The hash then would contain mappings from fields to
required values. But read on.

> I have also thought about setting a class variable on the models to set
> whether active/inactive/all articles are returned, so that anytime you
> want to set the type returned you set this class variable and then call
> your functions (recent_articles, etc...).

Don't do that. There are several disadvantages:

- it's not concurrency safe

- behavior of methods is not obvious, i.e. it's controlled by some
hidden flag

- it's more error prone (if you forget to set the flag than the method
will yield the wrong result) than with a parameter

Basically a search criterion belongs to the execution of the query and
not into a class var which is more static.

> What I would like to know is if there are any suggestions as to a good
> practice to follow in how to implement this functionality, one of the
> ways I have stated or some other way that I haven't considered.
>
> I hope I have been clear. Thanks for the help in advance.
>
> P.S. The application is done in ruby on rails.

I'm not familiar with ActiveRecord but I believe that it is possible to
have the flag stored with ever item (article, event...) - which is where
it belongs anyway - and then query the DB with a criterion (i.e. active
== true or false). This seems the most natural thing to do.

Kind regards

robert

zycte

6/17/2006 11:37:00 AM

0

So, if I get you right you have a few public class methods on Article
and Event that will do the queries. You want to get rid of the "active"
parameter in each query.

One way to do this would be create a class method: active_items. It
returns an object that is has the same query methods as the class, that
is, both have the methods recent_articles, featured_articles, ... with
the exact same parameter list.

On the implementation side, this object could use your class again to
perform its queries (& share query code), but this is hidden to the
client, the controller.

In summary, you have:
News.recent_articles(*args)
News.active_items.recent_articles(*args)

When the user checks the "show only active" checkbox, you just replace
@query_handler with News.active_items. You don't have to change any
code and the parameter is implicit.

On 2006-06-17 05:20:13 +0200, daywalk@gmail.com said:

> Hey,
>
> I have a system that I am trying to design, it contains news articles,
> events, etc... There is model representing articles, one representing
> events, etc...
>
> Articles or events can be active or inactive, so I can do a query to
> return all active articles, all articles or all inactive articles.
>
> The question that I have is what would be the best way to design this.
> Right now I have each method (such as recent articles, featured
> articles, etc...) taking an 'active' parameter. This requires littering
> the code with method calls taking this parameter.
>
> I have also thought about setting a class variable on the models to set
> whether active/inactive/all articles are returned, so that anytime you
> want to set the type returned you set this class variable and then call
> your functions (recent_articles, etc...).
>
> What I would like to know is if there are any suggestions as to a good
> practice to follow in how to implement this functionality, one of the
> ways I have stated or some other way that I haven't considered.
>
> I hope I have been clear. Thanks for the help in advance.
>
> P.S. The application is done in ruby on rails.


Dumaiu

6/18/2006 5:13:00 PM

0

I like zycte's idea. It reminds me of a C++ idiom for working around
the absence of named parameters. The 'active' request's gotta be in
the call somewhere, in an argument or not, but the advantage of putting
it "before the period" in the method call is that you can create an
object (which I shall call a 'Query') that can be *reused*, solving
your verbosity problem. I wrote this pretty fast:

class Article
# Simple boolean features available:
def Article::attributes()
return %w( recent featured active ) # etc.
end

attributes.each { |i|
attr_accessor(i)
}
end

class Query
def initialize()
# Start with all attributes 'false', or 'nil', or whatever:
Article::attributes.each { |i|
eval "@#{i} = false"
}
end

# Reader methods:
Article::attributes.each { |i|
eval <<-EVAL
def #{i}?()
return @#{i}
end
EVAL
}

# Writer methods:
Article::attributes.each { |i|
eval <<-EVAL
def #{i}( val = true )
@#{i} = val

return self # Important!
end
EVAL
}

# Run the query:
def call( array )
# Assuming that your Articles, etc. are stored in an array:
return array.select { |elem|
# Find any attribute that doesn't match (returns 'nil' if all do):
not Article::attributes.detect { |att|
elem.method( "#{att}" ).call ^ method( "#{att}?" ).call
}
}
end
end

The eval() statements could be written more elegantly with
define_method() and the like; Query#call() assumes that all the
Articles are in an Array; and other evident cleanliness issues. Most
notably, the Query attributes should probably respond to an
intermediate 'any' value. But by extending said attribute list to
include other search criteria, you could make a Query as compex as you
wanted and then use call() to run it all at once.
Somebody out there may have a library to do all of this.

Dumaiu

6/18/2006 5:24:00 PM

0

Sorry. I should have provided an example. You could write

q = Query.new

and then

q.active.featured.recent(false)

and then, at any point,

q.call(array)

to return all Articles in 'array' which return 'active', 'featured',
and '!recent'.

-Jonathan