Commit 87d7ed404acf7ee97f4b1c5b6178a24bb73daed3

Authored by ikeqiao
0 parents
Exists in master

create from has_magic_columns

.gitignore 0 → 100644
  1 +++ a/.gitignore
... ... @@ -0,0 +1,18 @@
  1 +*.gem
  2 +*.rbc
  3 +.bundle
  4 +.config
  5 +.yardoc
  6 +Gemfile.lock
  7 +InstalledFiles
  8 +_yardoc
  9 +coverage
  10 +doc/
  11 +lib/bundler/man
  12 +pkg
  13 +rdoc
  14 +spec/reports
  15 +test/tmp
  16 +test/version_tmp
  17 +tmp
  18 +log
... ...
.rspec 0 → 100644
  1 +++ a/.rspec
... ... @@ -0,0 +1 @@
  1 +--color --format documentation
... ...
Gemfile 0 → 100644
  1 +++ a/Gemfile
... ... @@ -0,0 +1,8 @@
  1 +source "http://ruby.taobao.org"
  2 +
  3 +gem 'rails', ' >= 4.0.0'
  4 +
  5 +group :test do
  6 + gem 'rspec-rails', ' >= 3.0.0'
  7 + gem 'sqlite3'
  8 +end
... ...
LICENSE.txt 0 → 100644
  1 +++ a/LICENSE.txt
... ... @@ -0,0 +1,22 @@
  1 +Copyright (c) 2014 ikeqiao
  2 +
  3 +MIT License
  4 +
  5 +Permission is hereby granted, free of charge, to any person obtaining
  6 +a copy of this software and associated documentation files (the
  7 +"Software"), to deal in the Software without restriction, including
  8 +without limitation the rights to use, copy, modify, merge, publish,
  9 +distribute, sublicense, and/or sell copies of the Software, and to
  10 +permit persons to whom the Software is furnished to do so, subject to
  11 +the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be
  14 +included in all copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
... ...
README.md 0 → 100644
  1 +++ a/README.md
... ... @@ -0,0 +1,29 @@
  1 +# HasMagicFields
  2 +
  3 +TODO: Write a gem description
  4 +
  5 +## Installation
  6 +
  7 +Add this line to your application's Gemfile:
  8 +
  9 + gem 'has_magic_fields'
  10 +
  11 +And then execute:
  12 +
  13 + $ bundle
  14 +
  15 +Or install it yourself as:
  16 +
  17 + $ gem install has_magic_fields
  18 +
  19 +## Usage
  20 +
  21 +TODO: Write usage instructions here
  22 +
  23 +## Contributing
  24 +
  25 +1. Fork it
  26 +2. Create your feature branch (`git checkout -b my-new-feature`)
  27 +3. Commit your changes (`git commit -am 'Add some feature'`)
  28 +4. Push to the branch (`git push origin my-new-feature`)
  29 +5. Create new Pull Request
... ...
Rakefile 0 → 100644
  1 +++ a/Rakefile
... ... @@ -0,0 +1,7 @@
  1 +require 'rake'
  2 +require "rspec"
  3 +require File.expand_path('../spec/spec_helper', __FILE__)
  4 +
  5 +task :default do
  6 + system 'bundle exec rspec spec'
  7 +end
0 8 \ No newline at end of file
... ...
has_magic_fields.gemspec 0 → 100644
  1 +++ a/has_magic_fields.gemspec
... ... @@ -0,0 +1,25 @@
  1 +# coding: utf-8
  2 +lib = File.expand_path('../lib', __FILE__)
  3 +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
  4 +require 'has_magic_fields/version'
  5 +
  6 +Gem::Specification.new do |s|
  7 + s.name = "has_magic_fields"
  8 + s.version = HasMagicFields::VERSION
  9 + s.authors = ["ikeqiao"]
  10 + s.email = ["zhzsi@126.com"]
  11 + s.description = %q{TODO: Write a gem description}
  12 + s.summary = %q{TODO: Write a gem summary}
  13 + s.homepage = ""
  14 + s.license = "MIT"
  15 +
  16 + s.files = `git ls-files`.split($/)
  17 + s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
  18 + s.test_files = s.files.grep(%r{^(test|s|features)/})
  19 + s.require_paths = ["lib"]
  20 +
  21 + s.add_development_dependency "bundler", "~> 1.3"
  22 + s.add_development_dependency "rake"
  23 + s.add_dependency("rails", [">= 4.0.0"])
  24 +
  25 +end
