toy-model 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.swp
6
+ *.sqlite3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in toy-model.gemspec
4
+ gemspec
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new('spec')
@@ -0,0 +1,9 @@
1
+ module ToyModel; end
2
+
3
+ require "toy-model/attributes"
4
+ require "toy-model/attribute_observer"
5
+ require "toy-model/attribute_wrapper"
6
+ require "toy-model/attributes_collection"
7
+ require "toy-model/version"
8
+
9
+ require "toy-model/railtie" if defined? Rails
@@ -0,0 +1,44 @@
1
+ module ToyModel
2
+ class AttributeObserver
3
+
4
+ attr_accessor :attribute
5
+
6
+ def initialize model
7
+ return unless model.respond_to?(:use_toy_model?) && model.use_toy_model?
8
+ @model = model
9
+ unless ActiveRecord::Base.connection.table_exists? @model.table_name
10
+ Class.new(ActiveRecord::Migration).create_table(@model.table_name.to_sym) do |t|
11
+ t.timestamps
12
+ end
13
+ end
14
+ @model.attributes.each do |attribute|
15
+ set_attribute(attribute)
16
+ @model.attr_accessible attribute.column
17
+ @model.attr_accessible :"#{attribute.column}_id" if attribute._as == :belongs_to
18
+ end
19
+ @model.reset_column_information
20
+ end
21
+
22
+ def set_attribute attribute
23
+ return if attribute.skip_table_column?
24
+ add_attribute attribute
25
+ update_attribute attribute
26
+ end
27
+
28
+ def add_attribute attribute
29
+ unless @model.column_names.include? attribute.to_table_column.to_s
30
+ Class.new(ActiveRecord::Migration).add_column @model.table_name.to_sym, attribute.to_table_column, attribute.to_table_type
31
+ end
32
+ end
33
+
34
+ def update_attribute attribute
35
+ column = @model.columns.select{|c| c.name == attribute.to_table_column.to_s}.first
36
+ if column && column.type != attribute.to_table_type
37
+ Class.new(ActiveRecord::Migration).change_column @model.table_name, attribute.to_table_column, attribute.to_table_type
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,45 @@
1
+ module ToyModel
2
+ class AttributeWrapper
3
+
4
+ attr_accessor :column, :parent, :_as, :_helper, :_options
5
+
6
+ def initialize column, parent
7
+ @column = column
8
+ @parent = parent
9
+ @_as = :string
10
+ end
11
+
12
+ def as value
13
+ @_as = value
14
+ enforce_relations
15
+ self
16
+ end
17
+
18
+ def enforce_relations
19
+ @parent.send @_as, @column if [:has_many, :has_and_belongs_to_many, :has_one, :belongs_to].include? @_as
20
+ if [:has_many, :has_one].include? @_as
21
+ related = @column.to_s.singularize.classify.constantize
22
+ related.attribute(@parent.to_s.underscore.gsub(' ', '_').to_sym).as(:belongs_to)
23
+ ToyModel::AttributeObserver.new related
24
+ end
25
+ end
26
+
27
+ def to_table_column
28
+ return nil if skip_table_column?
29
+ return :"#{@column}_id" if @_as == :belongs_to
30
+ @column
31
+ end
32
+
33
+ def to_table_type
34
+ return nil if skip_table_column?
35
+ return :integer if @_as == :belongs_to
36
+ @_as
37
+ end
38
+
39
+ def skip_table_column?
40
+ [:has_many, :has_and_belongs_to_many, :has_one].include? @_as
41
+ end
42
+
43
+ end
44
+ end
45
+
@@ -0,0 +1,24 @@
1
+ module ToyModel::Attributes
2
+
3
+ mattr_accessor :toy_attributes
4
+ self.toy_attributes = []
5
+
6
+ def attribute value
7
+ wrapper = ToyModel::AttributeWrapper.new value, self
8
+ self.toy_attributes << wrapper
9
+ wrapper
10
+ end
11
+
12
+ def attrs *args
13
+ ToyModel::AttributesCollection.new self, *args
14
+ end
15
+
16
+ def attributes
17
+ toy_attributes.select{|a| a.parent == self}
18
+ end
19
+
20
+ def use_toy_model?
21
+ true
22
+ end
23
+
24
+ end
@@ -0,0 +1,17 @@
1
+ module ToyModel
2
+ class AttributesCollection
3
+
4
+ attr_accessor :attributes
5
+
6
+ def initialize klass, *args
7
+ @attributes = []
8
+ args.each { |attr| @attributes << klass.attribute(attr) }
9
+ end
10
+
11
+ def method_missing(m, *args, &block)
12
+ @attributes.each { |attr| attr.send m, *args }
13
+ self
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module ToyModel
2
+
3
+ def self.load! dir_path
4
+ ActiveRecord::Base.extend ToyModel::Attributes
5
+ Dir[dir_path].each do |file|
6
+ require file
7
+ ToyModel::AttributeObserver.new file.split('/').last.split('.').first.classify.constantize
8
+ end
9
+ end
10
+
11
+ class Engine < Rails::Engine
12
+ initializer 'toy_model.initialize', :after => :disable_dependency_loading do |app|
13
+ ToyModel.load! "#{Rails.root}/app/models/*.rb"
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,3 @@
1
+ module ToyModel
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe ToyModel::AttributeObserver do
4
+
5
+ it "creates table for new models" do
6
+ Warrior.table_exists?.should == true
7
+ end
8
+
9
+ it "changes the column type" do
10
+ Warrior.attributes.last.as(:text)
11
+ ToyModel::AttributeObserver.new Warrior
12
+ Warrior.columns_hash['story'].type.should == :text
13
+ end
14
+
15
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ToyModel::Attributes do
4
+
5
+ describe Warrior do
6
+
7
+ subject{ Warrior.first }
8
+
9
+ it{should respond_to(:name)}
10
+ its(:name){should == 'Mortaro'}
11
+ its(:name){should be_a(String)}
12
+ it{should respond_to(:weapons)}
13
+
14
+ it "automatically creates a has_many relation" do
15
+ subject.weapons.first.should == Weapon.first
16
+ end
17
+
18
+ end
19
+
20
+ describe Weapon do
21
+
22
+ subject{ Weapon.first }
23
+
24
+ it{should respond_to(:warrior_id)}
25
+ it{should respond_to(:min_damage)}
26
+ it{should respond_to(:max_damage)}
27
+ its(:min_damage){should be_a(Fixnum)}
28
+ its(:warrior){should == Warrior.first}
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,10 @@
1
+ require 'rails/all'
2
+ require 'toy-model'
3
+ require 'rspec-rails'
4
+
5
+ autoload :Warrior, "#{File.dirname(__FILE__)}/support/models/warrior.rb"
6
+ autoload :Weapon, "#{File.dirname(__FILE__)}/support/models/weapon.rb"
7
+
8
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: './toy_model.sqlite3')
9
+ ToyModel.load! "#{File.dirname(__FILE__)}/support/models/*.rb"
10
+ load "#{File.dirname(__FILE__)}/support/seeds.rb"
@@ -0,0 +1,4 @@
1
+ class Warrior < ActiveRecord::Base
2
+ attribute(:weapons).as(:has_many)
3
+ attrs(:name, :story)
4
+ end
@@ -0,0 +1,4 @@
1
+ class Weapon < ActiveRecord::Base
2
+ attribute(:name)
3
+ attrs(:min_damage, :max_damage).as(:integer)
4
+ end
@@ -0,0 +1,4 @@
1
+ Warrior.destroy_all
2
+ Weapon.destroy_all
3
+ warrior = Warrior.create name: 'Mortaro'
4
+ warrior.weapons.create name: 'Overpowered Staff', min_damage: 900, max_damage: 999
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "toy-model/version"
4
+
5
+ Gem::Specification.new do |s|
6
+
7
+ s.name = "toy-model"
8
+ s.version = ToyModel::VERSION
9
+ s.authors = ["Christian Mortaro"]
10
+ s.email = ["christian.mortaro@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Handles the models for the Toy Locomotive}
13
+ s.description = %q{Another layer above ActiveRecord}
14
+
15
+ s.rubyforge_project = "toy-model"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency "rails"
23
+ s.add_development_dependency "rspec-rails"
24
+ s.add_development_dependency "sqlite3"
25
+ s.add_development_dependency "shoulda"
26
+
27
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: toy-model
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Christian Mortaro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &3102792 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *3102792
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec-rails
27
+ requirement: &3101652 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *3101652
36
+ - !ruby/object:Gem::Dependency
37
+ name: sqlite3
38
+ requirement: &3100428 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *3100428
47
+ - !ruby/object:Gem::Dependency
48
+ name: shoulda
49
+ requirement: &3099576 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *3099576
58
+ description: Another layer above ActiveRecord
59
+ email:
60
+ - christian.mortaro@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - Rakefile
68
+ - lib/toy-model.rb
69
+ - lib/toy-model/attribute_observer.rb
70
+ - lib/toy-model/attribute_wrapper.rb
71
+ - lib/toy-model/attributes.rb
72
+ - lib/toy-model/attributes_collection.rb
73
+ - lib/toy-model/railtie.rb
74
+ - lib/toy-model/version.rb
75
+ - spec/lib/attribute_observer_spec.rb
76
+ - spec/lib/attributes_spec.rb
77
+ - spec/spec_helper.rb
78
+ - spec/support/models/warrior.rb
79
+ - spec/support/models/weapon.rb
80
+ - spec/support/seeds.rb
81
+ - toy-model.gemspec
82
+ homepage: ''
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project: toy-model
102
+ rubygems_version: 1.8.16
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Handles the models for the Toy Locomotive
106
+ test_files: []