Forum: Ruby on Rails Newbie Question about Custom Classes

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Brent J. (Guest)
on 2006-03-20 17:37
(Received via mailing list)
Sorry if this is a complete newbish question, but I'm trying to wrap
my head around creating custom classes in my rails webapp.  I'm
normally a Java developer, but I figured I'd give RoR a try and see
how I like it, and whether it would be useful for production use with
a new client.

Anyways, what are the best practices for custom classes?  Where and/or
how do I create and use them?  Is there a tutorial somewhere?
Basically, here's what I'm trying to do.  I have an XML file in a
custom format that represents news articles.  In my controller I'm
using REXML to read and parse that file (BTW, see my note at the end
of this email), and I want to encapsulate that into an "Article" type
class, with title, date, description, etc that I can then use in my
view.

How do I go about this?  Where should I store the class?  If someone
could point me to a tutorial or example of custom classes in a Rails
app, or give me a little hint how/where to start I'd really appreciate
it.

Thanks,

- Brent

NOTE:  I was having a terrible time with RoR giving me a "File not
found" error when calling File.new.  It said the current directory was
my rails project directory root.  I checked, rechecked, copied-pasted
the directory/file to make SURE it was there.  It was!  Turns out the
current directory is the config/ directory and NOT the project one as
reported.
Norman T. (Guest)
on 2006-03-20 17:52
(Received via mailing list)
Am Montag, den 20.03.2006, 10:37 -0500 schrieb Brent J.:
> using REXML to read and parse that file (BTW, see my note at the end
> of this email), and I want to encapsulate that into an "Article" type
> class, with title, date, description, etc that I can then use in my
> view.
>
> How do I go about this?  Where should I store the class?  If someone
> could point me to a tutorial or example of custom classes in a Rails
> app, or give me a little hint how/where to start I'd really appreciate
> it.

I would suggest storing your Article model in the app/models directory
and adding a create_from_xml class method, or parse the xml in the
controller as you already do.

--
Norman T.

http://blog.inlet-media.de
Brent J. (Guest)
on 2006-03-20 17:58
(Received via mailing list)
Thanks for the response.  I was just thinking of doing this.  But
here's what I would normally do in Java.  I'd create a News class, and
an Article class.  The News class would read the XML and create an
array of Article classes.

So, should I create two models, one called News and one called
Articles?  Is every custom class considered a model?  What about some
utility class that really doesn't fit as a model?

Thanks again,

- Brent
Norman T. (Guest)
on 2006-03-20 18:15
(Received via mailing list)
Am Montag, den 20.03.2006, 10:57 -0500 schrieb Brent J.:
>
> - Brent
>
> On 3/20/06, Norman T. <removed_email_address@domain.invalid> wrote:
> > I would suggest storing your Article model in the app/models directory
> > and adding a create_from_xml class method, or parse the xml in the
> > controller as you already do.

Ok, i'll get a little bit deeper:

Classes, that hold data go into app/models. Classes that have nothing to
do with holding data, go into the lib directory.

If your parsing logic is not too complex, i would put it into the
Article class. If it is complex, put it as a separate class or module in
lib.

My suggestion for your Article class:

class Article

  # class methods
  class < self
    def build_from_xml
      # parsing logic goes here returning an Array of Article objects
    end
  end
end

In your controller just do:

class NewsController < ApplicationController
  def my_action
    File.open('my_articles.xml') do |file|
      @articles = Article.build_from_xml(file.read)
    end
  end
end

--
Norman T.

http://blog.inlet-media.de
Brent J. (Guest)
on 2006-03-20 18:27
(Received via mailing list)
Thanks for the info!  The parsing won't be terribly complex (just
doing some xpath queries, etc) so I think I'll use your suggestion.

In Java, for a class to be used it has to be in your classpath.  How
does RoR figure out where the actual class is?  Does it look under
your app/models (and controllers, views, etc) and lib directories?

Thanks again,

- Brent
Norman T. (Guest)
on 2006-03-20 18:59
(Received via mailing list)
Am Montag, den 20.03.2006, 11:27 -0500 schrieb Brent J.:

> In Java, for a class to be used it has to be in your classpath.  How
> does RoR figure out where the actual class is?  Does it look under
> your app/models (and controllers, views, etc) and lib directories?