... ...
lib/generators/has_magic_fields/install/USAGE 0 → 100644
  1 +++ a/lib/generators/has_magic_fields/install/USAGE
... ... @@ -0,0 +1,8 @@
  1 +Description:
  2 + Add a migration for has_magic_fields.
  3 +
  4 +Example:
  5 + rails generate has_magic_fields:install
  6 +
  7 + This will create:
  8 + db/migrate/XXX_add_has_magic_fields_tables.rb
... ...
lib/generators/has_magic_fields/install/install_generator.rb 0 → 100644
  1 +++ a/lib/generators/has_magic_fields/install/install_generator.rb
... ... @@ -0,0 +1,24 @@
  1 +require 'rails/generators/base'
  2 +
  3 +module HasMagicFields
  4 + class InstallGenerator < Rails::Generators::Base
  5 + include Rails::Generators::Migration
  6 +
  7 + source_root File.expand_path('../templates',__FILE__)
  8 +
  9 + desc "Add has_magic_fields migration."
  10 +
  11 + def self.next_migration_number(path)
  12 + unless @prev_migration_nr
  13 + @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
  14 + else
  15 + @prev_migration_nr += 1
  16 + end
  17 + @prev_migration_nr.to_s
  18 + end
  19 +
  20 + def add_migration
  21 + migration_template "migration.rb", "db/migrate/add_has_magic_fields_tables.rb"
  22 + end
  23 + end
  24 +end
... ...
lib/generators/has_magic_fields/install/templates/migration.rb 0 → 100644
  1 +++ a/lib/generators/has_magic_fields/install/templates/migration.rb
... ... @@ -0,0 +1,51 @@
  1 +class AddHasMagicFieldsTables < ActiveRecord::Migration
  2 + def change
  3 + create_table :magic_fields do |t|
  4 + t.column :name, :string
  5 + t.column :pretty_name, :string
  6 + t.column :datatype, :string, :default => "string"
  7 + t.column :default, :string
  8 + t.column :is_required, :boolean, :default => false
  9 + t.column :include_blank, :boolean, :default => false
  10 + t.column :allow_other, :boolean, :default => true
  11 + t.column :created_at, :datetime
  12 + t.column :updated_at, :datetime
  13 + end
  14 +
  15 + create_table :magic_attributes do |t|
  16 + t.column :magic_field_id, :integer
  17 + t.column :magic_option_id, :integer
  18 + t.column :value, :string
  19 + t.column :created_at, :datetime
  20 + t.column :updated_at, :datetime
  21 + end
  22 +
  23 + create_table :magic_options do |t|
  24 + t.column :magic_field_id, :integer
  25 + t.column :value, :string
  26 + t.column :synonym, :string
  27 + t.column :created_at, :datetime
  28 + t.column :updated_at, :datetime
  29 + end
  30 +
  31 + create_table :magic_field_relationships do |t|
  32 + t.column :magic_field_id, :integer
  33 + t.column :owner_id, :integer
  34 + t.column :owner_type, :string
  35 + t.column :created_at, :datetime
  36 + t.column :updated_at, :datetime
  37 + end
  38 +
  39 + create_table :magic_attribute_relationships do |t|
  40 + t.column :magic_attribute_id, :integer
  41 + t.column :owner_id, :integer
  42 + t.column :owner_type, :string
  43 + end
  44 +
  45 + add_index :magic_attributes, [:magic_field_id, :magic_option_id], name:"attributes_column_option"
  46 + add_index :magic_attribute_relationships, [:magic_attribute_id, :owner_id], name:"magic_attribute_owner"
  47 + add_index :magic_field_relationships, [:magic_field_id, :owner_id], name:"magic_field_owner"
  48 +
  49 + end
  50 +
  51 +end
