Ruby中,ActiveRecord 初次使用心得(一)
阿新 • • 發佈:2019-01-28
自己要寫一個將csv檔案資料匯入資料庫的Ruby程式,用到了ActiveRecord,程式如下:
require 'csv'require 'rubygems'
require 'active_record'
require 'yaml'
class_name = ARGV[0].split('/').last.split('.')[0]
eval("
class #{class_name} < ActiveRecord::Base
end
") #Create class dynamicly
class Import_csv_data
def initialize(csv_file_path) #Method initialization gets csv_file_path form command line
if csv_file_path.eql?(nil)
puts 'Please ruby the file with csv file path, such as "ruby example.rb /home/..example.csv"'
else
@table_name = csv_file_path.split('/').last.split('.')[0]
@csv_file_path = csv_file_path
@field_num = 0
end
end
def import_data() #Main Method. invoke Method read_csv_file, connect_db
if @table_name
connect_db()
all_data = read_csv_file()
1.upto(all_data.length - 1) do |data_index|
data = []
sql = make_sql(all_data, data_index)
puts sql
eval("
data = #{@table_name}.find_by_sql \"#{sql}\"
")
if data.eql?([])
Object::const_get(@table_name).new do |value|
0.upto(all_data[0].length - 2) do |num|
eval("
value.#{all_data[0][num]} = #{all_data[data_index][num]}
")
end
value.save
end
end
end
end
end
private
def read_csv_file() #Method read_csv_file is to get data from csv file, return all_data which
#is two-dimensional array.
all_data = []
CSV.open(@csv_file_path,'r') do |row|
all_data << row
@field_num = row.length - 1
end
return all_data
end
def connect_db() #Method is to connect DB
db_config = YAML.load(File.open("db_config.yaml")) #Get congfigrat
ActiveRecord::Base.establish_connection(:adapter => db_config["adapter"],
:host => db_config["host"],
:username => db_config["username"],
:password => db_config["password"],
:database => db_config["database"])
ActiveRecord::Base.pluralize_table_names = false
end
def make_sql(all_data, data_index) #Method is to make sql query
table_name = @table_name.downcase
sql = "select * from #{table_name} where "
1.upto(ARGV.length - 1) do |argv_index|
unless argv_index == 1
sql << " and "
end
sql << "#{all_data[0][ARGV[argv_index].to_i]} = #{all_data[data_index][ARGV[argv_index].to_i]}"
end
return sql
end
end
Import_csv_data.new(ARGV[0]).import_data()
功能不算複雜,編寫的過程卻異常艱難:
1,因為要做到通用性,根據csv檔案的名字將資料匯入相應的表中,所以繼承於ActiveRecord::Base的類要動態生成,這裡,我用了最簡單的方法:eval(“ your codes ”),其實,還有很多其他的方法,例如,Object::const_set(@table_name),等等。
2,在用到ActiveRecord包時,遇到複合主鍵的問題,因為ActiveRecord不支援複合主鍵,所以我自己編寫了SQL語句,但是在呼叫方法#{@table_name}.find_by_sql 時,總是報語法錯誤,反覆除錯後,發現在SQL語句兩邊加雙引號 \"#{sql}\" 後,問題解決。