Forum: Ruby on Rails Rake Tasks

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.
Joel D. (Guest)
on 2009-06-07 00:54
Hi Everyone,

I just need some further help clarifying a custom rake task I'm building
and the logistics of how it should be working.

I've created a custom rake task in libs/tasks called scraper.rake which
so far just contains the following:

desc "This task will parse data from ncaa.org and upload the data to our
db"
task :scraper => :environment do
  # code goes here for scraping
end

This rake task will be parsing data from ncaa.org and placing it into my
DB for further processing.  The .rb file I created has the following:

===============================

#== Scraper Version 1.0
#
#*Created By:* _Elricstorm_
#
# _Special thanks to Soledad Penades for his initial parse idea which I
worked with to create the Scraper program.
# His article is located at
http://www.iterasi.net/openviewer.aspx?sqrlitid=wd...
#
require 'hpricot'
require 'open-uri'

# This class is used to parse and collect data out of an html element
class Scraper
  attr_accessor :url, :element_type, :clsname, :childsearch, :doc,
:numrows
   # Define what the url is, what element type and class name we want to
parse and open the url.
  def initialize(url, element_type, clsname, childsearch)
    @url = url
    @element_type = element_type
    @clsname = clsname
    @childsearch = childsearch
    @doc = Hpricot(open(url))
    @numrows = numrows
  end

  # Scrape data based on the type of element, its class name, and define
the child element that contains our data
  def scrape_data

    @rows = []

    (doc/"#{@element_type}.#{@clsname}#{@childsearch}").each do |row|
      cells = []
      (row/"td").each do |cell|

          if (cell/" span.s").length > 0
                values = (cell/"span.s").inner_html.split('<br
/>').collect{ |str|
                pair = str.strip.split('=').collect{|val| val.strip}
                Hash[pair[0], pair[1]]
              }

              if(values.length==1)
                cells << cell.inner_text.strip
              else
                cells << values.strip
              end

          elsif
              cells << cell.inner_text.strip
          end
      end
      @rows << cells
    end
    @rows.shift # Shifting removes the row containing the <th> table
header elements.
    @rows.delete([]) # Remove any empty rows in our array of arrays.
    @numrows = @rows.length
  end

  def clean_celldata
     @rows[@numrows-1][0] = 120
  end

  # Print a joined list by row to see our results
  def print_values
    puts "Number of rows = #{numrows}."
    for i in 0..@numrows-1
      puts @rows[i].join(', ')
    end
  end
end
# In our search we are supplying the website url to parse, the type of
element (ex: table), the class name of that element
# and the child element that contains the data we wish to retrieve.
offensive_rushing =
Scraper.new('http://web1.ncaa.org/mfb/natlRank.jsp?year=2008&rp...,
      'table', 'statstable', '//tr')
offensive_rushing.scrape_data
offensive_rushing.clean_celldata
offensive_rushing.print_values

================================

If you tested that out, you will see a print out of 120 rows of data..

What I want to do is to utilize the .rb file I created with my rake
task.  However, I'm not sure how to incorporate that into rails.  Once I
get past this hurdle it should help with future issues.

So, here are my list of questions in order of what I am curious to
know..