0 52 \ No newline at end of file
... ...
lib/has_magic_fields.rb 0 → 100644
  1 +++ a/lib/has_magic_fields.rb
... ... @@ -0,0 +1,10 @@
  1 +require "has_magic_fields/version"
  2 +require "has_magic_fields/models/magic_attribute"
  3 +require "has_magic_fields/models/magic_field"
  4 +require "has_magic_fields/models/magic_option"
  5 +require "has_magic_fields/models/magic_attribute_relationship"
  6 +require "has_magic_fields/models/magic_field_relationship"
  7 +require "has_magic_fields/extend"
  8 +
  9 +
  10 +
... ...
lib/has_magic_fields/extend.rb 0 → 100644
  1 +++ a/lib/has_magic_fields/extend.rb
... ... @@ -0,0 +1,173 @@
  1 +module HasMagicFields
  2 + module Extend extend ActiveSupport::Concern
  3 + module ClassMethods
  4 + def has_magic_fields(options = {})
  5 + # Associations
  6 + has_many :magic_attribute_relationships, :as => :owner, :dependent => :destroy
  7 + has_many :magic_attributes, :through => :magic_attribute_relationships, :dependent => :destroy
  8 +
  9 + # Eager loading - EXPERIMENTAL!
  10 + if options[:eager]
  11 + class_eval do
  12 + def after_initialize
  13 + initialize_magic_fields
  14 + end
  15 + end
  16 + end
  17 +
  18 + # Inheritence
  19 + cattr_accessor :inherited_from
  20 +
  21 + # if options[:through] is supplied, treat as an inherited relationship
  22 + if self.inherited_from = options[:through]
  23 + class_eval do
  24 + def inherited_magic_fields
  25 + raise "Cannot inherit MagicFields from a non-existant association: #{@inherited_from}" unless self.class.method_defined?(inherited_from)# and self.send(inherited_from)
  26 + self.send(inherited_from).magic_fields
  27 + end
  28 + end
  29 + alias_method :magic_fields, :inherited_magic_fields unless method_defined? :magic_fields
  30 +
  31 + # otherwise the calling model has the relationships
  32 + else
  33 + has_many :magic_field_relationships, :as => :owner, :dependent => :destroy
  34 + has_many :magic_fields, :through => :magic_field_relationships, :dependent => :destroy
  35 + end
  36 +
  37 + # # Hook into Base
  38 + class_eval do
  39 + alias_method :reload_without_magic, :reload
  40 + alias_method :create_or_update_without_magic, :create_or_update
  41 + alias_method :read_attribute_without_magic, :read_attribute
  42 + end
  43 +
  44 +
  45 + # Add Magic to Base
  46 + alias_method :reload, :reload_with_magic
  47 + alias_method :read_attribute, :read_attribute_with_magic
  48 + alias_method :create_or_update, :create_or_update_with_magic
  49 + end
  50 + end
  51 +
  52 + included do
  53 + # Reinitialize MagicFields and MagicAttributes when Model is reloaded
  54 + def reload_with_magic
  55 + initialize_magic_fields
  56 + reload_without_magic
  57 + end
  58 +
  59 + def update_attributes(new_attributes)
  60 + attributes = new_attributes.stringify_keys
  61 + magic_attrs = magic_fields.map(&:name)
  62 +
  63 + super(attributes.select{ |k, v| !magic_attrs.include?(k) })
  64 + attributes.select{ |k, v| magic_attrs.include?(k) }.each do |k, v|
  65 + col = find_magic_field_by_name(k)
  66 + attr = find_magic_attribute_by_column(col).first
  67 + attr.update_attributes(:value => v)
  68 + end
  69 + end
  70 +
  71 + private
  72 +
  73 + # Save MagicAttributes from @attributes
  74 + def create_or_update_with_magic
  75 + if result = create_or_update_without_magic
  76 + magic_fields.each do |column|
  77 + value = @attributes[column.name]
  78 + existing = find_magic_attribute_by_column(column)
  79 +
  80 + unless column.datatype == 'check_box_multiple'
  81 + (attr = existing.first) ?
  82 + update_magic_attribute(attr, value) :
  83 + create_magic_attribute(column, value)
  84 + else
  85 + #TODO - make this more efficient
  86 + value = [value] unless value.is_a? Array
  87 + existing.map(&:destroy) if existing
  88 + value.collect {|v| create_magic_attribute(column, v)}
  89 + end
  90 + end
  91 + end
  92 + result
  93 + end
  94 +
  95 + # Load (lazily) MagicAttributes or fall back
  96 + def method_missing(method_id, *args)
  97 + super(method_id, *args)
  98 + rescue NoMethodError
  99 + method_name = method_id.to_s
  100 + attr_names = magic_fields.map(&:name)
  101 + initialize_magic_fields and retry if attr_names.include?(method_name) or
  102 + (md = /[\?|\=]/.match(method_name) and
  103 + attr_names.include?(md.pre_match))
  104 + super(method_id, *args)
  105 + end
  106 +
  107 + # Load the MagicAttribute(s) associated with attr_name and cast them to proper type.
  108 + def read_attribute_with_magic(attr_name)
  109 + return read_attribute_without_magic(attr_name) if column_for_attribute(attr_name) # filter for regular columns
  110 + attr_name = attr_name.to_s
  111 +
  112 + if !(value = @attributes[attr_name]).nil?
  113 + if column = find_magic_field_by_name(attr_name)
  114 + if value.is_a? Array
  115 + value.map {|v| column.type_cast(v)}
  116 + else
  117 + column.type_cast(value)
  118 + end
  119 + else
  120 + value
  121 + end
  122 + else
  123 + nil
  124 + end
  125 + end
  126 +
  127 + # Lookup all MagicAttributes and setup @attributes
  128 + def initialize_magic_fields
  129 + magic_fields.each do |column|
  130 + attribute = find_magic_attribute_by_column(column)
  131 + name = column.name
  132 +
  133 + # Validation
  134 + self.class.validates_presence_of(name) if column.is_required?
  135 +
  136 + # Write attribute
  137 + unless column.datatype == 'check_box_multiple'
  138 + (attr = attribute.first) ?
  139 + write_magic_attribute(name, attr.to_s) :
  140 + write_magic_attribute(name, column.default)
  141 + else
  142 + write_magic_attribute(name, attribute.map(&:to_s))
  143 + end
  144 + end
  145 + end
  146 +
  147 +
  148 + def write_magic_attribute(magic_attribute, value)
  149 + @attributes[magic_attribute] = value
  150 + @attributes_cache[magic_attribute] = value
  151 + end
  152 +
  153 + def find_magic_attribute_by_column(column)
  154 + magic_attributes.to_a.find_all {|attr| attr.magic_field_id == column.id}
  155 + end
  156 +
  157 + def find_magic_field_by_name(attr_name)
  158 + magic_fields.to_a.find {|column| column.name == attr_name}
  159 + end
  160 +
  161 + def create_magic_attribute(magic_field, value)
  162 + magic_attributes << MagicAttribute.create(:magic_field => magic_field, :value => value)
  163 + end
  164 +
  165 + def update_magic_attribute(magic_attribute, value)
  166 + magic_attribute.update_attributes(:value => value)
  167 + end
  168 + end
  169 +
  170 + end
  171 +end
  172 +
  173 +