Ruby has a loadpath. It is extended by Rails (1.0) using the following
method:

      def default_load_paths
        paths = ["#{root_path}/test/mocks/#{environment}"]

        # Then model subdirectories.
        # TODO: Don't include .rb models as load paths
        paths.concat(Dir["#{root_path}/app/models/[_a-z]*"])
        paths.concat(Dir["#{root_path}/components/[_a-z]*"])

        # Followed by the standard includes.
        # TODO: Don't include dirs for frameworks that are not used
        paths.concat %w(
          app
          app/models
          app/controllers
          app/helpers
          app/services
          app/apis
          components
          config
          lib
          vendor
          vendor/rails/railties
          vendor/rails/railties/lib
          vendor/rails/actionpack/lib
          vendor/rails/activesupport/lib
          vendor/rails/activerecord/lib
          vendor/rails/actionmailer/lib
          vendor/rails/actionwebservice/lib
        ).map { |dir| "#{root_path}/#{dir}" }.select { |dir|
File.directory?(dir) }
      end

Files in this directories don't have to be required explicitly (because
of some Ruby extensions made by rails), but files in subdirectories of
you loadpath, e.g. lib/my_library/myfile.rb must be required like this:

require 'my_library/myfile'

--
Norman T.

http://blog.inlet-media.de
Brent J. (Guest)
on 2006-03-20 20:44
(Received via mailing list)
Alright, I know I have to be doing something extremely noobish.  But
I've created a simple class that has one method just as a test,
because RoR can't seem to find the methods I put in the class.  So
here's the simplest example I could think of:

class Article
    def blah
    end
end

Yes, this does absolutely nothing.  But if I try this in my controller:

Article.blah()

I get "undefined method `blah' for #<Article:0xb789bfbc>".  It doesn't
matter what I put into "blah" it just never sees it.  It does,
however, see the article class.  Do I have to do anything special, or
define the method another way so that it's accessible from the
controller?  It's currently in app/models/article.rb.

Thanks,

- Brent
Calle D. (Guest)
on 2006-03-20 20:59
(Received via mailing list)
>>>>> "Brent" == Brent J. <removed_email_address@domain.invalid> writes:

> Alright, I know I have to be doing something extremely noobish.

Kind of, yes. It's a Ruby thing rather than a Rails thing you're
missing.

> class Article
>     def blah
>     end
> end

> Yes, this does absolutely nothing.  But if I try this in my controller:

> Article.blah()

> I get "undefined method `blah' for #<Article:0xb789bfbc>".

That's because you've defined an instance method but are trying to
call a class method. That's not going to work, as you've noticed. With
the code as you've written it here, you can call it like this...

a = Article.new
a.blah

...or, if you want to call it as a class method, you do like this...

class Article
  def self.blah
  end
end

...and then you can call Article.blah

--
		     Calle D. <removed_email_address@domain.invalid>
		 http://www.livejournal.com/users/cdybedahl/
   "But that was in the gauzy realm of meat and oxygen, not this real
world
	       here on the screen." -- archbishopm, LiveJournal
Brent J. (Guest)
on 2006-03-20 21:07
(Received via mailing list)
> That's because you've defined an instance method but are trying to
> call a class method. That's not going to work, as you've noticed. With
> the code as you've written it here, you can call it like this...
>
> a = Article.new
> a.blah

Tried that first, actually.  I get the same result, undefined method.

> ...or, if you want to call it as a class method, you do like this...
>
> class Article
>   def self.blah
>   end
> end

Just tried that, but got the same message.  I know I've missed
something hugely obvious somewhere.  I wasn't sure if the problem was
Ruby OR Rails related, but I looked at some examples and tutorials on
creating classes in Ruby and it looks pretty straight forward.  So I
thought maybe there was something in Rails I had to do to get it to
work correctly.

Thanks,

- Brent
Brent J. (Guest)
on 2006-03-20 21:12
(Received via mailing list)
OK, here's the deal.  It turns out I've got some caching turned on or
something.  I bounced Apache HTTPD and wham, it worked.  I then added
a return to my blah function to return a string.  I tried again and it
wasnt returning anything.  I bounced the server again and it returned
the value I set.  Seems as though it gets cached the first time it
runs then never changes again.

Thanks for the help,

- Brent
Tom M. (Guest)
on 2006-03-20 21:13
(Received via mailing list)
Where is your class file located?

--
-- Tom M.
Norman T. (Guest)
on 2006-03-20 21:15
(Received via mailing list)
Am Montag, den 20.03.2006, 14:06 -0500 schrieb Brent J.:
> >
> work correctly.
What about what i suggested before:

class Article

  # class methods
  class < self
    def blah
    end
  end
end

Don't forget to restart your Websever unless you are working in
development mode using webrick server.
--
Norman T.

http://blog.inlet-media.de
Brent J. (Guest)
on 2006-03-20 21:20
(Received via mailing list)
It's located in app/models.  I was thinking it may be running in the
production environment, because there is a setting called
"config.cache_classes" which was set to true.  But I tried setting
that to false and restarting and still get the same result.

- Brent
This topic is locked and can not be replied to.