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 ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in toy-locomotive.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new('spec')
@@ -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
@@ -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,3 @@
1
+ module ToyLocomotive
2
+ VERSION = "0.0.1"
3
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe ToyLocomotive do
4
+
5
+ it { should respond_to :routes }
6
+
7
+ end
@@ -0,0 +1,6 @@
1
+ require 'toy-locomotive'
2
+ require 'rspec-rails'
3
+
4
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: './toy_locomotive.sqlite3')
5
+
6
+ %w(schema models seeds controllers).each { |file| load "#{File.dirname(__FILE__)}/support/#{file}.rb" }
@@ -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: []