toy-locomotive 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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +3 -0
- data/lib/toy-locomotive/.initializer.rb.swp +0 -0
- data/lib/toy-locomotive/initializer.rb +14 -0
- data/lib/toy-locomotive/router/.controller.rb.swp +0 -0
- data/lib/toy-locomotive/router/.model.rb.swp +0 -0
- data/lib/toy-locomotive/router/controller.rb +100 -0
- data/lib/toy-locomotive/router/model.rb +40 -0
- data/lib/toy-locomotive/version.rb +3 -0
- data/lib/toy-locomotive.rb +13 -0
- data/spec/lib/router_controller_spec.rb +71 -0
- data/spec/lib/router_model_spec.rb +49 -0
- data/spec/lib/toy_locomotive_spec.rb +7 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/controllers.rb +30 -0
- data/spec/support/models.rb +16 -0
- data/spec/support/schema.rb +19 -0
- data/spec/support/seeds.rb +1 -0
- data/toy-locomotive.gemspec +28 -0
- metadata +109 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
Binary file
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ToyLocomotive
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
initializer 'toy_locomotive.initialize', :after=> :disable_dependency_loading do |app|
|
4
|
+
Dir["#{Rails.root}/app/models/*.rb"].each {|file| require file}
|
5
|
+
Dir["#{Rails.root}/app/controllers/*.rb"].each do |file|
|
6
|
+
require file
|
7
|
+
const = file.split('/').last.split('.').first.classify.constantize.append_filters!
|
8
|
+
end
|
9
|
+
Rails.application.class.routes.draw do
|
10
|
+
ToyLocomotive.routes.each {|route| match route[:path] => "#{route[:controller]}##{route[:action]}", as: route[:as], via: route[:method]}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module ToyLocomotive::Router::Controller
|
2
|
+
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
%w(get put post delete).each {|via| eval "def #{via} path, opts={}, &blk; match_action \"#{via}\", path, opts, blk; end"}
|
6
|
+
|
7
|
+
def match_action method, path, opts, blk
|
8
|
+
action = extract_action path, opts
|
9
|
+
extract_filter action, path, opts
|
10
|
+
path = extract_path path, opts
|
11
|
+
as = extract_as path, opts
|
12
|
+
controller = extract_controller
|
13
|
+
add_route method, action, path, as, controller
|
14
|
+
define_method action, blk
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_route method, action, path, as, controller
|
18
|
+
ToyLocomotive.routes ||= []
|
19
|
+
ToyLocomotive.routes << {method: method, action: action, path: path, controller: controller, as: as}
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_member_filter action
|
23
|
+
@member_filters ||= []
|
24
|
+
@member_filters << action.to_sym
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_collection_filter action
|
28
|
+
@collection_filters ||= []
|
29
|
+
@collection_filters << action.to_sym
|
30
|
+
end
|
31
|
+
|
32
|
+
def extract_path path, opts={}
|
33
|
+
path[0] == '/' ? path : "#{extract_model.route_chain}#{opts[:on] == 'member' ? extract_model.to_route : "/#{extract_model.to_s.underscore.pluralize}"}/#{path.parameterize}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def extract_as path, opts={}
|
37
|
+
action = extract_action path, opts
|
38
|
+
path[0] == '/' ? action : "#{action}_#{extract_model.to_as}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def extract_action path, opts={}
|
42
|
+
(opts[:as] || (path == '/' ? 'root' : path)).parameterize.underscore
|
43
|
+
end
|
44
|
+
|
45
|
+
def extract_controller
|
46
|
+
to_s.gsub('Controller', '').downcase
|
47
|
+
end
|
48
|
+
|
49
|
+
def extract_model
|
50
|
+
extract_controller.singularize.camelize.constantize
|
51
|
+
end
|
52
|
+
|
53
|
+
def extract_filter action, path, opts
|
54
|
+
return if path[0] == '/'
|
55
|
+
send :"add_#{opts[:on]}_filter", action
|
56
|
+
end
|
57
|
+
|
58
|
+
def append_filters!
|
59
|
+
before_filter :extract_parent_vars, only: ((@member_filters || []) + (@collection_filters || []))
|
60
|
+
before_filter :extract_member_var, only: (@member_filters || [])
|
61
|
+
before_filter :extract_collection_var, only: (@collection_filters || [])
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
module InstanceMethods
|
67
|
+
|
68
|
+
def extract_parent_vars
|
69
|
+
chain = self.class.extract_model.belongs_chain
|
70
|
+
vars = []
|
71
|
+
if chain.any?
|
72
|
+
root = chain.pop
|
73
|
+
parent = root.find(params[root.to_params])
|
74
|
+
instance_variable_set root.to_member_var, parent
|
75
|
+
vars << parent
|
76
|
+
chain.reverse!.each do |model|
|
77
|
+
parent = parent.send(model.to_s.underscore.pluralize).find(params[model.to_params])
|
78
|
+
instance_variable_set model.to_member_var, parent
|
79
|
+
vars << parent
|
80
|
+
end
|
81
|
+
end
|
82
|
+
vars
|
83
|
+
end
|
84
|
+
|
85
|
+
def extract_member_var
|
86
|
+
parent = instance_variable_get (model = self.class.extract_model).belongs_chain.reverse.pop.to_member_var
|
87
|
+
parent ? instance_variable_set(model.to_member_var, parent.send(model.to_s.underscore.pluralize).find(params[model.to_params])) : model.find(params[model.to_params])
|
88
|
+
end
|
89
|
+
|
90
|
+
def extract_collection_var
|
91
|
+
parent = instance_variable_get (model = self.class.extract_model).belongs_chain.reverse.pop.to_member_var
|
92
|
+
parent ? instance_variable_set(model.to_collection_var, parent.send(model.to_s.underscore.pluralize)) : model.all
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
ActionController::Base.extend ToyLocomotive::Router::Controller::ClassMethods
|
100
|
+
ActionController::Base.send :include, ToyLocomotive::Router::Controller::InstanceMethods
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ToyLocomotive::Router::Model
|
2
|
+
|
3
|
+
def belongs_to_route
|
4
|
+
reflections = reflect_on_all_associations(:belongs_to)
|
5
|
+
reflections.any? ? reflections.first.name.to_s.camelize.constantize : nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def belongs_chain chain=[]
|
9
|
+
parent_route = (chain.last || self).belongs_to_route
|
10
|
+
parent_route ? belongs_chain(chain << parent_route) : chain
|
11
|
+
end
|
12
|
+
|
13
|
+
def route_chain
|
14
|
+
belongs_chain.reverse.map{|m| m.to_route}.join
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_route
|
18
|
+
s = to_s.parameterize.downcase
|
19
|
+
"/#{s.pluralize}/:#{s}_id"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_member_var
|
23
|
+
"@#{to_s.underscore}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_collection_var
|
27
|
+
to_member_var.pluralize
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_params
|
31
|
+
:"#{to_s.underscore}_id"
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_as
|
35
|
+
belongs_chain.reverse!.map{|m| m.to_s.underscore }.join('_') << (belongs_chain.empty? ? to_s.underscore : "_#{to_s.underscore}")
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
ActiveRecord::Base.extend ToyLocomotive::Router::Model
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "rails/all"
|
2
|
+
require "toy-locomotive/version"
|
3
|
+
|
4
|
+
module ToyLocomotive
|
5
|
+
|
6
|
+
module Router; end
|
7
|
+
mattr_accessor :routes
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
require "toy-locomotive/router/model"
|
12
|
+
require "toy-locomotive/router/controller"
|
13
|
+
require "toy-locomotive/initializer"
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DogsController do
|
4
|
+
|
5
|
+
subject { DogsController }
|
6
|
+
|
7
|
+
its(:extract_model) {should == Dog}
|
8
|
+
its(:extract_controller) {should == 'dogs'}
|
9
|
+
|
10
|
+
[:get, :put, :post, :delete].each {|via| it { should respond_to(via) }}
|
11
|
+
|
12
|
+
it "extracts vars" do
|
13
|
+
dog_controller = DogsController.new
|
14
|
+
dog_controller.extract_parent_vars[0].class.should == Alien
|
15
|
+
dog_controller.extract_parent_vars[1].class.should == Human
|
16
|
+
dog_controller.extract_member_var.class.should == Dog
|
17
|
+
dog_controller.extract_collection_var.class.should == Array
|
18
|
+
dog_controller.extract_collection_var.first.class.should == Dog
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.extract_action' do
|
22
|
+
it "recognizes the root" do
|
23
|
+
DogsController.extract_action('/').should == 'root'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns the option :as if declared" do
|
27
|
+
DogsController.extract_action('lorem-ipsum', as: 'dolor-sit').should == 'dolor_sit'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns the path if no options" do
|
31
|
+
DogsController.extract_action('lorem-ipsum').should == 'lorem_ipsum'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.extract_as' do
|
36
|
+
it "returns the action if its absolute path" do
|
37
|
+
DogsController.extract_as('/lorem-ipsum').should == 'lorem_ipsum'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the chain as method if its relative path" do
|
41
|
+
DogsController.extract_as('lorem').should == 'lorem_alien_human_dog'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '.extract_path' do
|
46
|
+
it "returns itself if absolute path" do
|
47
|
+
DogsController.extract_path('/lorem').should == '/lorem'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "matches relative path on member" do
|
51
|
+
DogsController.extract_path('lorem', on: 'member').should == '/aliens/:alien_id/humans/:human_id/dogs/:dog_id/lorem'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "matches relative path on collection" do
|
55
|
+
DogsController.extract_path('lorem', on: 'collection').should == '/aliens/:alien_id/humans/:human_id/dogs/lorem'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '.get' do
|
60
|
+
it "adds a empty method" do
|
61
|
+
DogsController.get('/lorem'){}
|
62
|
+
DogsController.new.should respond_to(:lorem)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "adds a method from a block" do
|
66
|
+
DogsController.get('/lorem') { 'lorem-ipsum' }
|
67
|
+
DogsController.new.lorem.should == 'lorem-ipsum'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dog do
|
4
|
+
|
5
|
+
subject { Dog }
|
6
|
+
|
7
|
+
{ to_params: :dog_id,
|
8
|
+
to_collection_var: '@dogs',
|
9
|
+
to_member_var: '@dog',
|
10
|
+
to_route: '/dogs/:dog_id',
|
11
|
+
route_chain: '/aliens/:alien_id/humans/:human_id',
|
12
|
+
belongs_chain: [Human, Alien],
|
13
|
+
belongs_to_route: Human,
|
14
|
+
to_as: 'alien_human_dog'
|
15
|
+
}.each{|method, expectation| its(method) {should == expectation}}
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Human do
|
20
|
+
|
21
|
+
subject { Human }
|
22
|
+
|
23
|
+
{ to_params: :human_id,
|
24
|
+
to_collection_var: '@humans',
|
25
|
+
to_member_var: '@human',
|
26
|
+
to_route: '/humans/:human_id',
|
27
|
+
route_chain: '/aliens/:alien_id',
|
28
|
+
belongs_chain: [Alien],
|
29
|
+
belongs_to_route: Alien,
|
30
|
+
to_as: 'alien_human'
|
31
|
+
}.each{|method, expectation| its(method) {should == expectation}}
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Alien do
|
36
|
+
|
37
|
+
subject { Alien }
|
38
|
+
|
39
|
+
{ to_params: :alien_id,
|
40
|
+
to_collection_var: '@aliens',
|
41
|
+
to_member_var: '@alien',
|
42
|
+
to_route: '/aliens/:alien_id',
|
43
|
+
route_chain: '',
|
44
|
+
belongs_chain: [],
|
45
|
+
belongs_to_route: nil,
|
46
|
+
to_as: 'alien'
|
47
|
+
}.each{|method, expectation| its(method) {should == expectation}}
|
48
|
+
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
class DogsController < ActionController::Base
|
2
|
+
|
3
|
+
def params
|
4
|
+
{alien_id: Alien.first.id, human_id: Human.first.id, dog_id: Dog.first.id}
|
5
|
+
end
|
6
|
+
|
7
|
+
get '/absolute' do
|
8
|
+
'absolute route'
|
9
|
+
end
|
10
|
+
|
11
|
+
get 'member', on: 'member' do
|
12
|
+
'member route'
|
13
|
+
end
|
14
|
+
|
15
|
+
get 'collection', on: 'collection' do
|
16
|
+
'collection route'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
DogsController.append_filters!
|
21
|
+
|
22
|
+
class HumansController < ActionController::Base
|
23
|
+
|
24
|
+
end
|
25
|
+
HumansController.append_filters!
|
26
|
+
|
27
|
+
class AliensController < ActionController::Base
|
28
|
+
|
29
|
+
end
|
30
|
+
AliensController.append_filters!
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Dog < ActiveRecord::Base
|
2
|
+
belongs_to :human
|
3
|
+
end
|
4
|
+
|
5
|
+
class Human < ActiveRecord::Base
|
6
|
+
belongs_to :alien
|
7
|
+
has_many :dogs
|
8
|
+
end
|
9
|
+
|
10
|
+
class Alien < ActiveRecord::Base
|
11
|
+
has_many :humans
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveSupport::Inflector.inflections do |inflect|
|
15
|
+
inflect.irregular 'Human', 'Humans'
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
|
3
|
+
self.verbose = false
|
4
|
+
|
5
|
+
create_table :dogs, :force => true do |t|
|
6
|
+
t.integer :human_id
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table :humans, :force => true do |t|
|
11
|
+
t.integer :alien_id
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table :aliens, :force => true do |t|
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Alien.create.humans.create.dogs.create
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "toy-locomotive/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
|
7
|
+
s.name = "toy-locomotive"
|
8
|
+
s.version = ToyLocomotive::VERSION
|
9
|
+
s.authors = ["Christian Mortaro"]
|
10
|
+
s.email = ["mortaro@towsta.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{a Toy Locomotive to run over Rails}
|
13
|
+
s.description = %q{a Different aproach to Rails applications}
|
14
|
+
|
15
|
+
s.rubyforge_project = "toy-locomotive"
|
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_dependency "rails"
|
23
|
+
|
24
|
+
s.add_development_dependency "rspec-rails"
|
25
|
+
s.add_development_dependency "sqlite3"
|
26
|
+
s.add_development_dependency "shoulda"
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: toy-locomotive
|
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: 2012-05-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: &22779288 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *22779288
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec-rails
|
27
|
+
requirement: &22778760 !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: *22778760
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sqlite3
|
38
|
+
requirement: &22778280 !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: *22778280
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: shoulda
|
49
|
+
requirement: &22777812 !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: *22777812
|
58
|
+
description: a Different aproach to Rails applications
|
59
|
+
email:
|
60
|
+
- mortaro@towsta.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- .gitignore
|
66
|
+
- Gemfile
|
67
|
+
- Rakefile
|
68
|
+
- lib/toy-locomotive.rb
|
69
|
+
- lib/toy-locomotive/.initializer.rb.swp
|
70
|
+
- lib/toy-locomotive/initializer.rb
|
71
|
+
- lib/toy-locomotive/router/.controller.rb.swp
|
72
|
+
- lib/toy-locomotive/router/.model.rb.swp
|
73
|
+
- lib/toy-locomotive/router/controller.rb
|
74
|
+
- lib/toy-locomotive/router/model.rb
|
75
|
+
- lib/toy-locomotive/version.rb
|
76
|
+
- spec/lib/router_controller_spec.rb
|
77
|
+
- spec/lib/router_model_spec.rb
|
78
|
+
- spec/lib/toy_locomotive_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
- spec/support/controllers.rb
|
81
|
+
- spec/support/models.rb
|
82
|
+
- spec/support/schema.rb
|
83
|
+
- spec/support/seeds.rb
|
84
|
+
- toy-locomotive.gemspec
|
85
|
+
homepage: ''
|
86
|
+
licenses: []
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project: toy-locomotive
|
105
|
+
rubygems_version: 1.8.16
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: a Toy Locomotive to run over Rails
|
109
|
+
test_files: []
|