toy-model 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []