mappable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +87 -0
- data/Rakefile +32 -0
- data/app/assets/javascripts/mappable/application.js +9 -0
- data/app/assets/javascripts/mappable/mappings.js +2 -0
- data/app/assets/javascripts/mappable/maps.js +2 -0
- data/app/assets/stylesheets/mappable/application.css +7 -0
- data/app/assets/stylesheets/mappable/mappings.css +4 -0
- data/app/assets/stylesheets/mappable/maps.css +4 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/mappable/application_controller.rb +4 -0
- data/app/controllers/mappable/mappings_controller.rb +54 -0
- data/app/controllers/mappable/maps_controller.rb +46 -0
- data/app/helpers/mappable/application_helper.rb +4 -0
- data/app/helpers/mappable/mappings_helper.rb +4 -0
- data/app/helpers/mappable/maps_helper.rb +4 -0
- data/app/models/mappable/map.rb +19 -0
- data/app/models/mappable/mapping.rb +6 -0
- data/app/views/mappable/mappings/_form.html.erb +26 -0
- data/app/views/mappable/mappings/edit.html.erb +6 -0
- data/app/views/mappable/mappings/index.html.erb +25 -0
- data/app/views/mappable/mappings/new.html.erb +5 -0
- data/app/views/mappable/mappings/show.html.erb +19 -0
- data/app/views/mappable/maps/_form.html.erb +47 -0
- data/app/views/mappable/maps/edit.html.erb +6 -0
- data/app/views/mappable/maps/index.html.erb +29 -0
- data/app/views/mappable/maps/new.html.erb +5 -0
- data/app/views/mappable/maps/show.html.erb +25 -0
- data/config/routes.rb +25 -0
- data/db/migrate/20110919042052_create_mappable_maps.rb +12 -0
- data/db/migrate/20110919042056_create_mappable_mappings.rb +12 -0
- data/lib/generators/mappable/views/USAGE +20 -0
- data/lib/generators/mappable/views/views_generator.rb +20 -0
- data/lib/mappable.rb +6 -0
- data/lib/mappable/engine.rb +9 -0
- data/lib/mappable/map_route.rb +27 -0
- data/lib/mappable/map_router.rb +22 -0
- data/lib/mappable/version.rb +3 -0
- data/lib/tasks/mappable_tasks.rake +4 -0
- metadata +156 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Mike Bannister
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Mappable #
|
2
|
+
|
3
|
+
Lightweight string mappings engine for Rails
|
4
|
+
|
5
|
+
## Synopsis ##
|
6
|
+
|
7
|
+
Provides models and a UI for creating and maintaining string pairs. A tiny DSL is included so developers to easily make use of the generated data. The UI allows system administrators to create groups of string pairs that can be maintained by non-technical people.
|
8
|
+
|
9
|
+
We use this tool to map account names in a legacy system, where we don't control the names, to their corresponding names in our in-house system.
|
10
|
+
|
11
|
+
## Installation ##
|
12
|
+
|
13
|
+
Add it to your `Gemfile`
|
14
|
+
|
15
|
+
gem 'mappable'
|
16
|
+
|
17
|
+
Bundle it up
|
18
|
+
|
19
|
+
bundle install
|
20
|
+
|
21
|
+
Install the migrations and apply them
|
22
|
+
|
23
|
+
rake mappable:install:migrations
|
24
|
+
rake db:migrate
|
25
|
+
|
26
|
+
The migrations will add tables similar to this
|
27
|
+
|
28
|
+
create_table "mappable_mappings", :force => true do |t|
|
29
|
+
t.integer "map_id"
|
30
|
+
t.string "from"
|
31
|
+
t.string "to"
|
32
|
+
end
|
33
|
+
|
34
|
+
create_table "mappable_maps", :force => true do |t|
|
35
|
+
t.string "subject"
|
36
|
+
t.string "attr"
|
37
|
+
t.string "from"
|
38
|
+
t.string "to"
|
39
|
+
end
|
40
|
+
|
41
|
+
Mount the engine
|
42
|
+
|
43
|
+
mount Mappable::Engine => '/map'
|
44
|
+
|
45
|
+
You can use the included generator to copy the views if you'd like to customize them
|
46
|
+
|
47
|
+
rails generate mappable:views
|
48
|
+
|
49
|
+
Definitions
|
50
|
+
|
51
|
+
* **Mappings**: String pairs that map to each other
|
52
|
+
|
53
|
+
- [http://localhost:3000/map/account/name](http://localhost:3000/map/account/name)
|
54
|
+
|
55
|
+
* **Maps**: A group of mappings and relevant metadata.
|
56
|
+
|
57
|
+
- [http://localhost:3000/map](http://localhost:3000/maps)
|
58
|
+
|
59
|
+
## Example usage ##
|
60
|
+
|
61
|
+
Given the following records
|
62
|
+
|
63
|
+
### Map ###
|
64
|
+
|
65
|
+
id = 1
|
66
|
+
subject = 'account'
|
67
|
+
attr = 'name'
|
68
|
+
from = 'legacy'
|
69
|
+
to = 'current'
|
70
|
+
|
71
|
+
### Mapping ###
|
72
|
+
|
73
|
+
id = 1
|
74
|
+
map_id = 1
|
75
|
+
from = 'Old Account Name'
|
76
|
+
to = 'New Account Name'
|
77
|
+
|
78
|
+
Now you can map strings in either direction using the following grammar
|
79
|
+
|
80
|
+
LegacyAccountName("Old Account Name").to_current #=> "New Account Name"
|
81
|
+
CurrentAccountName("New Account Name").to_legacy #=> "Old Account Name"
|
82
|
+
|
83
|
+
## TODO ##
|
84
|
+
|
85
|
+
Better indexing in migrations
|
86
|
+
Rake task for installing views
|
87
|
+
Add security features
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Mappable'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
|
31
|
+
RSpec::Core::RakeTask.new(:spec)
|
32
|
+
task :default => :spec
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into including all the files listed below.
|
2
|
+
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
3
|
+
// be included in the compiled file accessible from http://example.com/assets/application.js
|
4
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
5
|
+
// the compiled file.
|
6
|
+
//
|
7
|
+
//= require jquery
|
8
|
+
//= require jquery_ujs
|
9
|
+
//= require_tree .
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll automatically include all the stylesheets available in this directory
|
3
|
+
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
4
|
+
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
5
|
+
*= require_self
|
6
|
+
*= require_tree .
|
7
|
+
*/
|
@@ -0,0 +1,56 @@
|
|
1
|
+
body { background-color: #fff; color: #333; }
|
2
|
+
|
3
|
+
body, p, ol, ul, td {
|
4
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
5
|
+
font-size: 13px;
|
6
|
+
line-height: 18px;
|
7
|
+
}
|
8
|
+
|
9
|
+
pre {
|
10
|
+
background-color: #eee;
|
11
|
+
padding: 10px;
|
12
|
+
font-size: 11px;
|
13
|
+
}
|
14
|
+
|
15
|
+
a { color: #000; }
|
16
|
+
a:visited { color: #666; }
|
17
|
+
a:hover { color: #fff; background-color:#000; }
|
18
|
+
|
19
|
+
div.field, div.actions {
|
20
|
+
margin-bottom: 10px;
|
21
|
+
}
|
22
|
+
|
23
|
+
#notice {
|
24
|
+
color: green;
|
25
|
+
}
|
26
|
+
|
27
|
+
.field_with_errors {
|
28
|
+
padding: 2px;
|
29
|
+
background-color: red;
|
30
|
+
display: table;
|
31
|
+
}
|
32
|
+
|
33
|
+
#error_explanation {
|
34
|
+
width: 450px;
|
35
|
+
border: 2px solid red;
|
36
|
+
padding: 7px;
|
37
|
+
padding-bottom: 0;
|
38
|
+
margin-bottom: 20px;
|
39
|
+
background-color: #f0f0f0;
|
40
|
+
}
|
41
|
+
|
42
|
+
#error_explanation h2 {
|
43
|
+
text-align: left;
|
44
|
+
font-weight: bold;
|
45
|
+
padding: 5px 5px 5px 15px;
|
46
|
+
font-size: 12px;
|
47
|
+
margin: -7px;
|
48
|
+
margin-bottom: 0px;
|
49
|
+
background-color: #c00;
|
50
|
+
color: #fff;
|
51
|
+
}
|
52
|
+
|
53
|
+
#error_explanation ul li {
|
54
|
+
font-size: 12px;
|
55
|
+
list-style: square;
|
56
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Mappable
|
2
|
+
class MappingsController < ApplicationController
|
3
|
+
before_filter :load_map!, only: [:index, :new]
|
4
|
+
|
5
|
+
def index
|
6
|
+
@mappings = @map.mappings
|
7
|
+
end
|
8
|
+
|
9
|
+
def show
|
10
|
+
@mapping = Mapping.find(params[:id])
|
11
|
+
end
|
12
|
+
|
13
|
+
def new
|
14
|
+
@mapping = Mapping.new(map: @map)
|
15
|
+
end
|
16
|
+
|
17
|
+
def edit
|
18
|
+
@mapping = Mapping.find(params[:id])
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@mapping = Mapping.new(params[:mapping])
|
23
|
+
|
24
|
+
if @mapping.save
|
25
|
+
redirect_to mappings_url(subject: @mapping.parent_map.subject, attr: @mapping.parent_map.attr.pluralize), notice: 'Mapping was successfully created.'
|
26
|
+
else
|
27
|
+
render action: "new"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
@mapping = Mapping.find(params[:id])
|
33
|
+
|
34
|
+
if @mapping.update_attributes(params[:mapping])
|
35
|
+
redirect_to mappings_url(subject: @mapping.parent_map.subject, attr: @mapping.parent_map.attr.pluralize), notice: 'Mapping was successfully updated.'
|
36
|
+
else
|
37
|
+
render action: "edit"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def destroy
|
42
|
+
@mapping = Mapping.find(params[:id])
|
43
|
+
@mapping.destroy
|
44
|
+
|
45
|
+
redirect_to mappings_url
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def load_map!
|
51
|
+
@map = Map.find_by_subject_and_attr!(params[:subject], params[:attr].try(:singularize))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Mappable
|
2
|
+
class MapsController < ApplicationController
|
3
|
+
def index
|
4
|
+
@maps = Map.all
|
5
|
+
end
|
6
|
+
|
7
|
+
def show
|
8
|
+
@map = Map.find(params[:id])
|
9
|
+
end
|
10
|
+
|
11
|
+
def new
|
12
|
+
@map = Map.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def edit
|
16
|
+
@map = Map.find(params[:id])
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
@map = Map.new(params[:map])
|
21
|
+
|
22
|
+
if @map.save
|
23
|
+
redirect_to maps_url, notice: 'Map was successfully created.'
|
24
|
+
else
|
25
|
+
render action: "new"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def update
|
30
|
+
@map = Map.find(params[:id])
|
31
|
+
|
32
|
+
if @map.update_attributes(params[:map])
|
33
|
+
redirect_to maps_url, notice: 'Map was successfully updated.'
|
34
|
+
else
|
35
|
+
render action: "edit"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def destroy
|
40
|
+
@map = Map.find(params[:id])
|
41
|
+
@map.destroy
|
42
|
+
|
43
|
+
redirect_to maps_url
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Mappable
|
2
|
+
class Map < ActiveRecord::Base
|
3
|
+
has_many :mappings
|
4
|
+
|
5
|
+
after_save do
|
6
|
+
Mappable::MapRouter.build_map_routes!
|
7
|
+
end
|
8
|
+
|
9
|
+
def value_for(mapping_name, in_value)
|
10
|
+
in_direction = :from if to.to_sym == mapping_name
|
11
|
+
in_direction = :to if from.to_sym == mapping_name
|
12
|
+
if in_direction
|
13
|
+
out_direction = :from if in_direction == :to
|
14
|
+
out_direction = :to if in_direction == :from
|
15
|
+
self.mappings.where(in_direction => in_value).first.send(out_direction)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= form_for(@mapping, url: mappings_url(subject: @mapping.parent_map.subject, attr: @mapping.parent_map.attr.pluralize)) do |f| %>
|
2
|
+
<% if @mapping.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@mapping.errors.count, "error") %> prohibited this mapping from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @mapping.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<div class="field">
|
15
|
+
<%= f.label :from %><br />
|
16
|
+
<%= f.text_field :from %>
|
17
|
+
</div>
|
18
|
+
<div class="field">
|
19
|
+
<%= f.label :to %><br />
|
20
|
+
<%= f.text_field :to %>
|
21
|
+
</div>
|
22
|
+
<%= f.hidden_field :map_id %>
|
23
|
+
<div class="actions">
|
24
|
+
<%= f.submit %>
|
25
|
+
</div>
|
26
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<h1><%= @map.subject.humanize %> <%= @map.attr.humanize.downcase %> mappings</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>From</th>
|
6
|
+
<th>To</th>
|
7
|
+
<th></th>
|
8
|
+
<th></th>
|
9
|
+
<th></th>
|
10
|
+
</tr>
|
11
|
+
|
12
|
+
<% @mappings.each do |mapping| %>
|
13
|
+
<tr>
|
14
|
+
<td><%= mapping.from %></td>
|
15
|
+
<td><%= mapping.to %></td>
|
16
|
+
<td><%= link_to 'Show', mapping_path(mapping, subject: @map.subject, attr: @map.attr.pluralize) %></td>
|
17
|
+
<td><%= link_to 'Edit', edit_mapping_path(mapping) %></td>
|
18
|
+
<td><%= link_to 'Destroy', mapping_path(mapping, subject: @map.subject, attr: @map.attr.pluralize), confirm: 'Are you sure?', method: :delete %></td>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</table>
|
22
|
+
|
23
|
+
<br />
|
24
|
+
|
25
|
+
<%= link_to "New #{@map.subject.humanize.titleize} #{@map.attr.humanize.titleize} Mapping", new_mapping_path(subject: @map.subject, attr: @map.attr.pluralize) %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<h1>Edit <%= @map.subject.humanize.titleize %> <%= @map.attr.humanize.titleize %> Mappings</h1>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<b>Map:</b>
|
5
|
+
<%= @mapping.parent_map.subject %>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
<b>From:</b>
|
10
|
+
<%= @mapping.from %>
|
11
|
+
</p>
|
12
|
+
|
13
|
+
<p>
|
14
|
+
<b>To:</b>
|
15
|
+
<%= @mapping.to %>
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<%= link_to 'Edit', edit_mapping_path(@mapping) %> |
|
19
|
+
<%= link_to 'Back', mappings_path %>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<%= form_for(@map) do |f| %>
|
2
|
+
<% if @map.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@map.errors.count, "error") %> prohibited this map from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @map.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<table border=0 cellpadding="0" cellspacing="5">
|
15
|
+
<tr>
|
16
|
+
<td>
|
17
|
+
<div class="field">
|
18
|
+
<%= f.label :subject %><br />
|
19
|
+
<%= f.text_field :subject %>
|
20
|
+
</div>
|
21
|
+
</td>
|
22
|
+
<td>
|
23
|
+
<div class="field">
|
24
|
+
<%= f.label :attr, "Attribute" %><br />
|
25
|
+
<%= f.text_field :attr %>
|
26
|
+
</div>
|
27
|
+
</td>
|
28
|
+
</tr>
|
29
|
+
<tr>
|
30
|
+
<td>
|
31
|
+
<div class="field">
|
32
|
+
<%= f.label :from, "From name" %><br />
|
33
|
+
<%= f.text_field :from %>
|
34
|
+
</div>
|
35
|
+
</td>
|
36
|
+
<td>
|
37
|
+
<div class="field">
|
38
|
+
<%= f.label :to, "To name" %><br />
|
39
|
+
<%= f.text_field :to %>
|
40
|
+
</div>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
</table>
|
44
|
+
<div class="actions">
|
45
|
+
<%= f.submit %>
|
46
|
+
</div>
|
47
|
+
<% end %>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<h1>Maps</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Subject</th>
|
6
|
+
<th>Attribute</th>
|
7
|
+
<th>From</th>
|
8
|
+
<th>To</th>
|
9
|
+
<th></th>
|
10
|
+
<th></th>
|
11
|
+
<th></th>
|
12
|
+
</tr>
|
13
|
+
|
14
|
+
<% @maps.each do |map| %>
|
15
|
+
<tr>
|
16
|
+
<td><%= map.subject %></td>
|
17
|
+
<td><%= map.attr %></td>
|
18
|
+
<td><%= map.from %></td>
|
19
|
+
<td><%= map.to %></td>
|
20
|
+
<td><%= link_to 'Show', map %></td>
|
21
|
+
<td><%= link_to 'Edit', edit_map_path(map) %></td>
|
22
|
+
<td><%= link_to 'Destroy', map, confirm: 'Are you sure?', method: :delete %></td>
|
23
|
+
</tr>
|
24
|
+
<% end %>
|
25
|
+
</table>
|
26
|
+
|
27
|
+
<br />
|
28
|
+
|
29
|
+
<%= link_to 'New Map', new_map_path %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<h1><%= @map.subject.humanize.titleize %> <%= @map.attr.humanize.titleize %> Mappings</h1>
|
2
|
+
|
3
|
+
<h2>Maps <em><%= @map.from %></em> to <em><%= @map.to %></em></h2>
|
4
|
+
|
5
|
+
<table border="0" cellpadding="5" cellspacing="1">
|
6
|
+
<thead>
|
7
|
+
<tr>
|
8
|
+
<th>From</th>
|
9
|
+
<th>To</th>
|
10
|
+
</tr>
|
11
|
+
</thead>
|
12
|
+
<tbody>
|
13
|
+
<% @map.mappings.each do |mapping| %>
|
14
|
+
<tr>
|
15
|
+
<td><%= mapping.from %></td>
|
16
|
+
<td><%= mapping.to %></td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
19
|
+
</tbody>
|
20
|
+
</table>
|
21
|
+
|
22
|
+
<br />
|
23
|
+
|
24
|
+
<%= link_to 'Edit', edit_map_path(@map) %> |
|
25
|
+
<%= link_to 'Back', maps_path %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Mappable::Engine.routes.draw do
|
2
|
+
resources :maps, :path => "/"
|
3
|
+
|
4
|
+
match "/:subject/:attr",
|
5
|
+
to: 'mappings#index',
|
6
|
+
as: 'mappings',
|
7
|
+
via: 'get'
|
8
|
+
|
9
|
+
match "/:subject/:attr",
|
10
|
+
to: 'mappings#create',
|
11
|
+
as: 'mappings',
|
12
|
+
via: 'post'
|
13
|
+
|
14
|
+
match "/:subject/:attr/new",
|
15
|
+
to: 'mappings#new',
|
16
|
+
as: 'new_mapping',
|
17
|
+
via: 'get'
|
18
|
+
|
19
|
+
match "/:subject/:attr/:id",
|
20
|
+
to: 'mappings#show',
|
21
|
+
as: 'mapping',
|
22
|
+
via: 'get'
|
23
|
+
|
24
|
+
resources :mappings, only: [:edit, :destroy]
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Description:
|
2
|
+
Copy the views from mappable so you can override them
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate mappable:views
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
app/views/mappable
|
9
|
+
app/views/mappable/mappings
|
10
|
+
app/views/mappable/mappings/_form.html.erb
|
11
|
+
app/views/mappable/mappings/edit.html.erb
|
12
|
+
app/views/mappable/mappings/index.html.erb
|
13
|
+
app/views/mappable/mappings/new.html.erb
|
14
|
+
app/views/mappable/mappings/show.html.erb
|
15
|
+
app/views/mappable/maps
|
16
|
+
app/views/mappable/maps/_form.html.erb
|
17
|
+
app/views/mappable/maps/edit.html.erb
|
18
|
+
app/views/mappable/maps/index.html.erb
|
19
|
+
app/views/mappable/maps/new.html.erb
|
20
|
+
app/views/mappable/maps/show.html.erb
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mappable
|
2
|
+
class ViewsGenerator < Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path('../../../../../app/views/mappable', __FILE__)
|
4
|
+
argument :name, :type => :string, :default => 'views'
|
5
|
+
|
6
|
+
def copy_view_files
|
7
|
+
empty_directory "app/views/mappable/maps"
|
8
|
+
copy_file "maps/_form.html.erb", "app/views/mappable/maps/_form.html.erb"
|
9
|
+
copy_file "maps/edit.html.erb", "app/views/mappable/maps/edit.html.erb"
|
10
|
+
copy_file "maps/index.html.erb", "app/views/mappable/maps/index.html.erb"
|
11
|
+
copy_file "maps/new.html.erb", "app/views/mappable/maps/new.html.erb"
|
12
|
+
copy_file "maps/show.html.erb", "app/views/mappable/maps/show.html.erb"
|
13
|
+
empty_directory "app/views/mappable/mappings"
|
14
|
+
copy_file "mappings/edit.html.erb", "app/views/mappable/mappings/edit.html.erb"
|
15
|
+
copy_file "mappings/index.html.erb", "app/views/mappable/mappings/index.html.erb"
|
16
|
+
copy_file "mappings/new.html.erb", "app/views/mappable/mappings/new.html.erb"
|
17
|
+
copy_file "mappings/show.html.erb", "app/views/mappable/mappings/show.html.erb"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/mappable.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mappable
|
2
|
+
class MapRoute
|
3
|
+
attr_reader :map, :in_value
|
4
|
+
|
5
|
+
def initialize(map, in_value)
|
6
|
+
@map = map
|
7
|
+
@in_value = in_value
|
8
|
+
end
|
9
|
+
|
10
|
+
def mapped_value_for_method_missing(sym)
|
11
|
+
mapping_name = sym.to_s.slice(3..-1).to_sym
|
12
|
+
map.value_for(mapping_name, in_value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def map_route_method?(sym)
|
16
|
+
sym.to_s.starts_with?('to_')
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(sym, *args, &block)
|
20
|
+
if map_route_method?(sym)
|
21
|
+
mapped_value_for_method_missing(sym)
|
22
|
+
else
|
23
|
+
super(sym, *args, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Mappable
|
2
|
+
class MapRouter
|
3
|
+
class << self
|
4
|
+
def build_map_routes!
|
5
|
+
# this can get called before the database has been migrated
|
6
|
+
return unless Mappable::Map.table_exists?
|
7
|
+
Mappable::Map.all.each do |map|
|
8
|
+
build_map_route!(:from, map)
|
9
|
+
build_map_route!(:to, map)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_map_route!(direction, map)
|
14
|
+
mapping_name = map.send(direction.to_sym)
|
15
|
+
method_sym = "#{mapping_name}_#{map.subject}_#{map.attr}".camelize.to_sym
|
16
|
+
Kernel.send :define_method, method_sym do |in_value|
|
17
|
+
Mappable::MapRoute.new(map, in_value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mappable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mike Bannister
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-21 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: &2156013160 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.1.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2156013160
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sqlite3
|
27
|
+
requirement: &2156012300 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.3.4
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156012300
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec-rails
|
38
|
+
requirement: &2156011300 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.6.1
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2156011300
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: capybara
|
49
|
+
requirement: &2156010320 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.1
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2156010320
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: mocha
|
60
|
+
requirement: &2156009440 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.10.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2156009440
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: launchy
|
71
|
+
requirement: &2156008220 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 2.0.5
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2156008220
|
80
|
+
description: Lightweight string mappings engine for Rails
|
81
|
+
email:
|
82
|
+
- mikebannister@gmail.com
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- app/assets/javascripts/mappable/application.js
|
88
|
+
- app/assets/javascripts/mappable/mappings.js
|
89
|
+
- app/assets/javascripts/mappable/maps.js
|
90
|
+
- app/assets/stylesheets/mappable/application.css
|
91
|
+
- app/assets/stylesheets/mappable/mappings.css
|
92
|
+
- app/assets/stylesheets/mappable/maps.css
|
93
|
+
- app/assets/stylesheets/scaffold.css
|
94
|
+
- app/controllers/mappable/application_controller.rb
|
95
|
+
- app/controllers/mappable/mappings_controller.rb
|
96
|
+
- app/controllers/mappable/maps_controller.rb
|
97
|
+
- app/helpers/mappable/application_helper.rb
|
98
|
+
- app/helpers/mappable/mappings_helper.rb
|
99
|
+
- app/helpers/mappable/maps_helper.rb
|
100
|
+
- app/models/mappable/map.rb
|
101
|
+
- app/models/mappable/mapping.rb
|
102
|
+
- app/views/mappable/mappings/_form.html.erb
|
103
|
+
- app/views/mappable/mappings/edit.html.erb
|
104
|
+
- app/views/mappable/mappings/index.html.erb
|
105
|
+
- app/views/mappable/mappings/new.html.erb
|
106
|
+
- app/views/mappable/mappings/show.html.erb
|
107
|
+
- app/views/mappable/maps/_form.html.erb
|
108
|
+
- app/views/mappable/maps/edit.html.erb
|
109
|
+
- app/views/mappable/maps/index.html.erb
|
110
|
+
- app/views/mappable/maps/new.html.erb
|
111
|
+
- app/views/mappable/maps/show.html.erb
|
112
|
+
- config/routes.rb
|
113
|
+
- db/migrate/20110919042052_create_mappable_maps.rb
|
114
|
+
- db/migrate/20110919042056_create_mappable_mappings.rb
|
115
|
+
- lib/generators/mappable/views/USAGE
|
116
|
+
- lib/generators/mappable/views/views_generator.rb
|
117
|
+
- lib/mappable/engine.rb
|
118
|
+
- lib/mappable/map_route.rb
|
119
|
+
- lib/mappable/map_router.rb
|
120
|
+
- lib/mappable/version.rb
|
121
|
+
- lib/mappable.rb
|
122
|
+
- lib/tasks/mappable_tasks.rake
|
123
|
+
- MIT-LICENSE
|
124
|
+
- Rakefile
|
125
|
+
- README.md
|
126
|
+
homepage: https://github.com/mikebannister/mappable
|
127
|
+
licenses: []
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
hash: 2003648880004134230
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ! '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
segments:
|
148
|
+
- 0
|
149
|
+
hash: 2003648880004134230
|
150
|
+
requirements: []
|
151
|
+
rubyforge_project:
|
152
|
+
rubygems_version: 1.8.8
|
153
|
+
signing_key:
|
154
|
+
specification_version: 3
|
155
|
+
summary: Lightweight string mappings engine for Rails
|
156
|
+
test_files: []
|