Class: AuxCode
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- AuxCode
- Defined in:
- lib/aux_codes.rb,
lib/aux_codes/aux_code_class.rb
Overview
extend AuxCode to return a full-blown ActiveRecord class
Class Method Summary collapse
- .categories ⇒ Object
- .category(category_object_or_id_or_name) ⇒ Object (also: [])
- .category_code_names(category_object_or_id_or_name) ⇒ Object
- .category_codes(category_object_or_id_or_name) ⇒ Object (also: category_values)
- .category_names ⇒ Object
- .create_classes! ⇒ Object
-
.init ⇒ Object
initialize AuxCodes …
-
.load(hash) ⇒ Object
loads AuxCodes (creates them) from a Hash, keyed on the name of the aux code categories to create.
- .load_file(serialized_yaml_file_path) ⇒ Object
- .load_yaml(yaml_string) ⇒ Object
-
.method_missing_with_indifferent_hash_style_values(name, *args, &block) ⇒ Object
this allows us to say things like:.
Instance Method Summary collapse
- #[](attribute_or_code_name) ⇒ Object
- #aux_code_class(&block) ⇒ Object
- #class_name ⇒ Object
- #code_names ⇒ Object
- #deserialized_meta_hash ⇒ Object
- #get_meta_attribute(meta_attribute) ⇒ Object
- #is_a_category? ⇒ Boolean
-
#method_missing_with_indifferent_hash_style_values(name, *args, &block) ⇒ Object
this allows us to say things like:.
- #set_meta_attribute(meta_attribute, value) ⇒ Object
- #to_s ⇒ Object
Class Method Details
.categories ⇒ Object
108 109 110 |
# File 'lib/aux_codes.rb', line 108 def categories AuxCode.find_all_by_aux_code_id(0) end |
.category(category_object_or_id_or_name) ⇒ Object Also known as: []
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/aux_codes.rb', line 116 def category category_object_or_id_or_name obj = category_object_or_id_or_name return obj if obj.is_a?AuxCode return AuxCode.find(obj) if obj.is_a?Fixnum if obj.is_a?(String) || obj.is_a?(Symbol) obj = obj.to_s found = AuxCode.find_by_name_and_aux_code_id(obj, 0) if found.nil? # try replacing underscores with spaces and doing a 'LIKE' search found = AuxCode.find :first, :conditions => ["name LIKE ? AND aux_code_id = ?", obj.gsub('_', ' '), 0] end return found end raise "I don't know how to find an AuxCode of type #{ obj.class }" end |
.category_code_names(category_object_or_id_or_name) ⇒ Object
138 139 140 |
# File 'lib/aux_codes.rb', line 138 def category_code_names category_object_or_id_or_name category( category_object_or_id_or_name ).code_names end |
.category_codes(category_object_or_id_or_name) ⇒ Object Also known as: category_values
133 134 135 |
# File 'lib/aux_codes.rb', line 133 def category_codes category_object_or_id_or_name category( category_object_or_id_or_name ).codes end |
.category_names ⇒ Object
112 113 114 |
# File 'lib/aux_codes.rb', line 112 def category_names AuxCode.categories.map &:name end |
.create_classes! ⇒ Object
142 143 144 145 146 |
# File 'lib/aux_codes.rb', line 142 def create_classes! AuxCode.categories.each do |category| Kernel::const_set category.class_name, category.aux_code_class end end |
.init ⇒ Object
initialize AuxCodes … looks for config/aux_codes.yml and creates classes
182 183 184 185 186 187 188 189 190 |
# File 'lib/aux_codes.rb', line 182 def init # should eventually take configuration options (hash || block) if ActiveRecord::Base.connection.tables.include? 'aux_codes' aux_codes_yml = File.join 'config', 'aux_codes.yml' if File.file? aux_codes_yml load_file aux_codes_yml create_classes! end end end |
.load(hash) ⇒ Object
loads AuxCodes (creates them) from a Hash, keyed on the name of the aux code categories to create
hash: a Hash or an Array [ [key,value], [key,value] ] or anything with an enumerator
that'll work with `hash.each {|key,value| ... }`
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/aux_codes.rb', line 198 def load hash return unless hash.is_a?Hash hash.each do |category_name, codes| category = AuxCode.find_or_create_by_name( category_name.to_s ).aux_code_class codes.each do |name, values| # only a name given if values.nil? or values.empty? if name.is_a? String or name.is_a? Symbol # we have a String || Symbol, it's likely the code's name, eg. :foo or 'bar' category.create :name => name.to_s unless category.code_names.include?(name.to_s) elsif name.is_a? Hash # we have a Hash, likely with the create options, eg. { :name => 'hi', :foo =>'bar' } category.create name else raise "not sure how to create code in category #{ category.name } with: #{ name.inspect }" end # we have a name and values else if values.is_a? Hash and (name.is_a? String or name.is_a? Symbol) # we have a Hash, likely with the create options ... we'll merge the name in as :name and create code = category[ name.to_s ] if code values.each do |attribute, new_value| code.send "#{attribute}=", new_value # update values end else code = category.create values.merge({ :name => name.to_s }) end else raise "not sure how to create code in category #{ category.name } with: #{ name.inspect }, #{ values.inspect }" end end end end end |
.load_file(serialized_yaml_file_path) ⇒ Object
176 177 178 |
# File 'lib/aux_codes.rb', line 176 def load_file serialized_yaml_file_path load_yaml File.read(serialized_yaml_file_path) end |
.load_yaml(yaml_string) ⇒ Object
171 172 173 174 |
# File 'lib/aux_codes.rb', line 171 def load_yaml yaml_string require 'yaml' self.load YAML::load(yaml_string) end |
.method_missing_with_indifferent_hash_style_values(name, *args, &block) ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/aux_codes.rb', line 154 def method_missing_with_indifferent_hash_style_values name, *args, &block unless self.respond_to?:aux_code_id # in which case, this is a *derived* class, not AuxCode begin method_missing_without_indifferent_hash_style_values name, *args, &block rescue NoMethodError => ex begin self[name] rescue raise ex end end else method_missing_without_indifferent_hash_style_values name, *args, &block end end |
Instance Method Details
#[](attribute_or_code_name) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/aux_codes.rb', line 45 def [] attribute_or_code_name if attributes.include?attribute_or_code_name attributes[attribute_or_code_name] else found = codes.select {|c| c.name.to_s =~ /#{attribute_or_code_name}/ } if found.empty? # try case insensitive (sans underscores) found = codes.select {|c| c.name.downcase.gsub('_',' ').to_s =~ /#{attribute_or_code_name.to_s.downcase.gsub('_',' ')}/ } end found.first if found end end |
#aux_code_class(&block) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/aux_codes/aux_code_class.rb', line 6 def aux_code_class &block klass = Class.new(AuxCode) do class << self attr_accessor :aux_code_id, :aux_code def aux_code # @aux_code ||= AuxCode.find aux_code_id AuxCode.find aux_code_id end def [] code aux_code[code] end # # this handles typical ActiveRecord::Base method_missing features, eg: aux_code.find_by_name 'foo' # # we wrap these methods in the scope of this aux code (category) # def method_missing_with_aux_code_scope name, *args, &block if name.to_s[/^find/] if name.to_s[/or_create_by_/] name = "#{name}_and_aux_code_id".to_sym args << self.aux_code_id # method_missing_without_aux_code_scope name, *args AuxCode.send name, *args, &block else with_scope(:find => { :conditions => ['aux_code_id = ?', self.aux_code_id] }) do method_missing_without_aux_code_scope name, *args, &block end end else method_missing_without_aux_code_scope name, *args, &block end rescue NoMethodError => ex begin aux_code.send name, *args, &block # try on the AuxCode instance for this class ... rescue raise ex end end alias_method_chain :method_missing, :aux_code_scope def count_with_aux_code_scope = {} with_scope(:find => { :conditions => ['aux_code_id = ?', self.aux_code_id] }) do count_without_aux_code_scope end end alias_method_chain :count, :aux_code_scope def find_with_aux_code_scope first_or_all, = {} with_scope(:find => { :conditions => ['aux_code_id = ?', self.aux_code_id] }) do find_without_aux_code_scope first_or_all, end end alias_method_chain :find, :aux_code_scope def create_with_aux_code_scope = {} create_without_aux_code_scope .merge({ :aux_code_id => self.aux_code_id }) end alias_method_chain :create, :aux_code_scope def create_with_aux_code_scope! = {} create_without_aux_code_scope! .merge({ :aux_code_id => self.aux_code_id }) end alias_method_chain :create!, :aux_code_scope def new_with_aux_code_scope = {} begin new_without_aux_code_scope .merge({ :aux_code_id => self.aux_code_id }) rescue ActiveRecord::UnknownAttributeError => ex # we were likely passed some unknown meta attributes ... define them ... = /unknown attribute: (.*)/.match(ex.).captures.first << self. new_with_aux_code_scope # re-call ... WARNING ... might end up in infinite loop! end end alias_method_chain :new, :aux_code_scope end end klass.aux_code_id = self.id # the class needs to know its own aux_code_id # # add custom attributes # klass.class.class_eval do # an array of valid meta attribute names attr_accessor :meta_attributes def *attribute_names @meta_attributes ||= [] @meta_attributes += attribute_names.map {|attribute_name| attribute_name.to_s } @meta_attributes end end # class customizations (if block passed in) klass.class_eval(&block) if block # for each of the meta_attributes defined, create getter and setter methods # # CAUTION: the way we're currently doing this, this'll only work if attr_meta # is set when you initially get the aux_code_class ... adding # meta attributes later won't currently work! # klass.class_eval { def self. self. ||= [] self..each do || unless self.respond_to? define_method() do () end end unless self.respond_to? "#{}=" define_method("#{}=") do |value| (, value) end end end end } # wow, need to clean this up ... klass end |
#class_name ⇒ Object
37 38 39 |
# File 'lib/aux_codes.rb', line 37 def class_name name.gsub(/[^[:alpha:]]/,'_').titleize.gsub(' ','').singularize end |
#code_names ⇒ Object
29 30 31 |
# File 'lib/aux_codes.rb', line 29 def code_names codes.map &:name end |
#deserialized_meta_hash ⇒ Object
58 59 60 61 62 |
# File 'lib/aux_codes.rb', line 58 def require 'yaml' self. ||= "" YAML::load(self.) || { } end |
#get_meta_attribute(meta_attribute) ⇒ Object
64 65 66 |
# File 'lib/aux_codes.rb', line 64 def [.to_s] end |
#is_a_category? ⇒ Boolean
33 34 35 |
# File 'lib/aux_codes.rb', line 33 def is_a_category? aux_code_id == 0 end |
#method_missing_with_indifferent_hash_style_values(name, *args, &block) ⇒ Object
this allows us to say things like:
foo = AuxCode.create :name => 'foo'
foo.codes.create :name => 'bar'
foo.bar # should return the bar aux code under the foo category
if bar doesn't exist, we throw a normal NoMethodError
this should check meta_attributes on the object too
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/aux_codes.rb', line 86 def method_missing_with_indifferent_hash_style_values name, *args, &block method_missing_without_indifferent_hash_style_values name, *args, &block rescue NoMethodError => ex begin if name.to_s[/=$/] self.(name.to_s.sub(/=$/,''), args.first) # we said `code.foo= X` so we should set the foo meta attribute to X save else code = self[name] code = self.(name) unless code raise ex unless code return code end rescue raise ex end end |
#set_meta_attribute(meta_attribute, value) ⇒ Object
68 69 70 71 72 73 |
# File 'lib/aux_codes.rb', line 68 def , value require 'yaml' = [.to_s] = value self. = .to_yaml end |
#to_s ⇒ Object
41 42 43 |
# File 'lib/aux_codes.rb', line 41 def to_s name end |