... ...
lib/has_magic_fields/models/magic_attribute.rb 0 → 100644
  1 +++ a/lib/has_magic_fields/models/magic_attribute.rb
... ... @@ -0,0 +1,29 @@
  1 +# Always work through the interface MagicAttribute.value
  2 +class MagicAttribute < ActiveRecord::Base
  3 + belongs_to :magic_field
  4 + belongs_to :magic_option
  5 +
  6 + before_save :update_magic
  7 +
  8 + def to_s
  9 + (magic_option) ? magic_option.value : value
  10 + end
  11 +
  12 + def update_magic
  13 + if option = find_magic_option_for(value)
  14 + unless magic_option and magic_option == option
  15 + self.value = nil
  16 + self.magic_option = option
  17 + end
  18 + elsif magic_field.allow_other
  19 + self.magic_option = nil
  20 + end
  21 + end
  22 +
  23 +private
  24 +
  25 + def find_magic_option_for(value)
  26 + magic_field.magic_options.find(:first,
  27 + :conditions => ["value = ? or synonym = ?", value, value]) unless magic_field.nil? or magic_field.magic_options.blank?
  28 + end
  29 +end
... ...
lib/has_magic_fields/models/magic_attribute_relationship.rb 0 → 100644
  1 +++ a/lib/has_magic_fields/models/magic_attribute_relationship.rb
