class Flextures::Loader
data loader
Constants
- COMPLETER
column set default value
- FORMATS
- PARENT
base configurations
- TRANSLATER
colum data translate
Public Class Methods
# File lib/flextures/flextures_loader.rb, line 136 def self.cache?(params) return unless params.first.is_a?(Hash) param = params.first param[:cache] == true end
return flextures data translate filter translate filter is some functions
-
column value is fill, if colum is not nullable
-
factory filter
@params [ActiveRecord::Base] klass ActiveRecord
model data @params [Proc] factory FactoryFilter @params [String] filename @params [Symbol] ext file type (:csv or :yml) @params [Hash] options other options @return [Proc] translate filter
# File lib/flextures/flextures_loader.rb, line 367 def self.create_filter(klass, factory, filename, ext, options) columns = klass.columns # data translate array to hash column_hash = columns.reduce({}) { |h,col| h[col.name] = col; h } translaters = column_hash.reduce({}){ |h,(k,col)| h[k] = col.translater(klass); h } strict_filter = ->(o,h){ # if value is not 'nil', value translate suitable form h.each { |k,v| v.nil? || o[k] = translaters[k]&.call(v) } # call FactoryFilter factory.call(*[o, filename, ext][0, factory.arity]) if factory and !options[:unfilter] o } return strict_filter if options[:strict]==true lack_columns = columns.reject { |c| c.null and c.default }.map{ |o| o.name.to_sym } # default value shound not be null columns not_nullable_columns = columns.reject(&:null).map(&:name) completers = column_hash.reduce({}){ |h,(k,col)| h[k] = col.completer(klass); h } # receives hased data and translate ActiveRecord Model data # loose filter correct error values # strict filter don't correct errora values and raise error loose_filter = ->(o,h){ h.reject! { |k,v| options[:minus].include?(k) } if options[:minus] # if column name is not include database table columns, those names delete h.select! { |k,v| column_hash[k] } strict_filter.call(o,h) # set default value if value is 'nil' not_nullable_columns.each { |k| o[k].nil? && o[k] = completers[k]&.call } # fill span values if column is not exist lack_columns.each { |k| o[k].nil? && o[k] = completers[k]&.call } o } end
create filter and table info
# File lib/flextures/flextures_loader.rb, line 342 def self.create_model_filter(format, file_name, type) table_name = format[:table].to_s klass = PARENT::create_model(table_name) # if you use 'rails3_acts_as_paranoid' gem, that is not delete data 'delete_all' method klass.send(klass.respond_to?(:delete_all!) ? :delete_all! : :delete_all) filter = ->(h){ filter = create_filter(klass, LoadFilter[table_name.to_sym], file_name, type, format) o = klass.new o = filter.call(o, h) o } [klass, filter] end
parse format option and return load file info @param [Hash] format load file format informations @return [Array] [file_name, filt_type(:csv or :yml)]
# File lib/flextures/flextures_loader.rb, line 313 def self.file_exist(format, type = %i[csv yml]) table_name = format[:table].to_s file_name = (format[:file] || format[:table]).to_s base_dir_name = Flextures::Configuration.load_directory self.stair_list(format[:dir], format[:stair]).each do |dir| file_path = File.join(base_dir_name, dir, file_name) formats = FORMATS.select { |fmt| (type & fmt).present? } formats.each do |fmt| return ["#{file_path}.#{fmt.join('.')}", *fmt] if File.exist?("#{file_path}.#{fmt.join('.')}") end end ["#{File.join(base_dir_name, file_name)}.csv", nil] end
file load check @return [Bool] lodable is 'true'
# File lib/flextures/flextures_loader.rb, line 329 def self.file_loadable?(format, file_name) return unless File.exist?(file_name) puts "try loading #{file_name}" if !format[:silent] and ![:fun].include?(format[:loader]) true end
load fixture datas
example: flextures :all # load all table data flextures :users, :items # load table data, received arguments flextures :users => :users2 # :table_name => :file_name
@params [Hash] fixtures load table data
# File lib/flextures/flextures_loader.rb, line 196 def self.flextures(*fixtures) loader = Flextures::Loader::Instance.new loader.loads(*fixtures) end
load fixture data fixture file prefer YAML to CSV @params [Hash] format file load format(table name, file name, options…)
# File lib/flextures/flextures_loader.rb, line 213 def self.load(format, type = %i[csv yml]) file_name, *exts = file_exist(format, type) format[:erb] = exts.include?(:erb) method = exts.find { |k| type.include?(k) } return unless self.file_loadable?(format, file_name) klass, filter = self.create_model_filter(format, file_name, method) case method when :csv self.load_csv(format, klass, filter, file_name) when :yml self.load_yml(format, klass, filter, file_name) else puts "Warning: #{file_name} is not exist!" unless format[:silent] end end
# File lib/flextures/flextures_loader.rb, line 242 def self.load_csv(format, klass, filter, file_name) file = self.load_file(format, file_name) attributes = klass.columns.map(&:name) ActiveRecord::Base.transaction do csv = SmarterCSV.process(file.path) keys = csv.first.keys.map(&:to_s) warning("CSV", attributes, keys) unless format[:silent] csv.each do |row| h = row.reduce({}){ |h,(k,v)| h[k.to_s]=v; h } o = filter.call(h) o.save(validate: false) end end file_name end
# File lib/flextures/flextures_loader.rb, line 232 def self.load_file(format, file_name) file = nil if format[:erb] str = File.open(file_name){ |f| f.read } file = ERB.new(str).result else file = File.open(file_name) end end
# File lib/flextures/flextures_loader.rb, line 258 def self.load_yml(format, klass, filter, file_name) file = self.load_file(format, file_name) yaml = YAML.load(file) return false unless yaml # if file is empty attributes = klass.columns.map(&:name) ActiveRecord::Base.transaction do yaml.each do |k,h| warning("YAML", attributes, h.keys) unless format[:silent] o = filter.call(h) o.save(validate: false) end end file_name end
@return [Proc] order rule block (user Array#sort methd)
# File lib/flextures/flextures_loader.rb, line 202 def self.loading_order ->(a,b) do a = Flextures::Configuration.table_load_order.index(a) || -1 b = Flextures::Configuration.table_load_order.index(b) || -1 b <=> a end end
# File lib/flextures/flextures_loader.rb, line 118 def initialize(*_) # 読み込み状態を持っておく @options = {} @already_loaded_fixtures = {} end
if parameter include controller, action value load directroy is change spec/fixtures/:controller_name/:action_name/ @return [String] directory path
# File lib/flextures/flextures_loader.rb, line 280 def self.parse_controller_option(options) controller_dir = ["controllers"] controller_dir<< options[:controller] if options[:controller] controller_dir<< options[:action] if options[:controller] and options[:action] File.join(*controller_dir) end
parse flextures function arguments @params [Hash] fixtures function arguments @return [Array] formatted load options
# File lib/flextures/flextures_loader.rb, line 173 def self.parse_flextures_options(base_options, *fixtures) options = {} options = fixtures.shift if fixtures.size > 1 and fixtures.first.is_a?(Hash) options[:dir] = self.parse_controller_option(options) if options[:controller] options[:dir] = self.parse_model_options(options) if options[:model] # :all value load all loadable fixtures fixtures = Flextures::deletable_tables if fixtures.size==1 and :all == fixtures.first last_hash = fixtures.last.is_a?(Hash) ? fixtures.pop : {} load_hash = fixtures.reduce({}){ |h,name| h[name.to_sym] = name.to_s; h } # if name is string is buged load_hash.merge!(last_hash) load_hash.map { |k,v| { table: k, file: v, loader: :fun }.merge(base_options).merge(options) } end
if parameter include controller, action value load directroy is change spec/fixtures/:model_name/:method_name/ @return [String] directory path
# File lib/flextures/flextures_loader.rb, line 291 def self.parse_model_options(options) model_dir = ["models"] model_dir<< options[:model] if options[:model] model_dir<< options[:method] if options[:model] and options[:method] File.join(*model_dir) end
example: self.create_stair_list(“foo/bar/baz”) return [“foo/bar/baz”,“foo/bar”,“foo”,“”]
# File lib/flextures/flextures_loader.rb, line 301 def self.stair_list(dir, stair=true) return [dir.to_s] unless stair l = [] dir.to_s.split("/").reduce([]){ |a,d| a<< d; l.unshift(a.join("/")); a } l<< "" l end
print warinig message that lack or not exist colum names
# File lib/flextures/flextures_loader.rb, line 336 def self.warning(format, attributes, keys) (attributes-keys).each { |name| puts "Warning: #{format} colum is missing! [#{name}]" } (keys-attributes).each { |name| puts "Warning: #{format} colum is left over! [#{name}]" } end
Public Instance Methods
called by Rspec or Should after filter reflesh options
# File lib/flextures/flextures_loader.rb, line 160 def delete_options @options = {} end
compare
# File lib/flextures/flextures_loader.rb, line 144 def equal_table_data?(src, dst) return false unless src.is_a?(Hash) return false unless dst.is_a?(Hash) (src.to_a - dst.to_a).empty? end
return current option status @return [Hash] current option status
# File lib/flextures/flextures_loader.rb, line 166 def flextures_options @options end
# File lib/flextures/flextures_loader.rb, line 132 def load(params) self.class.load(params) end
# File lib/flextures/flextures_loader.rb, line 124 def loads(*fixtures) # キャッシュが有効 ∧ 呼んだ事無いファイル load_list = self.class.parse_flextures_options(@options, *fixtures) load_list.sort(&self.class.loading_order).each do |params| load(params) end end
called by Rspec or Should set options @params [Hash] options exmple : { cashe: true, dir: “models/users” }
# File lib/flextures/flextures_loader.rb, line 154 def set_options(options) @options.merge!(options) end