toy-model 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/Rakefile +3 -0
- data/lib/toy-model.rb +9 -0
- data/lib/toy-model/attribute_observer.rb +44 -0
- data/lib/toy-model/attribute_wrapper.rb +45 -0
- data/lib/toy-model/attributes.rb +24 -0
- data/lib/toy-model/attributes_collection.rb +17 -0
- data/lib/toy-model/railtie.rb +17 -0
- data/lib/toy-model/version.rb +3 -0
- data/spec/lib/attribute_observer_spec.rb +15 -0
- data/spec/lib/attributes_spec.rb +32 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/models/warrior.rb +4 -0
- data/spec/support/models/weapon.rb +4 -0
- data/spec/support/seeds.rb +4 -0
- data/toy-model.gemspec +27 -0
- metadata +106 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/lib/toy-model.rb
ADDED
@@ -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,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
|
data/spec/spec_helper.rb
ADDED
@@ -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"
|
data/toy-model.gemspec
ADDED
@@ -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: []
|