... ... @@ -0,0 +1,4 @@
  1 +class MagicAttributeRelationship < ActiveRecord::Base
  2 + belongs_to :magic_attribute
  3 + belongs_to :owner, :polymorphic => true
  4 +end
... ...
lib/has_magic_fields/models/magic_field.rb 0 → 100644
  1 +++ a/lib/has_magic_fields/models/magic_field.rb
... ... @@ -0,0 +1,54 @@
  1 +class MagicField < ActiveRecord::Base
  2 + has_many :magic_field_relationships
  3 + has_many :owners, :through => :magic_field_relationships, :as => :owner
  4 + has_many :magic_options
  5 + has_many :magic_attributes, :dependent => :destroy
  6 +
  7 + validates_presence_of :name, :datatype
  8 + validates_format_of :name, :with => /\A[a-z][a-z0-9_]+\z/
  9 +
  10 + def type_cast(value)
  11 + begin
  12 + case datatype.to_sym
  13 + when :check_box_boolean
  14 + (value.to_int == 1) ? true : false
  15 + when :date
  16 + Date.parse(value)
  17 + when :datetime
  18 + Time.parse(value)
  19 + when :integer
  20 + value.to_int
  21 + else
  22 + value
  23 + end
  24 + rescue
  25 + value
  26 + end
  27 + end
  28 +
  29 + # Display a nicer (possibly user-defined) name for the column or use a fancified default.
  30 + def pretty_name
  31 + super || name.humanize
  32 + end
  33 +
  34 + #get or set a variable with the variable as the called method
  35 + def self.method_missing(method, *args)
  36 + debugger
  37 +
  38 + method_name = method.to_s
  39 + super(method, *args)
  40 + rescue NoMethodError
  41 + debugger
  42 + #set a value for a variable
  43 + if method_name =~ /=$/
  44 + var_name = method_name.gsub('=', '')
  45 + value = args.first
  46 + self[var_name] = value
  47 + #retrieve a value
  48 + else
  49 + self[method_name]
  50 + end
  51 + end
  52 +
  53 +
  54 +end
... ...
lib/has_magic_fields/models/magic_field_relationship.rb 0 → 100644
  1 +++ a/lib/has_magic_fields/models/magic_field_relationship.rb
... ... @@ -0,0 +1,5 @@
  1 +class MagicFieldRelationship < ActiveRecord::Base
  2 + belongs_to :magic_field
  3 + belongs_to :owner, :polymorphic => true
  4 + #belongs_to :extended_model, :polymorphic => true
  5 +end
... ...
lib/has_magic_fields/models/magic_option.rb 0 → 100644
  1 +++ a/lib/has_magic_fields/models/magic_option.rb
... ... @@ -0,0 +1,7 @@
  1 +class MagicOption < ActiveRecord::Base
  2 + belongs_to :magic_field
  3 +
  4 + validates_presence_of :value
  5 + validates_uniqueness_of :value, :scope => :magic_field_id
  6 + validates_uniqueness_of :synonym, :scope => :magic_field_id, :if => Proc.new{|this| !this.synonym.nil? and !this.synonym.empty?}
  7 +end
0 8 \ No newline at end of file
... ...
lib/has_magic_fields/version.rb 0 → 100644
  1 +++ a/lib/has_magic_fields/version.rb
... ... @@ -0,0 +1,3 @@
  1 +module HasMagicFields
  2 + VERSION = "0.0.1"
  3 +end
... ...
rails/init.rb 0 → 100644
  1 +++ a/rails/init.rb
... ... @@ -0,0 +1 @@
  1 +require 'has_magic_fields'