1.  Where do custom .rb files go inside of my rails project?  (for
instance I understand the MVC but with a rake task - in my brain it's
outside of the project and I'm not sure how it is supposed to
communicate with controllers or pull/associate variables from those
areas.

2.  With my custom .rb I'm also requiring 'hpricot'.  Is there anything
special I need to do with a .rake file to make sure that it knows to
pull this gem?  And, if I export to my real site, how do I ensure that
hpricot is loaded there too?  In otherwords, what expectations should I
be relying on?

3.  When I run a rake task and need to communicate with my database (for
uploading purposes) is there an easy way to do this?  Can I utilize
.rake with my DB inside of my rails environment? Or, are rake tasks
completely seperate and distinct and need to be considered outside of
scope?

4.  Can anyone provide me a summarized step by step (nothing too fancy
or that takes up too much of your own time) with how "you" would
accomplish this kind of rake task given a similar .rb and .rake file?
What generalized steps would you take?  Create a class? (if so, where
would you place it)  How would you communicate with the DB within rails?
etc.

I know these are a lot of questions but I figure even if one or two of
them get answered, I'm happy.  You don't have to feel that you can't
reply if you don't have the answers to all of them.  Any answers that
can be touched upon would be greatly appreciated.

I am a newbie and learning rails (but many books do not talk about these
particulars).  So, I'm relying on others that have patience and
understanding to help enlighten me so that one day I too, can help
others that need similar help.

Thanks.
Maurício L. (Guest)
on 2009-06-07 07:41
(Received via mailing list)
On Sat, Jun 6, 2009 at 5:54 PM, J. D.<removed_email_address@domain.invalid>
wrote:
> 1.  Where do custom .rb files go inside of my rails project?  (for
> instance I understand the MVC but with a rake task - in my brain it's
> outside of the project and I'm not sure how it is supposed to
> communicate with controllers or pull/associate variables from those
> areas.
>

This custom file should be called scraper.rb and should be placed at
the /lib folder of your application. In a rake task you don't really
access or call controllers, you just run the task, which is telling
the scrapper to load the data and then save it to the DB.

> 2.  With my custom .rb I'm also requiring 'hpricot'.  Is there anything
> special I need to do with a .rake file to make sure that it knows to
> pull this gem?  And, if I export to my real site, how do I ensure that
> hpricot is loaded there too?  In otherwords, what expectations should I
> be relying on?
>

You don't need to do anything else, Rails will automatically enable
rubygems and by requiring hpricot you will tell it to load the gem.

> 3.  When I run a rake task and need to communicate with my database (for
> uploading purposes) is there an easy way to do this?  Can I utilize
> .rake with my DB inside of my rails environment? Or, are rake tasks
> completely seperate and distinct and need to be considered outside of
> scope?
>

Now you have to learn the Rails database access framework,
ActiveRecord, you should probably find plenty of material about it.


-
Maurício Linhares
http://alinhavado.wordpress.com/ (pt-br) |
http://codeshooter.wordpress.com/ (en)
Joel D. (Guest)
on 2009-06-07 16:40
Maurício Linhares wrote:
> This custom file should be called scraper.rb and should be placed at
> the /lib folder of your application. In a rake task you don't really
> access or call controllers, you just run the task, which is telling
> the scrapper to load the data and then save it to the DB.
>

So, just to make sure I understand correctly..

The scraper.rb file would go in the lib folder and my scraper.rake file
would go in the lib\tasks folder?  The rake file - would I have to
include anything to call that .rb file?  I'm sorry if I am
misunderstanding this portion of the mechanics.

>
> You don't need to do anything else, Rails will automatically enable
> rubygems and by requiring hpricot you will tell it to load the gem.
>

Thanks - that part is easy enough.  When I go to port my app to my real
site, I will have to install hpricot there as well?  Or, can I include
hpricot in vendor\plugins?

>
> Now you have to learn the Rails database access framework,
> ActiveRecord, you should probably find plenty of material about it.
>

This is the part that I'm currently studying/reading on and it's
wonderful thus far.  I just didn't know if the rake task or the ruby
file had to communicate with activerecord in a certain way..

i.e. - When I have a controller created it can communicate through the
model and access the database.  Since the rake and rb file are not part
of MVC, I just didn't know if it also used similar mechanics or not.

Thanks for the feedback.  I'll wait for the reply on the first note to
figure it out..
Frederick C. (Guest)
on 2009-06-07 17:05
(Received via mailing list)
On Jun 7, 1:40 pm, "J. D." <removed_email_address@domain.invalid> wrote:
> include anything to call that .rb file?  I'm sorry if I am
> misunderstanding this portion of the mechanics.
>
>
Because your task depends on :environment Rails is loaded, in
particular its dependency management is loaded so it will find your
Scraper class as long as it's in scraper.rb somewhere on its search
path. Don't take my word for it though, try it!

Fred
Joel D. (Guest)
on 2009-06-07 18:01
Frederick C. wrote:
> On Jun 7, 1:40�pm, "J. D." <removed_email_address@domain.invalid> wrote:
>> include anything to call that .rb file? �I'm sorry if I am
>> misunderstanding this portion of the mechanics.
>>
>>
> Because your task depends on :environment Rails is loaded, in
> particular its dependency management is loaded so it will find your
> Scraper class as long as it's in scraper.rb somewhere on its search
> path. Don't take my word for it though, try it!
>
> Fred

Thanks,

I'll test a couple of generic variables and puts...
Joel D. (Guest)
on 2009-06-07 18:08
Thanks - I understand that part now!

I put scraper.rb in my Libs folder
I put scraper.rake in my libs/tasks

I took the end portion of scraper.rb and removed it placing it in my
rake file:

desc "This task will parse data from ncaa.org and upload the data to our
db"
task :scraper => :environment do
  # In our search we are supplying the website url to parse, the type of
element (ex: table), the class name of that element
  # and the child element that contains the data we wish to retrieve.
  offensive_rushing =
Scraper.new('http://web1.ncaa.org/mfb/natlRank.jsp?year=2008&rp...,
    'table', 'statstable', '//tr')
  offensive_rushing.scrape_data
  offensive_rushing.clean_celldata
  offensive_rushing.print_values
end

And it did a print out when I called the rake..  So, now I'll have to
test this with the database and see how it works...

Thanks a ton (I understand it now)..

The part that was => environment do was telling my rake task to make
sure that the environment was fully loaded before running it.

So, if I wanted to run another rake task in the same rake file and I
wanted to make sure the first was done, I'd do something like:

task: next_task => :scraper do
  # code
end

which would make it run only after the scraper task had finished..
Thufir (Guest)
on 2009-09-23 22:29
(Received via mailing list)
On Sep 20, 6:20 am, Rick <removed_email_address@domain.invalid> wrote:
> Rake, like it's namesake Make, is useful for organizing complex tasks
> that typicallly have other complex tasks as preconditions.  It's
> typically used to organize "build cycle" stages which are passed
> through on the way to presenting the completed project (document,
> test, application, installation, ...).

Right, in this case I'm automating creating, destroying and populating
a db.  Is that inappropriate somehow?


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