Extracting PDF rows to Rails db? - ruby-on-rails

My source contains only 1,500 objects. At most it may grow to 2,000. I'm obtaining the objects via PDF and parsing with PDF Reader. They are parsed and returned by rows as String objects:
file = File.open("app/assets/images/file.pdf")
reader = PDF::Reader.new(file)
page = reader.pages[0]
rows = page.text.scan(/^.+/) #String Objects
rows.slice!(0..3) #Removes Header Info
Sample object :
=> ["1", "3", "215", "06/02/83", "Law,", "Steve"]
Then I remove the "," appended to last name and split the String object thus creating a Array Object:
row = #rows[0].tr(',', '').split #Array Objects
=> ["1", "3", "215", "06/02/83", "Law", "Steve"] #Array Object
I want to iterate through each row and insert into User table via console or form. What methods should I consider?
Thanks!

Lets assume you have mysql with users table in it and active_record gem installed.
If you writing just plain ruby script first you need to require active_record(commonly used ORM in rails), establish connection to db and create User model to get access to the users table via ActiveRecord:
require 'rubygems'
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => 'mysql',
:host => 'localhost',
:database => 'your_db_name'
)
class User < ActiveRecord::Base
end
So now all you need to do is to iterate over the rows and call User.create method:
rows.slice!(0..3).each do |row|
row.reverse! # reverse array so we can easily access its elements with ruby Array methods
first_name = row.first
last_name = row.second.sub(/,/, '') # remove ',' symbol
birth_date = row.third
...
User.create(:first_name => first_name, :last_name => last_name, :birth_date => birth_date, ...) # I assumed you have first_name, last_name, ..., columns in your users table
end
Its all can be done in one file.
If you writing something like a rake task in your Rails environment you need to configure db connection in config/database.yml and create User model in app/models dir.

Related

Does Ruby or Rails have an equivalent of pandas.read_sql?

So in Python, I am used to using something like
pd.read_sql(sql_query, connection_object)
in order to grab data from a remote database. But when forming a similar connection object in Ruby:
require 'pg'
#connect_obj = PG.connect(:host => host, :dbname => db , :user => user , :password => pwd , :port => port )
what can Ruby do in order to run something like pd.read_sql(sql_query, connection_object)?
With Rails, the usual way is to create a model class for your table and then use ActiveRecord methods.
But if you want to run some general queries without using any model classes, you can try it this way:
ActiveRecord::Base.connection.execute('SELECT * FROM users').each { |row| puts row }

How do you call "contains?" on a MongoMapper Array in Rails 3?