... ...
spec/has_magic_fields/magic_fileds_spec.rb 0 → 100644
  1 +++ a/spec/has_magic_fields/magic_fileds_spec.rb
... ... @@ -0,0 +1,105 @@
  1 +require 'spec_helper'
  2 +
  3 +
  4 +describe HasMagicFields do
  5 +
  6 + context "on a single model" do
  7 + before(:each) do
  8 + @charlie = Person.create(name: "charlie")
  9 + end
  10 +
  11 + it "initializes magic fields correctly" do
  12 + expect(@charlie).not_to be(nil)
  13 + expect(@charlie.class).to be(Person)
  14 + expect(@charlie.magic_fields).not_to be(nil)
  15 + end
  16 +
  17 + it "allows adding a magic field" do
  18 + @charlie.magic_fields.create(:name => 'salary')
  19 + expect(@charlie.magic_fields.length).to be(1)
  20 + end
  21 +
  22 + it "allows setting and saving of magic attributes" do
  23 + @charlie.magic_fields.create(:name => 'salary')
  24 + @charlie.salary = 50000
  25 + @charlie.save
  26 + @charlie = Person.find(@charlie.id)
  27 + expect(@charlie.salary).not_to be(nil)
  28 + end
  29 +
  30 + # it "forces required if is_required is true" do
  31 + # # TODO figure out why this fails
  32 + # @charlie.magic_fields.create(:name => "last_name", :is_required => true)
  33 + # expect(@charlie.save).to be(false)
  34 + # end
  35 +
  36 + it "allows datatype to be :date" do
  37 + @charlie.magic_fields.create(:name => "birthday", :datatype => :date)
  38 + @charlie.birthday = Date.today
  39 + expect(@charlie.save).to be(true)
  40 + end
  41 +
  42 + it "allows datatype to be :datetime" do
  43 + @charlie.magic_fields.create(:name => "signed_up_at", :datatype => :datetime)
  44 + @charlie.signed_up_at = DateTime.now
  45 + expect(@charlie.save).to be(true)
  46 + end
  47 +
  48 + it "allows datatype to be :integer" do
  49 + @charlie.magic_fields.create(:name => "age", :datatype => :integer)
  50 + @charlie.age = 5
  51 + expect(@charlie.save).to be(true)
  52 + end
  53 +
  54 + it "allows datatype to be :check_box_boolean" do
  55 + @charlie.magic_fields.create(:name => "retired", :datatype => :check_box_boolean)
  56 + @charlie.retired = false
  57 + expect(@charlie.save).to be(true)
  58 + end
  59 +
  60 + it "allows default to be set" do
  61 + @charlie.magic_fields.create(:name => "bonus", :default => "40000")
  62 + expect(@charlie.bonus).to eq("40000")
  63 + end
  64 +
  65 + it "allows a pretty display name to be set" do
  66 + @charlie.magic_fields.create(:name => "zip", :pretty_name => "Zip Code")
  67 + expect(@charlie.magic_fields.last.pretty_name).to eq("Zip Code")
  68 + end
  69 + end
  70 +
  71 + context "in a parent-child relationship" do
  72 + before(:each) do
  73 + @account = Account.create(name:"important")
  74 + @alice = User.create(name:"alice", account: @account )
  75 + end
  76 +
  77 + it "initializes magic fields correctly" do
  78 + expect(@alice).not_to be(nil)
  79 + expect(@alice.class).to be(User)
  80 + expect(@alice.magic_fields).not_to be(nil)
  81 +
  82 + expect(@account).not_to be(nil)
  83 + expect(@account.class).to be(Account)
  84 + expect(@alice.magic_fields).not_to be(nil)
  85 + end
  86 +
  87 + it "allows adding a magic field to the child" do
  88 + @alice.magic_fields.create(:name => 'salary')
  89 + expect(lambda{@alice.salary}).not_to raise_error
  90 + expect(lambda{@account.reload_with_magic.salary}).not_to raise_error
  91 + end
  92 +
  93 + it "allows adding a magic field to the parent" do
  94 + @account.magic_fields.create(:name => 'age')
  95 + expect(lambda{@alice.reload_with_magic.age}).not_to raise_error
  96 + end
  97 +
  98 + it "sets magic fields for all child models" do
  99 + @bob = User.create(name:"bob", account: @account )
  100 + @bob.magic_fields.create(:name => 'birthday')
  101 + @alice.reload_with_magic
  102 + expect(lambda{@alice.birthday}).not_to raise_error
  103 + end
  104 + end
  105 +end
