Class: ConfigScripts::Seeds::SeedType
- Inherits:
-
Object
- Object
- ConfigScripts::Seeds::SeedType
- Defined in:
- lib/config_scripts/seeds/seed_type.rb
Overview
This class encapsulates information about how to write seeds for a class to a seed file.
Attributes collapse
-
#associations ⇒ Array
readonly
The active record associations for the model class for this seed file.
-
#attributes ⇒ Array<Symbol>
readonly
The names of the attributes on the model object that we store in the seed file.
-
#dynamic_fetcher ⇒ Proc
readonly
The block that will be run when fetching items.
-
#dynamic_readers ⇒ Hash<Symbol, Proc>
readonly
The attributes that we generate dynamically after loading the ones from the seed file.
-
#dynamic_writers ⇒ Hash<Symbol, Proc>
readonly
The attributes that we generate dynamically when writing things to the seed file.
-
#filename ⇒ String
readonly
The name of the file that we will store these records in.
-
#identifier_attributes ⇒ Array<Symbol>
readonly
The names of the attributes used to compose a unique identifier for a record.
-
#klass ⇒ Class
readonly
The model class whose records we are storing in this seed file.
-
#scopes ⇒ Array<Array>
readonly
The scopes that we apply when fetching items.
-
#seed_set ⇒ SeedSet
readonly
The seed set that this type has been defined within.
Creation collapse
-
#initialize(seed_set, klass, filename, &block) ⇒ SeedType
constructor
This method creates a new seed type.
DSL collapse
-
#has_attributes(*new_attributes) ⇒ Array<Symbol>
This method adds new attributes to the ones written in this seed type.
-
#has_identifier_attributes(*attributes) ⇒ Array<Symbol>
This method defines the attributes used to generate a unique identifier for a record.
-
#has_scope(method, *args) ⇒ Array
This method adds a scope to the list used to filter the records for writing.
-
#when_fetching(&block) ⇒ Object
This method registers a custom block that will be run when fetching records.
-
#when_reading(attribute, &block) ⇒ Object
This method registers a custom block that will be run when reading a value from the seed file.
-
#when_writing(attribute, &block) ⇒ Object
This method registers a custom block that will be run when writing a value to the seed file.
Reading and Writing collapse
-
#read_from_folder(folder) ⇒ Object
This method reads the seed data from a file, and creates new records from it.
-
#read_value_for_association(attribute, identifier) ⇒ ActiveRecord::Base
This method gets the value that we will assign to an attribute for an association.
-
#read_value_for_attribute(value, attribute) ⇒ Object
This method takes a value from the CSV file and gives back the value that should be set on the record.
-
#write_to_folder(folder) ⇒ Object
This method writes the seed data file to a folder.
-
#write_value_for_attribute(item, attribute) ⇒ String
This method gets the value that we should write into the CSV file for an attribute.
Fetching collapse
-
#all ⇒ Relation
This method gets a relation encompassing all the records in the class.
-
#items ⇒ Relation
This method gets the items that we should write to our seed file.
-
#options ⇒ Hash
This method gets the additional information passed in when defining our seed set.
Seed Identifiers collapse
-
#record_for_seed_identifier(identifier) ⇒ ActiveRecord::Base
This method finds a record for our model class based on the unique seed identifier.
-
#seed_identifier_for_record(record) ⇒ String
This method gets the unique identifier for a record of the class that this seed type handles.
Constructor Details
#initialize(seed_set, klass, filename, &block) ⇒ SeedType
This method creates a new seed type.
This method should be given a block, which will be run in the instance context of the new seed type. That block should use the DSL methods to fill in the details for the seed type.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 75 def initialize(seed_set, klass, filename, &block) @seed_set = seed_set @klass = klass @filename = filename @attributes = [] @identifier_attributes = [:id] @scopes = [] @dynamic_writers = {} @dynamic_readers = {} @associations = {} @klass.reflect_on_all_associations.each do |association| @associations[association.name] = association.klass rescue nil end self.instance_eval(&block) if block_given? end |
Instance Attribute Details
#associations ⇒ Array (readonly)
The active record associations for the model class for this seed file.
34 35 36 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 34 def associations @associations end |
#attributes ⇒ Array<Symbol> (readonly)
The names of the attributes on the model object that we store in the seed file.
25 26 27 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 25 def attributes @attributes end |
#dynamic_fetcher ⇒ Proc (readonly)
The block that will be run when fetching items.
48 49 50 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 48 def dynamic_fetcher @dynamic_fetcher end |
#dynamic_readers ⇒ Hash<Symbol, Proc> (readonly)
The attributes that we generate dynamically after loading the ones from the seed file.
39 40 41 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 39 def dynamic_readers @dynamic_readers end |
#dynamic_writers ⇒ Hash<Symbol, Proc> (readonly)
The attributes that we generate dynamically when writing things to the seed file.
44 45 46 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 44 def dynamic_writers @dynamic_writers end |
#filename ⇒ String (readonly)
The name of the file that we will store these records in.
20 21 22 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 20 def filename @filename end |
#identifier_attributes ⇒ Array<Symbol> (readonly)
The names of the attributes used to compose a unique identifier for a record.
30 31 32 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 30 def identifier_attributes @identifier_attributes end |
#klass ⇒ Class (readonly)
The model class whose records we are storing in this seed file.
16 17 18 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 16 def klass @klass end |
#scopes ⇒ Array<Array> (readonly)
The scopes that we apply when fetching items.
Each entry will be an array. The first entry in the inner arrays will be a symbol, the name of a method that can be run on a relation. The result of the array will be passed in when running the method on the scope.
57 58 59 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 57 def scopes @scopes end |
#seed_set ⇒ SeedSet (readonly)
The seed set that this type has been defined within.
12 13 14 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 12 def seed_set @seed_set end |
Instance Method Details
#all ⇒ Relation
This method gets a relation encompassing all the records in the class.
We encapsulate this here so that we can use different calls in Rails 3 and Rails 4.
320 321 322 323 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 320 def all version = Rails.version[0] records = version == '3' ? self.klass.scoped : self.klass.all end |
#has_attributes(*new_attributes) ⇒ Array<Symbol>
This method adds new attributes to the ones written in this seed type.
102 103 104 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 102 def has_attributes(*new_attributes) @attributes += new_attributes end |
#has_identifier_attributes(*attributes) ⇒ Array<Symbol>
This method defines the attributes used to generate a unique identifier for a record.
114 115 116 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 114 def has_identifier_attributes(*attributes) @identifier_attributes = attributes end |
#has_scope(method, *args) ⇒ Array
This method adds a scope to the list used to filter the records for writing.
130 131 132 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 130 def has_scope(method, *args) @scopes << [method, args] end |
#items ⇒ Relation
This method gets the items that we should write to our seed file.
It will start with the scoped list for the model class, and then apply all the scopes in our #scopes list.
330 331 332 333 334 335 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 330 def items return @dynamic_fetcher.call if @dynamic_fetcher records = self.all self.scopes.each { |method, args| records = records.send(method, *args) } records end |
#options ⇒ Hash
This method gets the additional information passed in when defining our seed set.
341 342 343 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 341 def self.seed_set. end |
#read_from_folder(folder) ⇒ Object
This method reads the seed data from a file, and creates new records from it.
This will extract all the rows from the CSV file, and use #read_value_for_attribute to get the attributes for the record from each cell in the CSV file.
If this seed type has no attributes, this method will not try to read the file.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 202 def read_from_folder(folder) return unless attributes.any? CSV.open(File.join(folder, "#{self.filename}.csv"), headers: true) do |csv| csv.each do |row| record = self.klass.new row.each do |attribute, value| attribute = attribute.to_sym value = self.read_value_for_attribute(value, attribute) record.send("#{attribute}=", value) end begin record.save! rescue puts "#{self.filename}.csv" puts "#{row}" raise end end end end |
#read_value_for_association(attribute, identifier) ⇒ ActiveRecord::Base
This method gets the value that we will assign to an attribute for an association.
This will remove as many entries from the identifier as it needs to get the value.
303 304 305 306 307 308 309 310 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 303 def read_value_for_association(attribute, identifier) klass = @associations[attribute] unless klass class_name = identifier.shift klass = class_name.constantize end value = self.seed_set.record_for_seed_identifier(klass, identifier) end |
#read_value_for_attribute(value, attribute) ⇒ Object
This method takes a value from the CSV file and gives back the value that should be set on the record.
If the attribute is an association, this will pass it to the seed set as a seed identifier. If it is a polymorphic association, it will use the first part of the seed identifier as a class name.
278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 278 def read_value_for_attribute(value, attribute) if @dynamic_readers[attribute] value = @dynamic_readers[attribute].call(value) end if @associations.has_key?(attribute) return nil if value.blank? value = self.read_value_for_association(attribute, value.split("::")) end value end |
#record_for_seed_identifier(identifier) ⇒ ActiveRecord::Base
This method finds a record for our model class based on the unique seed identifier.
367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 367 def record_for_seed_identifier(identifier) return nil if identifier.blank? records = self.all self.identifier_attributes.each_with_index do |attribute, index| if self.associations.has_key?(attribute) value = self.read_value_for_association(attribute, identifier) records = records.where("#{attribute}_id" => value.try(:id)) else value = self.read_value_for_attribute(identifier.shift, attribute) records = records.where(attribute => value) end end records.first end |
#seed_identifier_for_record(record) ⇒ String
This method gets the unique identifier for a record of the class that this seed type handles.
355 356 357 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 355 def seed_identifier_for_record(record) self.identifier_attributes.collect { |param| self.write_value_for_attribute(record, param) }.join("::") end |
#when_fetching(&block) ⇒ Object
This method registers a custom block that will be run when fetching records.
162 163 164 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 162 def when_fetching(&block) @dynamic_fetcher = block end |
#when_reading(attribute, &block) ⇒ Object
This method registers a custom block that will be run when reading a value from the seed file.
This method takes a block that will be run on the value from the seed file. The return value of the block will be used in place of the original value from the seed file.
143 144 145 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 143 def when_reading(attribute, &block) @dynamic_readers[attribute] = block end |
#when_writing(attribute, &block) ⇒ Object
This method registers a custom block that will be run when writing a value to the seed file.
This method takes a block that will be run on the item whose values we are writing. The return value of the block will be used instead of running the method on the record.
156 157 158 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 156 def when_writing(attribute, &block) @dynamic_writers[attribute] = block end |
#write_to_folder(folder) ⇒ Object
This method writes the seed data file to a folder.
This will write a header row with the names of the attributes, and then write a row for each item from the #items method. It will use the #write_value_for_attribute method to get the values for the CSV file.
If this seed type has no attributes, this method will not write anything.
179 180 181 182 183 184 185 186 187 188 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 179 def write_to_folder(folder) return unless attributes.any? CSV.open(File.join(folder, "#{self.filename}.csv"), 'w') do |csv| csv << self.attributes self.items.each do |item| data = self.attributes.collect { |attribute| self.write_value_for_attribute(item, attribute) } csv << data end end end |
#write_value_for_attribute(item, attribute) ⇒ String
This method gets the value that we should write into the CSV file for an attribute.
If the value for that attribute is another model record, this will get its seed identifier from the seed set. Otherwise, it will just use the value.
If the attribute is a polymorphic foreign key, this will prefix the seed identifier with the class name.
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/config_scripts/seeds/seed_type.rb', line 242 def write_value_for_attribute(item, attribute) if @dynamic_writers[attribute] value = @dynamic_writers[attribute].call(item) else value = item.send(attribute) end if value.is_a?(ActiveRecord::Base) identifier = self.seed_set.seed_identifier_for_record(value) if !self.associations[attribute] identifier = "#{value.class.name}::#{identifier}" end value = identifier elsif value.is_a?(TrueClass) value = '1' elsif value.is_a?(FalseClass) value = '0' end value end |