I want to know how to check if an array element exists inside of a MongoMapper Array. This question is the closest I could find, but it addresses queries rather than simply using a document you already have.
My User model contains the line
key :roles, Array
The 'roles' array contains strings such as 'admin' or 'user.' For authorization, I need to call something like the following method on an instance of User:
if user.roles.contains?('admin')
# Do administrative stuff.
end
But when I try to call 'contains?' Ruby complains that there is no such method:
NoMethodError (undefined method `contains?' for #<Array:0x007fc845cd8948>):
app/models/ability.rb:11:in `initialize'
app/controllers/settings_controller.rb:5:in `index'
If there's no way to do this, then how do I convert the Array into a Ruby array to call 'contains?'? Calling to_a isn't doing it:
if user.roles.to_a.contains?('admin') # etc...
I'm using Rails 3.2.13, Ruby-1.9.3-p392, and MongoMapper 0.12.0 on Mountain Lion.
the function you are looking for is include?, so the expression would be: user.roles.include?('admin')
However since you mentioned mongomapper, if you were preforming a query on the roles array you would do the fallowing:
User.where( :roles => 'admin' )
You can also search an array with an array
User.where( :roles.in => ['admin'] )
for a query with admin or user you can do:
User.where( :$or => [{:roles => 'admin'},{:roles => 'user'}] )
and you can do and just the same:
User.where( :$and => [{:roles => 'admin'},{:roles => 'user'}] )

Active Record without Rails: How to pass an Arbitrary hash to Active Record

I'm trying to pass the following Hash to Active Record to save:
[{
"id"=>"WSECOUT",
"realtime_start"=>"2013-02-10",
"realtime_end"=>"2013-02-10",
"title"=>"Reserve Bank Credit - Securities Held Outright",
"observation_start"=>"1989-03-22",
"observation_end"=>"2013-02-06",
"frequency"=>"Weekly, Ending Wednesday",
"frequency_short"=>"W",
"units"=>"Billions of Dollars",
"units_short"=>"Bil. of $",
"seasonal_adjustment"=>"Not Seasonally Adjusted",
"seasonal_adjustment_short"=>"NSA",
"last_updated"=>"2013-02-08 08:32:33-06",
"popularity"=>"42",
"notes"=>"The amount of securities held by Federal Reserve Banks. This quantity is the cumulative result of permanent open market operations: outright purchases or sales of securities, conducted by the Federal Reserve. Section 14 of the Federal Reserve Act defines the securities that the Federal Reserve is authorized to buy and sell."
}]
My ruby class looks like this:
require 'rubygems'
require 'active_record'
require 'logger'
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:username => "root",
:password => "*********",
:database => "fred"
)
class Series < ActiveRecord::Base
attr_accessible :id, :realtime_start, :realtime_end, :title, :observation_start,
:observation_end, :frequency, :frequency_short, :units, :units_short,
:seasonal_adjustment, :seasonal_adjustment_short, :last_updated,
:popularity, :notes
end
require_relative 'wsecout'
#series = Wsecout.new.getSeries "wsecout"
#series = #series['series']
test = Series.create(#series)
The #series variable contains the Hash. When I run this code, the object is created as is the row in mysql, however, there is no data in the fields. I know I'm missing a step here, but I am unable to figure out which step. Also, is there going to be a problem with my Hash containing an id, because Active Record creates it's own id?
Answer to your second question "map that "id" to a new field called :series_id":
#series['series'][0]['series_id'] = #series['series'][0]['id']
#series['series'][0].delete('id')
Or if you want to change multiple keys based on some criteria, then use it in the if condition as below:
#series['series'][0].keys.each do |k|
if(k == 'id')
#series['series'][0]['series_id'] = #series['series'][0][k]
#series['series'][0].delete(k)
end
end
This will iterate through each key of the hash and if the key matches to id then it add another key series_id with the same value and delete the id.

Metaprogramming in Ruby On Rails

I have an array of strings: ["users", "torrents", "comments"]
these strings are the names of my bd tables.
how can I in .each loop connect to these tables and select|insert some data?
Avoid using eval
here is a simple solution using constantize
note: constantize will not allow arbitrary code to evaluated, it will just try to fetch a ruby constant, namely a Class
["users", "torrents", "comments"].each do |table_name|
# "users" => "User"
# or more complex
# "some_models" => "SomeModel"
#
class_name = table_name.singularize.camelize
# "User" => User
model_class = class_name.constantize
# do something with it
model_class.create!(:value => 12345)
end

Trouble importing csv file with ruby CSV Module

I'm trying to use Ruby's csv module to import the records contained in a csv file to my local table in a Ruby on Rails 3 application.
The table was created through the creation of model Movie.
Here is what I've been executing in console:
require 'csv'
CSV.foreach('public/uploads/VideoTitles2.csv') do |row|
record = Movie.new(
:media_format => row[0],
:title => row[1],
:copies_at_home => row[2],
:order => row[3]
)
record.save
end
The rows of the csv file match (in data type) the columns they're being passed into. Here is a shortened version of the csv file (VideoTitles2.csv) I'm attempting to import:
"DVD","LEAP OF FAITH",1,1
"DVD","COCOON",1,2
"DVD","TITANIC",1,3
where each record is separated by \n I believe. This csv file was exported from Access and its original file extension was .txt. I've manually changed it to .csv for sake of the import.
The problem is that, after executing the above lines in rails console, I get the following output:
=> nil
The import doesn't seem to happen. If anyone has an idea as to how I could remedy this I'd really appreciate it.
I don't see the problem. This code snippet returns nil because CSV.foreach returns nil, but this is no indication if the loop is run or not. Did you checked if any Movie was created? did you include any debug lines to follow the process?
You may want to check the output of record.save (or call record.save!), maybe validations errors are preventing the record from being created. Also, if you want the loop to return the created records, you can write this (Ruby >= 1.8.7):
require 'csv'
records = CSV.foreach('public/uploads/VideoTitles2.csv').map do |media_format, title, copies_at_home, order|
Movie.create!({
media_format: media_format,
title: title,
copies_at_home: copies_at_home,
order: order,
})
end
Okay there were two things I had wrong:
The exported csv file should not have quotations around the strings - I just removed them.
Thanks to tokland, the record.save! was necessary (as opposed to the record.save I was doing) - validation errors were preventing the records from being created.
So to conclude, one could just create the following function after creating the model/table Movie:
class Movie < ActiveRecord::Base
attr_accessible :media_format, :title, :copies_at_home, :order
require 'csv'
def self.import_movies()
CSV.foreach('public/uploads/movies.csv') do |row|
record = Movie.new(
:media_format => row[0],
:title => row[1],
:copies_at_home => row[2],
:order => row[3]
)
record.save!
end
end
end
Where movies.csv looks like the following:
Blu-ray, Movie 1, 1, 1
DVD, Movie 2, 1, 2
Blu-ray, Movie 3, 1, 3
then call this function in console as such:
Movie.import_movies()
and, as expected, all that would be returned in the console would be:
=> nil
Check your index view (if you've created one) and you should see that the records were successfully imported into the movies table.

Resources