... ...
spec/spec_helper.rb 0 → 100644
  1 +++ a/spec/spec_helper.rb
... ... @@ -0,0 +1,108 @@
  1 +require 'rubygems'
  2 +require "active_record"
  3 +require 'active_support'
  4 +require 'sqlite3'
  5 +require 'active_record/fixtures'
  6 +require 'debugger'
  7 +
  8 +
  9 +$LOAD_PATH.unshift(File.dirname(__FILE__))
  10 +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'rails'))
  11 +require "init"
  12 +
  13 +require "rails/railtie"
  14 +
  15 +# ActiveRecord::Base.logger = Logger.new(STDOUT)
  16 +ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
  17 +# ActiveRecord::Base.configurations = true
  18 +
  19 +ActiveRecord::Schema.verbose = false
  20 +
  21 +ActiveRecord::Schema.define do
  22 +
  23 + create_table "users", :force => true do |t|
  24 + t.column "name", :text
  25 + t.column "account_id", :integer
  26 + end
  27 +
  28 + create_table "accounts", :force => true do |t|
  29 + t.column "name", :text
  30 + end
  31 +
  32 + create_table "people", :force => true do |t|
  33 + t.column "name", :text
  34 + end
  35 +
  36 +
  37 + # Has Magic Columns migration generator output
  38 +
  39 + create_table :magic_fields do |t|
  40 + t.column :name, :string
  41 + t.column :pretty_name, :string
  42 + t.column :datatype, :string, :default => "string"
  43 + t.column :default, :string
  44 + t.column :is_required, :boolean, :default => false
  45 + t.column :include_blank, :boolean, :default => false
  46 + t.column :allow_other, :boolean, :default => true
  47 + t.column :created_at, :datetime
  48 + t.column :updated_at, :datetime
  49 + end
  50 +
  51 + create_table :magic_attributes do |t|
  52 + t.column :magic_field_id, :integer
  53 + t.column :magic_option_id, :integer
  54 + t.column :value, :string
  55 + t.column :created_at, :datetime
  56 + t.column :updated_at, :datetime
  57 + end
  58 +
  59 + create_table :magic_options do |t|
  60 + t.column :magic_field_id, :integer
  61 + t.column :value, :string
  62 + t.column :synonym, :string
  63 + t.column :created_at, :datetime
  64 + t.column :updated_at, :datetime
  65 + end
  66 +
  67 + create_table :magic_field_relationships do |t|
  68 + t.column :magic_field_id, :integer
  69 + t.column :owner_id, :integer
  70 + t.column :owner_type, :string
  71 + t.column :created_at, :datetime
  72 + t.column :updated_at, :datetime
  73 + end
  74 +
  75 + create_table :magic_attribute_relationships do |t|
  76 + t.column :magic_attribute_id, :integer
  77 + t.column :owner_id, :integer
  78 + t.column :owner_type, :string
  79 + end
  80 +
  81 +end
  82 +
  83 +
  84 +RSpec.configure do |config|
  85 +
  86 + config.before(:all) do
  87 + class Account < ActiveRecord::Base
  88 + include HasMagicFields::Extend
  89 + has_many :users
  90 + has_magic_fields
  91 + end
  92 +
  93 + class Person < ActiveRecord::Base
  94 + include HasMagicFields::Extend
  95 + has_magic_fields
  96 + end
  97 +
  98 + class User < ActiveRecord::Base
  99 + include HasMagicFields::Extend
  100 + belongs_to :account
  101 + has_magic_fields :through => :account
  102 + end
  103 + end
  104 +
  105 + config.after(:all) do
  106 + end
  107 +end
  108 +
... ...