Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

accepts_nested_attributes_for + :finder_sql => parent_id included

When using accepts_nested_attributes_for on an association that uses
:finder_sql, the "#{parent.class.name.to_s.downcase}_id" column gets
included in the generated SQL query.

The object id suffices in itself, there is no need to include the parent
id, which doesn't exist, as the association is synthetic.
There is no need to even have a valid path from a Host to the
LookupValue: if the LookupValue references the Host name, the former
should be listed in the latter
(hence many :through associations cannot do).

    Host -> Puppetclass -> Lookup key -> Lookup value
         `----------------------------´
  • Loading branch information...
commit f7d7fda89d69c2fb99f0ec0eaec6639b73cec253 0 parents
@ofavre ofavre authored
Showing with 2,402 additions and 0 deletions.
  1. +21 −0 .gitignore
  2. +42 −0 Gemfile
  3. +112 −0 Gemfile.lock
  4. +58 −0 README.rdoc
  5. +7 −0 Rakefile
  6. BIN  app/assets/images/rails.png
  7. +15 −0 app/assets/javascripts/application.js
  8. +20 −0 app/assets/javascripts/helper.js
  9. +2 −0  app/assets/javascripts/home.js
  10. +2 −0  app/assets/javascripts/host_classes.js
  11. +2 −0  app/assets/javascripts/hosts.js
  12. +2 −0  app/assets/javascripts/lookup_keys.js
  13. +2 −0  app/assets/javascripts/lookup_values.js
  14. +2 −0  app/assets/javascripts/puppetclasses.js
  15. +13 −0 app/assets/stylesheets/application.css
  16. +16 −0 app/assets/stylesheets/helper.css
  17. +4 −0 app/assets/stylesheets/home.css
  18. +4 −0 app/assets/stylesheets/host_classes.css
  19. +4 −0 app/assets/stylesheets/hosts.css
  20. +4 −0 app/assets/stylesheets/lookup_keys.css
  21. +4 −0 app/assets/stylesheets/lookup_values.css
  22. +4 −0 app/assets/stylesheets/puppetclasses.css
  23. +56 −0 app/assets/stylesheets/scaffold.css
  24. +3 −0  app/controllers/application_controller.rb
  25. +4 −0 app/controllers/home_controller.rb
  26. +83 −0 app/controllers/host_classes_controller.rb
  27. +83 −0 app/controllers/hosts_controller.rb
  28. +83 −0 app/controllers/lookup_keys_controller.rb
  29. +83 −0 app/controllers/lookup_values_controller.rb
  30. +83 −0 app/controllers/puppetclasses_controller.rb
  31. +25 −0 app/helpers/application_helper.rb
  32. +2 −0  app/helpers/home_helper.rb
  33. +2 −0  app/helpers/host_classes_helper.rb
  34. +2 −0  app/helpers/hosts_helper.rb
  35. +2 −0  app/helpers/lookup_keys_helper.rb
  36. +2 −0  app/helpers/lookup_values_helper.rb
  37. +2 −0  app/helpers/puppetclasses_helper.rb
  38. 0  app/mailers/.gitkeep
  39. 0  app/models/.gitkeep
  40. +12 −0 app/models/host.rb
  41. +5 −0 app/models/host_class.rb
  42. +11 −0 app/models/lookup_key.rb
  43. +9 −0 app/models/lookup_value.rb
  44. +11 −0 app/models/puppetclass.rb
  45. +1 −0  app/views/home/index.html.erb
  46. +25 −0 app/views/host_classes/_form.html.erb
  47. +6 −0 app/views/host_classes/edit.html.erb
  48. +25 −0 app/views/host_classes/index.html.erb
  49. +5 −0 app/views/host_classes/new.html.erb
  50. +15 −0 app/views/host_classes/show.html.erb
  51. +49 −0 app/views/hosts/_form.html.erb
  52. +6 −0 app/views/hosts/edit.html.erb
  53. +23 −0 app/views/hosts/index.html.erb
  54. +5 −0 app/views/hosts/new.html.erb
  55. +28 −0 app/views/hosts/show.html.erb
  56. +27 −0 app/views/layouts/application.html.erb
  57. +32 −0 app/views/lookup_keys/_fields.html.erb
  58. +19 −0 app/views/lookup_keys/_form.html.erb
  59. +6 −0 app/views/lookup_keys/edit.html.erb
  60. +27 −0 app/views/lookup_keys/index.html.erb
  61. +5 −0 app/views/lookup_keys/new.html.erb
  62. +20 −0 app/views/lookup_keys/show.html.erb
  63. +24 −0 app/views/lookup_values/_fields.html.erb
  64. +20 −0 app/views/lookup_values/_form.html.erb
  65. +6 −0 app/views/lookup_values/edit.html.erb
  66. +27 −0 app/views/lookup_values/index.html.erb
  67. +5 −0 app/views/lookup_values/new.html.erb
  68. +20 −0 app/views/lookup_values/show.html.erb
  69. +30 −0 app/views/puppetclasses/_form.html.erb
  70. +6 −0 app/views/puppetclasses/edit.html.erb
  71. +23 −0 app/views/puppetclasses/index.html.erb
  72. +5 −0 app/views/puppetclasses/new.html.erb
  73. +15 −0 app/views/puppetclasses/show.html.erb
  74. +4 −0 config.ru
  75. +62 −0 config/application.rb
  76. +6 −0 config/boot.rb
  77. +25 −0 config/database.yml
  78. +5 −0 config/environment.rb
  79. +37 −0 config/environments/development.rb
  80. +67 −0 config/environments/production.rb
  81. +37 −0 config/environments/test.rb
  82. +7 −0 config/initializers/backtrace_silencers.rb
  83. +15 −0 config/initializers/inflections.rb
  84. +5 −0 config/initializers/mime_types.rb
  85. +7 −0 config/initializers/secret_token.rb
  86. +8 −0 config/initializers/session_store.rb
  87. +14 −0 config/initializers/wrap_parameters.rb
  88. +5 −0 config/locales/en.yml
  89. +70 −0 config/routes.rb
  90. +9 −0 db/migrate/20120806143308_create_hosts.rb
  91. +9 −0 db/migrate/20120806143329_create_puppetclasses.rb
  92. +12 −0 db/migrate/20120806143338_create_lookup_keys.rb
  93. +12 −0 db/migrate/20120806143343_create_lookup_values.rb
  94. +10 −0 db/migrate/20120806143359_create_host_classes.rb
  95. +56 −0 db/schema.rb
  96. +7 −0 db/seeds.rb
  97. 0  lib/assets/.gitkeep
  98. 0  lib/tasks/.gitkeep
  99. 0  log/.gitkeep
  100. +26 −0 public/404.html
  101. +26 −0 public/422.html
  102. +25 −0 public/500.html
  103. 0  public/favicon.ico
  104. +5 −0 public/robots.txt
  105. +6 −0 script/rails
  106. 0  test/fixtures/.gitkeep
  107. +9 −0 test/fixtures/host_classes.yml
  108. +7 −0 test/fixtures/hosts.yml
  109. +11 −0 test/fixtures/lookup_keys.yml
  110. +16 −0 test/fixtures/lookup_values.yml
  111. +7 −0 test/fixtures/puppetclasses.yml
  112. 0  test/functional/.gitkeep
  113. +9 −0 test/functional/home_controller_test.rb
  114. +49 −0 test/functional/host_classes_controller_test.rb
  115. +78 −0 test/functional/hosts_controller_test.rb
  116. +49 −0 test/functional/lookup_keys_controller_test.rb
  117. +49 −0 test/functional/lookup_values_controller_test.rb
  118. +49 −0 test/functional/puppetclasses_controller_test.rb
  119. 0  test/integration/.gitkeep
  120. +12 −0 test/performance/browsing_test.rb
  121. +13 −0 test/test_helper.rb
  122. 0  test/unit/.gitkeep
  123. +4 −0 test/unit/helpers/home_helper_test.rb
  124. +4 −0 test/unit/helpers/host_classes_helper_test.rb
  125. +4 −0 test/unit/helpers/hosts_helper_test.rb
  126. +4 −0 test/unit/helpers/lookup_keys_helper_test.rb
  127. +4 −0 test/unit/helpers/lookup_values_helper_test.rb
  128. +4 −0 test/unit/helpers/puppetclasses_helper_test.rb
  129. +7 −0 test/unit/host_class_test.rb
  130. +7 −0 test/unit/host_test.rb
  131. +7 −0 test/unit/lookup_key_test.rb
  132. +7 −0 test/unit/lookup_value_test.rb
  133. +7 −0 test/unit/puppetclass_test.rb
21 .gitignore
@@ -0,0 +1,21 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile ~/.gitignore_global
+
+# Ignore bundler config
+/.bundle
+
+# Ignore the default SQLite database.
+/db/*.sqlite3
+
+# Ignore all logfiles and tempfiles.
+/log/*.log
+/tmp
+
+# Ignore the vendor path, where bundler installs its stuff
+/vendor
+
+# Ignore generated documentation
+/doc
42 Gemfile
@@ -0,0 +1,42 @@
+source 'https://rubygems.org'
+
+gem 'rails', '3.2.7'
+# Bundle edge Rails instead:
+#gem 'rails', :git => 'git://github.com/rails/rails.git'
+
+gem 'therubyracer', :require => 'v8'
+#gem 'active_record_deprecated_finders', :git => 'git://github.com/rails/active_record_deprecated_finders.git'
+#gem 'journey', :git => 'git://github.com/rails/journey.git'
+
+gem 'sqlite3'
+
+gem 'json'
+
+# Gems used only for assets and not required
+# in production environments by default.
+group :assets do
+ #gem 'sass-rails', '~> 3.2.3'
+ #gem 'coffee-rails', '~> 3.2.1'
+
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
+ # gem 'therubyracer', :platforms => :ruby
+
+ gem 'uglifier', '>= 1.0.3'
+end
+
+gem 'jquery-rails'
+
+# To use ActiveModel has_secure_password
+# gem 'bcrypt-ruby', '~> 3.0.0'
+
+# To use Jbuilder templates for JSON
+# gem 'jbuilder'
+
+# Use unicorn as the app server
+# gem 'unicorn'
+
+# Deploy with Capistrano
+# gem 'capistrano'
+
+# To use debugger
+gem 'ruby-debug'
112 Gemfile.lock
@@ -0,0 +1,112 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (3.2.7)
+ actionpack (= 3.2.7)
+ mail (~> 2.4.4)
+ actionpack (3.2.7)
+ activemodel (= 3.2.7)
+ activesupport (= 3.2.7)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.4)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.3)
+ activemodel (3.2.7)
+ activesupport (= 3.2.7)
+ builder (~> 3.0.0)
+ activerecord (3.2.7)
+ activemodel (= 3.2.7)
+ activesupport (= 3.2.7)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activeresource (3.2.7)
+ activemodel (= 3.2.7)
+ activesupport (= 3.2.7)
+ activesupport (3.2.7)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+ arel (3.0.2)
+ builder (3.0.0)
+ columnize (0.3.6)
+ erubis (2.7.0)
+ execjs (1.4.0)
+ multi_json (~> 1.0)
+ hike (1.2.1)
+ i18n (0.6.0)
+ journey (1.0.4)
+ jquery-rails (2.0.2)
+ railties (>= 3.2.0, < 5.0)
+ thor (~> 0.14)
+ json (1.7.4)
+ libv8 (3.3.10.4)
+ linecache (0.46)
+ rbx-require-relative (> 0.0.4)
+ mail (2.4.4)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.19)
+ multi_json (1.3.6)
+ polyglot (0.3.3)
+ rack (1.4.1)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ rails (3.2.7)
+ actionmailer (= 3.2.7)
+ actionpack (= 3.2.7)
+ activerecord (= 3.2.7)
+ activeresource (= 3.2.7)
+ activesupport (= 3.2.7)
+ bundler (~> 1.0)
+ railties (= 3.2.7)
+ railties (3.2.7)
+ actionpack (= 3.2.7)
+ activesupport (= 3.2.7)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (>= 0.14.6, < 2.0)
+ rake (0.9.2.2)
+ rbx-require-relative (0.0.9)
+ rdoc (3.12)
+ json (~> 1.4)
+ ruby-debug (0.10.4)
+ columnize (>= 0.1)
+ ruby-debug-base (~> 0.10.4.0)
+ ruby-debug-base (0.10.4)
+ linecache (>= 0.3)
+ sprockets (2.1.3)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ sqlite3 (1.3.6)
+ therubyracer (0.10.1)
+ libv8 (~> 3.3.10)
+ thor (0.15.4)
+ tilt (1.3.3)
+ treetop (1.4.10)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.33)
+ uglifier (1.2.7)
+ execjs (>= 0.3.0)
+ multi_json (~> 1.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ jquery-rails
+ json
+ rails (= 3.2.7)
+ ruby-debug
+ sqlite3
+ therubyracer
+ uglifier (>= 1.0.3)
58 README.rdoc
@@ -0,0 +1,58 @@
+= PoB: +parent_id+ gets included with +:finder_sql+ association
+
+This sample Rails web-application tends to reproduce a part of Foreman's architecture
+in order to highlight a potential bug of Rails.
+
+== How to fire the bug
+
+=== Using functional testing
+
+run `rake test`, or the following command:
+
+ $ rake test TEST=test/functional/hosts_controller_test.rb
+
+You will get:
+
+ DEPRECATION WARNING: The :finder_sql association option is deprecated. Please find an alternative (such as using scopes). (called from /data/theforeman/test-shortcut/app/models/host.rb:5)
+ Loaded suite /data/theforeman/test-shortcut/vendor/ruby/1.8/gems/rake-0.9.2.2/lib/rake/rake_test_loader
+ Started
+ ........E
+ Finished in 0.328863 seconds.
+
+ 1) Error:
+ test_should_update_lookup_value(HostsControllerTest):
+ ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: lookup_values.host_id: SELECT "lookup_values".* FROM "lookup_values" WHERE "lookup_values"."host_id" = 980190962 AND "lookup_values"."id" IN (980190962)
+ app/controllers/hosts_controller.rb:62:in `update'
+ app/controllers/hosts_controller.rb:61:in `update'
+ test/functional/hosts_controller_test.rb:56:in `test_should_update_lookup_value'
+
+ 9 tests, 11 assertions, 0 failures, 1 errors
+ rake aborted!
+ Command failed with status (1): [/usr/bin/ruby1.8 -I"lib:test" -I"/data/the...]
+
+ Tasks: TOP => test:single
+ (See full trace by running task with --trace)
+
+=== Manually through the web UI
+
+1. Create a puppetclass
+
+2. Create a lookup key
+
+3. Create a lookup value, with matcher "hostname=foo"
+
+4. Create a host of name "foo"
+
+5. Associate the host to the created puppetclass
+
+6. Edit the host
+
+ Eventually modify the lookup value's value
+
+ Save
+
+You will get:
+
+ ActiveRecord::StatementInvalid in HostsController#update
+
+ SQLite3::SQLException: no such column: lookup_values.host_id: SELECT "lookup_values".* FROM "lookup_values" WHERE "lookup_values"."host_id" = 1 AND "lookup_values"."id" IN (1)
7 Rakefile
@@ -0,0 +1,7 @@
+#!/usr/bin/env rake
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+TestShortcut::Application.load_tasks
BIN  app/assets/images/rails.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 app/assets/javascripts/application.js
@@ -0,0 +1,15 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// the compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require jquery
+//= require jquery_ujs
+//= require_tree .
20 app/assets/javascripts/helper.js
@@ -0,0 +1,20 @@
+$(function() {
+ $('form a.add_child').click(function() {
+ var association = $(this).attr('data-association');
+ var template = $('#' + association + '_fields_template').html();
+ var regexp = new RegExp('new_' + association, 'g');
+ var new_id = new Date().getTime();
+
+ $(this).parent().before(template.replace(regexp, new_id));
+ return false;
+ });
+
+ $('form a.remove_child').live('click', function() {
+ var hidden_field = $(this).prev('input[type=hidden]')[0];
+ if(hidden_field) {
+ hidden_field.value = '1';
+ }
+ $(this).parents('.fields').hide();
+ return false;
+ });
+});
2  app/assets/javascripts/home.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
2  app/assets/javascripts/host_classes.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
2  app/assets/javascripts/hosts.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
2  app/assets/javascripts/lookup_keys.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
2  app/assets/javascripts/lookup_values.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
2  app/assets/javascripts/puppetclasses.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
13 app/assets/stylesheets/application.css
@@ -0,0 +1,13 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+ */
16 app/assets/stylesheets/helper.css
@@ -0,0 +1,16 @@
+.topbar {
+ left: 0px;
+ top: 0px;
+ right: 0px;
+
+ background-color: black;
+ color: white;
+}
+
+.topbar a, .topbar a:visited {
+ color: white;
+}
+
+.inline, ul.menu li {
+ display: inline-block;
+}
4 app/assets/stylesheets/home.css
@@ -0,0 +1,4 @@
+/*
+ Place all the styles related to the matching controller here.
+ They will automatically be included in application.css.
+*/
4 app/assets/stylesheets/host_classes.css
@@ -0,0 +1,4 @@
+/*
+ Place all the styles related to the matching controller here.
+ They will automatically be included in application.css.
+*/
4 app/assets/stylesheets/hosts.css
@@ -0,0 +1,4 @@
+/*
+ Place all the styles related to the matching controller here.
+ They will automatically be included in application.css.
+*/
4 app/assets/stylesheets/lookup_keys.css
@@ -0,0 +1,4 @@
+/*
+ Place all the styles related to the matching controller here.
+ They will automatically be included in application.css.
+*/
4 app/assets/stylesheets/lookup_values.css
@@ -0,0 +1,4 @@
+/*
+ Place all the styles related to the matching controller here.
+ They will automatically be included in application.css.
+*/
4 app/assets/stylesheets/puppetclasses.css
@@ -0,0 +1,4 @@
+/*
+ Place all the styles related to the matching controller here.
+ They will automatically be included in application.css.
+*/
56 app/assets/stylesheets/scaffold.css
@@ -0,0 +1,56 @@
+body { background-color: #fff; color: #333; }
+
+body, p, ol, ul, td {
+ font-family: verdana, arial, helvetica, sans-serif;
+ font-size: 13px;
+ line-height: 18px;
+}
+
+pre {
+ background-color: #eee;
+ padding: 10px;
+ font-size: 11px;
+}
+
+a { color: #000; }
+a:visited { color: #666; }
+a:hover { color: #fff; background-color:#000; }
+
+div.field, div.actions {
+ margin-bottom: 10px;
+}
+
+#notice {
+ color: green;
+}
+
+.field_with_errors {
+ padding: 2px;
+ background-color: red;
+ display: table;
+}
+
+#error_explanation {
+ width: 450px;
+ border: 2px solid red;
+ padding: 7px;
+ padding-bottom: 0;
+ margin-bottom: 20px;
+ background-color: #f0f0f0;
+}
+
+#error_explanation h2 {
+ text-align: left;
+ font-weight: bold;
+ padding: 5px 5px 5px 15px;
+ font-size: 12px;
+ margin: -7px;
+ margin-bottom: 0px;
+ background-color: #c00;
+ color: #fff;
+}
+
+#error_explanation ul li {
+ font-size: 12px;
+ list-style: square;
+}
3  app/controllers/application_controller.rb
@@ -0,0 +1,3 @@
+class ApplicationController < ActionController::Base
+ protect_from_forgery
+end
4 app/controllers/home_controller.rb
@@ -0,0 +1,4 @@
+class HomeController < ApplicationController
+ def index
+ end
+end
83 app/controllers/host_classes_controller.rb
@@ -0,0 +1,83 @@
+class HostClassesController < ApplicationController
+ # GET /host_classes
+ # GET /host_classes.json
+ def index
+ @host_classes = HostClass.all
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.json { render :json => @host_classes }
+ end
+ end
+
+ # GET /host_classes/1
+ # GET /host_classes/1.json
+ def show
+ @host_class = HostClass.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.json { render :json => @host_class }
+ end
+ end
+
+ # GET /host_classes/new
+ # GET /host_classes/new.json
+ def new
+ @host_class = HostClass.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.json { render :json => @host_class }
+ end
+ end
+
+ # GET /host_classes/1/edit
+ def edit
+ @host_class = HostClass.find(params[:id])
+ end
+
+ # POST /host_classes
+ # POST /host_classes.json
+ def create
+ @host_class = HostClass.new(params[:host_class])
+
+ respond_to do |format|
+ if @host_class.save
+ format.html { redirect_to @host_class, :notice => 'Host class was successfully created.' }
+ format.json { render :json => @host_class, :status => :created, :location => @host_class }
+ else
+ format.html { render :action => "new" }
+ format.json { render :json => @host_class.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /host_classes/1
+ # PUT /host_classes/1.json
+ def update
+ @host_class = HostClass.find(params[:id])
+
+ respond_to do |format|
+ if @host_class.update_attributes(params[:host_class])
+ format.html { redirect_to @host_class, :notice => 'Host class was successfully updated.' }
+ format.json { head :no_content }
+ else
+ format.html { render :action => "edit" }
+ format.json { render :json => @host_class.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /host_classes/1
+ # DELETE /host_classes/1.json
+ def destroy
+ @host_class = HostClass.find(params[:id])
+ @host_class.destroy
+
+ respond_to do |format|
+ format.html { redirect_to host_classes_url }
+ format.json { head :no_content }
+ end
+ end
+end
83 app/controllers/hosts_controller.rb
@@ -0,0 +1,83 @@
+class HostsController < ApplicationController
+ # GET /hosts
+ # GET /hosts.json
+ def index
+ @hosts = Host.all
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.json { render :json => @hosts }
+ end
+ end
+
+ # GET /hosts/1
+ # GET /hosts/1.json
+ def show
+ @host = Host.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.json { render :json => @host }
+ end
+ end
+
+ # GET /hosts/new
+ # GET /hosts/new.json
+ def new
+ @host = Host.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.json { render :json => @host }
+ end
+ end
+
+ # GET /hosts/1/edit
+ def edit
+ @host = Host.find(params[:id])
+ end
+
+ # POST /hosts
+ # POST /hosts.json
+ def create
+ @host = Host.new(params[:host])
+
+ respond_to do |format|
+ if @host.save
+ format.html { redirect_to @host, :notice => 'Host was successfully created.' }
+ format.json { render :json => @host, :status => :created, :location => @host }
+ else
+ format.html { render :action => "new" }
+ format.json { render :json => @host.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /hosts/1
+ # PUT /hosts/1.json
+ def update
+ @host = Host.find(params[:id])
+
+ respond_to do |format|
+ if @host.update_attributes(params[:host])
+ format.html { redirect_to @host, :notice => 'Host was successfully updated.' }
+ format.json { head :no_content }
+ else
+ format.html { render :action => "edit" }
+ format.json { render :json => @host.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /hosts/1
+ # DELETE /hosts/1.json
+ def destroy
+ @host = Host.find(params[:id])
+ @host.destroy
+
+ respond_to do |format|
+ format.html { redirect_to hosts_url }
+ format.json { head :no_content }
+ end
+ end
+end
83 app/controllers/lookup_keys_controller.rb
@@ -0,0 +1,83 @@
+class LookupKeysController < ApplicationController
+ # GET /lookup_keys
+ # GET /lookup_keys.json
+ def index
+ @lookup_keys = LookupKey.all
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.json { render :json => @lookup_keys }
+ end
+ end
+
+ # GET /lookup_keys/1
+ # GET /lookup_keys/1.json
+ def show
+ @lookup_key = LookupKey.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.json { render :json => @lookup_key }
+ end
+ end
+
+ # GET /lookup_keys/new
+ # GET /lookup_keys/new.json
+ def new
+ @lookup_key = LookupKey.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.json { render :json => @lookup_key }
+ end
+ end
+
+ # GET /lookup_keys/1/edit
+ def edit
+ @lookup_key = LookupKey.find(params[:id])
+ end
+
+ # POST /lookup_keys
+ # POST /lookup_keys.json
+ def create
+ @lookup_key = LookupKey.new(params[:lookup_key])
+
+ respond_to do |format|
+ if @lookup_key.save
+ format.html { redirect_to @lookup_key, :notice => 'Lookup key was successfully created.' }
+ format.json { render :json => @lookup_key, :status => :created, :location => @lookup_key }
+ else
+ format.html { render :action => "new" }
+ format.json { render :json => @lookup_key.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /lookup_keys/1
+ # PUT /lookup_keys/1.json
+ def update
+ @lookup_key = LookupKey.find(params[:id])
+
+ respond_to do |format|
+ if @lookup_key.update_attributes(params[:lookup_key])
+ format.html { redirect_to @lookup_key, :notice => 'Lookup key was successfully updated.' }
+ format.json { head :no_content }
+ else
+ format.html { render :action => "edit" }
+ format.json { render :json => @lookup_key.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /lookup_keys/1
+ # DELETE /lookup_keys/1.json
+ def destroy
+ @lookup_key = LookupKey.find(params[:id])
+ @lookup_key.destroy
+
+ respond_to do |format|
+ format.html { redirect_to lookup_keys_url }
+ format.json { head :no_content }
+ end
+ end
+end
83 app/controllers/lookup_values_controller.rb
@@ -0,0 +1,83 @@
+class LookupValuesController < ApplicationController
+ # GET /lookup_values
+ # GET /lookup_values.json
+ def index
+ @lookup_values = LookupValue.all
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.json { render :json => @lookup_values }
+ end
+ end
+
+ # GET /lookup_values/1
+ # GET /lookup_values/1.json
+ def show
+ @lookup_value = LookupValue.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.json { render :json => @lookup_value }
+ end
+ end
+
+ # GET /lookup_values/new
+ # GET /lookup_values/new.json
+ def new
+ @lookup_value = LookupValue.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.json { render :json => @lookup_value }
+ end
+ end
+
+ # GET /lookup_values/1/edit
+ def edit
+ @lookup_value = LookupValue.find(params[:id])
+ end
+
+ # POST /lookup_values
+ # POST /lookup_values.json
+ def create
+ @lookup_value = LookupValue.new(params[:lookup_value])
+
+ respond_to do |format|
+ if @lookup_value.save
+ format.html { redirect_to @lookup_value, :notice => 'Lookup value was successfully created.' }
+ format.json { render :json => @lookup_value, :status => :created, :location => @lookup_value }
+ else
+ format.html { render :action => "new" }
+ format.json { render :json => @lookup_value.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /lookup_values/1
+ # PUT /lookup_values/1.json
+ def update
+ @lookup_value = LookupValue.find(params[:id])
+
+ respond_to do |format|
+ if @lookup_value.update_attributes(params[:lookup_value])
+ format.html { redirect_to @lookup_value, :notice => 'Lookup value was successfully updated.' }
+ format.json { head :no_content }
+ else
+ format.html { render :action => "edit" }
+ format.json { render :json => @lookup_value.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /lookup_values/1
+ # DELETE /lookup_values/1.json
+ def destroy
+ @lookup_value = LookupValue.find(params[:id])
+ @lookup_value.destroy
+
+ respond_to do |format|
+ format.html { redirect_to lookup_values_url }
+ format.json { head :no_content }
+ end
+ end
+end
83 app/controllers/puppetclasses_controller.rb
@@ -0,0 +1,83 @@
+class PuppetclassesController < ApplicationController
+ # GET /puppetclasses
+ # GET /puppetclasses.json
+ def index
+ @puppetclasses = Puppetclass.all
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.json { render :json => @puppetclasses }
+ end
+ end
+
+ # GET /puppetclasses/1
+ # GET /puppetclasses/1.json
+ def show
+ @puppetclass = Puppetclass.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.json { render :json => @puppetclass }
+ end
+ end
+
+ # GET /puppetclasses/new
+ # GET /puppetclasses/new.json
+ def new
+ @puppetclass = Puppetclass.new
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.json { render :json => @puppetclass }
+ end
+ end
+
+ # GET /puppetclasses/1/edit
+ def edit
+ @puppetclass = Puppetclass.find(params[:id])
+ end
+
+ # POST /puppetclasses
+ # POST /puppetclasses.json
+ def create
+ @puppetclass = Puppetclass.new(params[:puppetclass])
+
+ respond_to do |format|
+ if @puppetclass.save
+ format.html { redirect_to @puppetclass, :notice => 'Puppetclass was successfully created.' }
+ format.json { render :json => @puppetclass, :status => :created, :location => @puppetclass }
+ else
+ format.html { render :action => "new" }
+ format.json { render :json => @puppetclass.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /puppetclasses/1
+ # PUT /puppetclasses/1.json
+ def update
+ @puppetclass = Puppetclass.find(params[:id])
+
+ respond_to do |format|
+ if @puppetclass.update_attributes(params[:puppetclass])
+ format.html { redirect_to @puppetclass, :notice => 'Puppetclass was successfully updated.' }
+ format.json { head :no_content }
+ else
+ format.html { render :action => "edit" }
+ format.json { render :json => @puppetclass.errors, :status => :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /puppetclasses/1
+ # DELETE /puppetclasses/1.json
+ def destroy
+ @puppetclass = Puppetclass.find(params[:id])
+ @puppetclass.destroy
+
+ respond_to do |format|
+ format.html { redirect_to puppetclasses_url }
+ format.json { head :no_content }
+ end
+ end
+end
25 app/helpers/application_helper.rb
@@ -0,0 +1,25 @@
+module ApplicationHelper
+
+ def new_child_fields_template(form_builder, association, options = {})
+ options[:object] ||= form_builder.object.class.reflect_on_association(association).klass.new
+ options[:partial] ||= association.to_s.singularize
+ options[:form_builder_local] ||= :f
+
+ content_for :jstemplates do
+ content_tag(:div, :id => "#{association}_fields_template", :style => "display: none") do
+ form_builder.fields_for(association, options[:object], :child_index => "new_#{association}_attributes") do |f|
+ render(:partial => options[:partial], :locals => { options[:form_builder_local] => f })
+ end
+ end
+ end
+ end
+
+ def add_child_link(name, association)
+ link_to(name, "javascript:void(0)", :class => "add_child", :"data-association" => association)
+ end
+
+ def remove_child_link(name, f)
+ f.hidden_field(:_destroy) + link_to(name, "javascript:void(0)", :class => "remove_child")
+ end
+
+end
2  app/helpers/home_helper.rb
@@ -0,0 +1,2 @@
+module HomeHelper
+end
2  app/helpers/host_classes_helper.rb
@@ -0,0 +1,2 @@
+module HostClassesHelper
+end
2  app/helpers/hosts_helper.rb
@@ -0,0 +1,2 @@
+module HostsHelper
+end
2  app/helpers/lookup_keys_helper.rb
@@ -0,0 +1,2 @@
+module LookupKeysHelper
+end
2  app/helpers/lookup_values_helper.rb
@@ -0,0 +1,2 @@
+module LookupValuesHelper
+end
2  app/helpers/puppetclasses_helper.rb
@@ -0,0 +1,2 @@
+module PuppetclassesHelper
+end
0  app/mailers/.gitkeep
No changes.
0  app/models/.gitkeep
No changes.
12 app/models/host.rb
@@ -0,0 +1,12 @@
+class Host < ActiveRecord::Base
+ attr_accessible :name, :puppetclasses, :puppetclass_ids, :lookup_values_attributes
+ has_and_belongs_to_many :puppetclasses, :join_table => 'host_classes'
+
+ has_many :lookup_values, :dependent => :destroy,
+ :finder_sql => Proc.new { |host| %Q{ SELECT * FROM `lookup_values` WHERE `lookup_values`.`matcher` = 'hostname=#{name}' } }
+ accepts_nested_attributes_for :lookup_values, :allow_destroy => true
+
+ def to_label
+ name
+ end
+end
5 app/models/host_class.rb
@@ -0,0 +1,5 @@
+class HostClass < ActiveRecord::Base
+ belongs_to :host
+ belongs_to :puppetclass
+ # attr_accessible :title, :body
+end
11 app/models/lookup_key.rb
@@ -0,0 +1,11 @@
+class LookupKey < ActiveRecord::Base
+ attr_accessible :puppetclass_id, :default_value, :key, :lookup_values_attributes
+
+ belongs_to :puppetclass
+ has_many :lookup_values
+ accepts_nested_attributes_for :lookup_values, :allow_destroy => true
+
+ def to_label
+ puppetclass.try(:name) + " :: " + key
+ end
+end
9 app/models/lookup_value.rb
@@ -0,0 +1,9 @@
+class LookupValue < ActiveRecord::Base
+ attr_accessible :lookup_key_id, :value, :matcher
+
+ belongs_to :lookup_key
+
+ def to_label
+ lookup_key.to_label + " [" + matcher + "]"
+ end
+end
11 app/models/puppetclass.rb
@@ -0,0 +1,11 @@
+class Puppetclass < ActiveRecord::Base
+ attr_accessible :name, :lookup_keys_attributes
+
+ has_and_belongs_to_many :hosts, :join_table => 'host_classes'
+ has_many :lookup_keys
+ accepts_nested_attributes_for :lookup_keys, :allow_destroy => true
+
+ def to_label
+ name
+ end
+end
1  app/views/home/index.html.erb
@@ -0,0 +1 @@
+<h1>Foreman :finder_sql shortcut bug</h1>
25 app/views/host_classes/_form.html.erb
@@ -0,0 +1,25 @@
+<%= form_for(@host_class) do |f| %>
+ <% if @host_class.errors.any? %>
+ <div id="error_explanation">
+ <h2><%= pluralize(@host_class.errors.count, "error") %> prohibited this host_class from being saved:</h2>
+
+ <ul>
+ <% @host_class.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <div class="field">
+ <%= f.label :host %><br />
+ <%= f.text_field :host %>
+ </div>
+ <div class="field">
+ <%= f.label :puppetclass %><br />
+ <%= f.text_field :puppetclass %>
+ </div>
+ <div class="actions">
+ <%= f.submit %>
+ </div>
+<% end %>
6 app/views/host_classes/edit.html.erb
@@ -0,0 +1,6 @@
+<h1>Editing host_class</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Show', @host_class %> |
+<%= link_to 'Back', host_classes_path %>
25 app/views/host_classes/index.html.erb
@@ -0,0 +1,25 @@
+<h1>Listing host_classes</h1>
+
+<table>
+ <tr>
+ <th>Host</th>
+ <th>Puppetclass</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<% @host_classes.each do |host_class| %>
+ <tr>
+ <td><%= host_class.host %></td>
+ <td><%= host_class.puppetclass %></td>
+ <td><%= link_to 'Show', host_class %></td>
+ <td><%= link_to 'Edit', edit_host_class_path(host_class) %></td>
+ <td><%= link_to 'Destroy', host_class, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New Host class', new_host_class_path %>
5 app/views/host_classes/new.html.erb
@@ -0,0 +1,5 @@
+<h1>New host_class</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', host_classes_path %>
15 app/views/host_classes/show.html.erb
@@ -0,0 +1,15 @@
+<p id="notice"><%= notice %></p>
+
+<p>
+ <b>Host:</b>
+ <%= @host_class.host %>
+</p>
+
+<p>
+ <b>Puppetclass:</b>
+ <%= @host_class.puppetclass %>
+</p>
+
+
+<%= link_to 'Edit', edit_host_class_path(@host_class) %> |
+<%= link_to 'Back', host_classes_path %>
49 app/views/hosts/_form.html.erb
@@ -0,0 +1,49 @@
+<%= form_for(@host) do |f| %>
+ <% if @host.errors.any? %>
+ <div id="error_explanation">
+ <h2><%= pluralize(@host.errors.count, "error") %> prohibited this host from being saved:</h2>
+
+ <ul>
+ <% @host.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <div class="field">
+ <%= f.label :name %><br />
+ <%= f.text_field :name %>
+ </div>
+
+ <h2>Puppetclasses</h2>
+ <ul>
+ <%= f.fields_for :puppetclass_ids do |builder| %>
+ <%= builder.hidden_field '' %>
+ <% Puppetclass.all.sort { |pc1,pc2| pc1.name <=> pc2.name }.each do |puppetclass| %>
+ <%= content_tag :li do %>
+ <%= builder.label '' do %>
+ <%= builder.check_box '', { :checked => @host.puppetclass_ids.include?(puppetclass.id) }, puppetclass.id, '' %>
+ <%= puppetclass.name %>
+ <% end -%>
+ <% end -%>
+ <% end -%>
+ <% end -%>
+ </ul>
+
+ <h2>Lookup values</h2>
+ <ul>
+ <%# XXX This is the problematic form XXX %>
+ <%= f.fields_for :lookup_values do |builder| %>
+ <%= content_tag :li, :class => 'fields' do %>
+ <%= builder.object.lookup_key.to_label %> =
+ <%= builder.text_field :value %>
+ <%= remove_child_link "Remove", builder %>
+ <% end -%>
+ <% end -%>
+ </ul>
+
+ <div class="actions">
+ <%= f.submit %>
+ </div>
+<% end %>
6 app/views/hosts/edit.html.erb
@@ -0,0 +1,6 @@
+<h1>Editing host</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Show', @host %> |
+<%= link_to 'Back', hosts_path %>
23 app/views/hosts/index.html.erb
@@ -0,0 +1,23 @@
+<h1>Listing hosts</h1>
+
+<table>
+ <tr>
+ <th>Name</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<% @hosts.each do |host| %>
+ <tr>
+ <td><%= host.name %></td>
+ <td><%= link_to 'Show', host %></td>
+ <td><%= link_to 'Edit', edit_host_path(host) %></td>
+ <td><%= link_to 'Destroy', host, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New Host', new_host_path %>
5 app/views/hosts/new.html.erb
@@ -0,0 +1,5 @@
+<h1>New host</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', hosts_path %>
28 app/views/hosts/show.html.erb
@@ -0,0 +1,28 @@
+<p id="notice"><%= notice %></p>
+
+<p>
+ <b>Name:</b>
+ <%= @host.name %>
+</p>
+
+
+<h2>Puppetclasses</h2>
+<ul>
+ <% @host.puppetclasses.each do |puppetclass| %>
+ <%= content_tag :li do %>
+ <%= puppetclass.to_label %>
+ <% end -%>
+ <% end -%>
+</ul>
+
+<h2>Lookup values</h2>
+<ul>
+ <% @host.lookup_values.each do |lookup_value| %>
+ <%= content_tag :li do %>
+ <%= lookup_value.to_label %>
+ <% end -%>
+ <% end -%>
+</ul>
+
+<%= link_to 'Edit', edit_host_path(@host) %> |
+<%= link_to 'Back', hosts_path %>
27 app/views/layouts/application.html.erb
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>TestShortcut</title>
+ <%= stylesheet_link_tag "application", :media => "all" %>
+ <%= javascript_include_tag "application" %>
+ <%= csrf_meta_tags %>
+</head>
+<body>
+
+ <div class="topbar">
+ <ul class="inline menu">
+ <li><%= link_to 'Hosts', hosts_path %></li>
+ <li><%= link_to 'Puppetclasses', puppetclasses_path %></li>
+ <li><%= link_to 'Lookup keys', lookup_keys_path %></li>
+ <li><%= link_to 'Lookup values', lookup_values_path %></li>
+ </ul>
+ </div>
+
+<%= yield %>
+
+<div id="jstemplates">
+ <%= yield :jstemplates %>
+</div>
+
+</body>
+</html>
32 app/views/lookup_keys/_fields.html.erb
@@ -0,0 +1,32 @@
+<div <%= "id=#{(f.object.key || 'new_lookup_keys').to_s.gsub(' ','_')}" %> class="fields" >
+
+ <%= remove_child_link "Remove #{f.object.new_record? ? "Variable" : f.object}", f unless controller_name == "lookup_keys" %>
+
+ <%=
+ if params["puppetclass_id"] # new smart-var inside a puppetclass (REST nesting only)
+ # Show the parent puppetclass as a context, but permit no change
+ f.collection_select :puppetclass_id, [Puppetclass.from_param(params["puppetclass_id"])], :id, :to_label, {}, {:label => "Puppet class", :disabled => true}
+ else # new smart-var with no particular context
+ # Give a select for choosing the parent puppetclass
+ f.collection_select :puppetclass_id, Puppetclass.all, :id, :to_label, { :include_blank => 'None' }, {:label => "Puppet class"}
+ end unless @puppetclass or f.parent_builder.try(:object).is_a? Puppetclass # nested smart-vars form in a tab of puppetclass/_form: no edition allowed, and the puppetclass is already visible as a context
+ %>
+
+ <div class="field">
+ <%= f.label :key %><br />
+ <%= f.text_field :key %>
+ </div>
+ <div class="field">
+ <%= f.label :default_value %><br />
+ <%= f.text_field :default_value %>
+ </div>
+
+ <div id="lookup_values">
+ <%= f.fields_for :lookup_values do |builder| %>
+ <%= render :partial => 'lookup_values/fields', :locals => { :f => builder } %>
+ <% end -%>
+ <%= add_child_link 'New lookup values', :lookup_values %>
+ <%= new_child_fields_template f, :lookup_values, {:partial => 'lookup_values/fields'} %>
+ </div>
+
+</div>
19 app/views/lookup_keys/_form.html.erb
@@ -0,0 +1,19 @@
+<%= form_for(@lookup_key) do |f| %>
+ <% if @lookup_key.errors.any? %>
+ <div id="error_explanation">
+ <h2><%= pluralize(@lookup_key.errors.count, "error") %> prohibited this lookup_key from being saved:</h2>
+
+ <ul>
+ <% @lookup_key.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <%= render :partial => 'fields', :locals => { :f => f } %>
+
+ <div class="actions">
+ <%= f.submit %>
+ </div>
+<% end %>
6 app/views/lookup_keys/edit.html.erb
@@ -0,0 +1,6 @@
+<h1>Editing lookup_key</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Show', @lookup_key %> |
+<%= link_to 'Back', lookup_keys_path %>
27 app/views/lookup_keys/index.html.erb
@@ -0,0 +1,27 @@
+<h1>Listing lookup_keys</h1>
+
+<table>
+ <tr>
+ <th>Key</th>
+ <th>Default value</th>
+ <th>Puppetclass</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<% @lookup_keys.each do |lookup_key| %>
+ <tr>
+ <td><%= lookup_key.key %></td>
+ <td><%= lookup_key.default_value %></td>
+ <td><%= lookup_key.puppetclass.name %></td>
+ <td><%= link_to 'Show', lookup_key %></td>
+ <td><%= link_to 'Edit', edit_lookup_key_path(lookup_key) %></td>
+ <td><%= link_to 'Destroy', lookup_key, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New Lookup key', new_lookup_key_path %>
5 app/views/lookup_keys/new.html.erb
@@ -0,0 +1,5 @@
+<h1>New lookup_key</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', lookup_keys_path %>
20 app/views/lookup_keys/show.html.erb
@@ -0,0 +1,20 @@
+<p id="notice"><%= notice %></p>
+
+<p>
+ <b>Key:</b>
+ <%= @lookup_key.key %>
+</p>
+
+<p>
+ <b>Default value:</b>
+ <%= @lookup_key.default_value %>
+</p>
+
+<p>
+ <b>Puppetclass:</b>
+ <%= @lookup_key.puppetclass.name %>
+</p>
+
+
+<%= link_to 'Edit', edit_lookup_key_path(@lookup_key) %> |
+<%= link_to 'Back', lookup_keys_path %>
24 app/views/lookup_values/_fields.html.erb
@@ -0,0 +1,24 @@
+<div <%= "id=#{(f.object.key || 'new_lookup_keys').to_s.gsub(' ','_')}" %> class="fields" >
+
+ <%= remove_child_link "Remove #{f.object.new_record? ? "Value" : f.object}", f unless controller_name == "lookup_values" %>
+
+ <%=
+ if params["lookup_value_id"] # new value inside a lookup_key (REST nesting only)
+ # Show the parent lookup key as a context, but permit no change
+ f.collection_select :lookup_value_id, [Puppetclass.from_param(params["lookup_value_id"])], :id, :to_label, {}, {:label => "Lookup key", :disabled => true}
+ else # new lookup key with no particular context
+ # Give a select for choosing the parent lookup key
+ f.collection_select :lookup_key_id, LookupKey.all, :id, :to_label, { :include_blank => 'None' }, {:label => "Lookup key"}
+ end unless @lookup_key or f.parent_builder.try(:object).is_a? LookupKey # nested value form in a tab of puppetclass/_form: no edition allowed, and the lookup key is already visible as a context
+ %>
+
+ <div class="field">
+ <%= f.label :matcher %><br />
+ <%= f.text_field :matcher %>
+ </div>
+ <div class="field">
+ <%= f.label :value %><br />
+ <%= f.text_field :value %>
+ </div>
+
+</div>
20 app/views/lookup_values/_form.html.erb
@@ -0,0 +1,20 @@
+<%= form_for(@lookup_value) do |f| %>
+ <% if @lookup_value.errors.any? %>
+ <div id="error_explanation">
+ <h2><%= pluralize(@lookup_value.errors.count, "error") %> prohibited this lookup_value from being saved:</h2>
+
+ <ul>
+ <% @lookup_value.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <%= render :partial => 'fields', :locals => { :f => f } %>
+
+ <div class="actions">
+ <%= f.submit %>
+ </div>
+
+<% end %>
6 app/views/lookup_values/edit.html.erb
@@ -0,0 +1,6 @@
+<h1>Editing lookup_value</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Show', @lookup_value %> |
+<%= link_to 'Back', lookup_values_path %>
27 app/views/lookup_values/index.html.erb
@@ -0,0 +1,27 @@
+<h1>Listing lookup_values</h1>
+
+<table>
+ <tr>
+ <th>Matcher</th>
+ <th>Value</th>
+ <th>Lookup key</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<% @lookup_values.each do |lookup_value| %>
+ <tr>
+ <td><%= lookup_value.matcher %></td>
+ <td><%= lookup_value.value %></td>
+ <td><%= lookup_value.lookup_key.to_label %></td>
+ <td><%= link_to 'Show', lookup_value %></td>
+ <td><%= link_to 'Edit', edit_lookup_value_path(lookup_value) %></td>
+ <td><%= link_to 'Destroy', lookup_value, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New Lookup value', new_lookup_value_path %>
5 app/views/lookup_values/new.html.erb
@@ -0,0 +1,5 @@
+<h1>New lookup_value</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', lookup_values_path %>
20 app/views/lookup_values/show.html.erb
@@ -0,0 +1,20 @@
+<p id="notice"><%= notice %></p>
+
+<p>
+ <b>Matcher:</b>
+ <%= @lookup_value.matcher %>
+</p>
+
+<p>
+ <b>Value:</b>
+ <%= @lookup_value.value %>
+</p>
+
+<p>
+ <b>Lookup key:</b>
+ <%= @lookup_value.lookup_key.to_label %>
+</p>
+
+
+<%= link_to 'Edit', edit_lookup_value_path(@lookup_value) %> |
+<%= link_to 'Back', lookup_values_path %>
30 app/views/puppetclasses/_form.html.erb
@@ -0,0 +1,30 @@
+<%= form_for(@puppetclass) do |f| %>
+ <% if @puppetclass.errors.any? %>
+ <div id="error_explanation">
+ <h2><%= pluralize(@puppetclass.errors.count, "error") %> prohibited this puppetclass from being saved:</h2>
+
+ <ul>
+ <% @puppetclass.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <div class="field">
+ <%= f.label :name %><br />
+ <%= f.text_field :name %>
+ </div>
+
+ <div id="lookup_keys">
+ <%= f.fields_for :lookup_keys do |builder| %>
+ <%= render :partial => 'lookup_keys/fields', :locals => { :f => builder } %>
+ <% end -%>
+ <%= add_child_link 'New lookup keys', :lookup_keys %>
+ <%= new_child_fields_template f, :lookup_keys, {:partial => 'lookup_keys/fields'} %>
+ </div>
+
+ <div class="actions">
+ <%= f.submit %>
+ </div>
+<% end %>
6 app/views/puppetclasses/edit.html.erb
@@ -0,0 +1,6 @@
+<h1>Editing puppetclass</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Show', @puppetclass %> |
+<%= link_to 'Back', puppetclasses_path %>
23 app/views/puppetclasses/index.html.erb
@@ -0,0 +1,23 @@
+<h1>Listing puppetclasses</h1>
+
+<table>
+ <tr>
+ <th>Name</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<% @puppetclasses.each do |puppetclass| %>
+ <tr>
+ <td><%= puppetclass.name %></td>
+ <td><%= link_to 'Show', puppetclass %></td>
+ <td><%= link_to 'Edit', edit_puppetclass_path(puppetclass) %></td>
+ <td><%= link_to 'Destroy', puppetclass, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New Puppetclass', new_puppetclass_path %>
5 app/views/puppetclasses/new.html.erb
@@ -0,0 +1,5 @@
+<h1>New puppetclass</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', puppetclasses_path %>
15 app/views/puppetclasses/show.html.erb
@@ -0,0 +1,15 @@
+<p id="notice"><%= notice %></p>
+
+<p>
+ <b>Name:</b>
+ <%= @puppetclass.name %>
+</p>
+
+<h2>Lookup keys</h2>
+<% @puppetclass.lookup_keys.each do |lookup_key| %>
+ <p><b><%= lookup_key.key %>:</b> <%= lookup_key.default_value %></p>
+<% end -%>
+
+
+<%= link_to 'Edit', edit_puppetclass_path(@puppetclass) %> |
+<%= link_to 'Back', puppetclasses_path %>
4 config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run TestShortcut::Application
62 config/application.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+if defined?(Bundler)
+ # If you precompile assets before deploying to production, use this line
+ Bundler.require(*Rails.groups(:assets => %w(development test)))
+ # If you want your assets lazily compiled in production, use this line
+ # Bundler.require(:default, :assets, Rails.env)
+end
+
+module TestShortcut
+ class Application < Rails::Application
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Custom directories with classes and modules you want to be autoloadable.
+ # config.autoload_paths += %W(#{config.root}/extras)
+
+ # Only load the plugins named here, in the order given (default is alphabetical).
+ # :all can be used as a placeholder for all plugins not explicitly named.
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+ # Activate observers that should always be running.
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+ # config.time_zone = 'Central Time (US & Canada)'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+ # config.i18n.default_locale = :de
+
+ # Configure the default encoding used in templates for Ruby 1.9.
+ config.encoding = "utf-8"
+
+ # Configure sensitive parameters which will be filtered from the log file.
+ config.filter_parameters += [:password]
+
+ # Enable escaping HTML in JSON.
+ config.active_support.escape_html_entities_in_json = true
+
+ # Use SQL instead of Active Record's schema dumper when creating the database.
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
+ # like if you have constraints or database-specific column types
+ # config.active_record.schema_format = :sql
+
+ # Enforce whitelist mode for mass assignment.
+ # This will create an empty whitelist of attributes available for mass-assignment for all models
+ # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
+ # parameters by using an attr_accessible or attr_protected declaration.
+ config.active_record.whitelist_attributes = true
+
+ # Enable the asset pipeline
+ config.assets.enabled = true
+
+ # Version of your assets, change this if you want to expire all your assets
+ config.assets.version = '1.0'
+ end
+end
6 config/boot.rb
@@ -0,0 +1,6 @@
+require 'rubygems'
+
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
25 config/database.yml
@@ -0,0 +1,25 @@
+# SQLite version 3.x
+# gem install sqlite3
+#
+# Ensure the SQLite 3 gem is defined in your Gemfile
+# gem 'sqlite3'
+development:
+ adapter: sqlite3
+ database: db/development.sqlite3
+ pool: 5
+ timeout: 5000
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: sqlite3
+ database: db/test.sqlite3
+ pool: 5
+ timeout: 5000
+
+production:
+ adapter: sqlite3
+ database: db/production.sqlite3
+ pool: 5
+ timeout: 5000
5 config/environment.rb
@@ -0,0 +1,5 @@
+# Load the rails application
+require File.expand_path('../application', __FILE__)
+
+# Initialize the rails application
+TestShortcut::Application.initialize!
37 config/environments/development.rb
@@ -0,0 +1,37 @@
+TestShortcut::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Log error messages when you accidentally call methods on nil.
+ config.whiny_nils = true
+
+ # Show full error reports and disable caching
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger
+ config.active_support.deprecation = :log
+
+ # Only use best-standards-support built into browsers
+ config.action_dispatch.best_standards_support = :builtin
+
+ # Raise exception on mass assignment protection for Active Record models
+ config.active_record.mass_assignment_sanitizer = :strict
+
+ # Log the query plan for queries taking more than this (works
+ # with SQLite, MySQL, and PostgreSQL)
+ config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+ # Do not compress assets
+ config.assets.compress = false
+
+ # Expands the lines which load the assets
+ config.assets.debug = true
+end
67 config/environments/production.rb
@@ -0,0 +1,67 @@
+TestShortcut::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # Code is not reloaded between requests
+ config.cache_classes = true
+
+ # Full error reports are disabled and caching is turned on
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Disable Rails's static asset server (Apache or nginx will already do this)
+ config.serve_static_assets = false
+
+ # Compress JavaScripts and CSS
+ config.assets.compress = true
+
+ # Don't fallback to assets pipeline if a precompiled asset is missed
+ config.assets.compile = false
+
+ # Generate digests for assets URLs
+ config.assets.digest = true
+
+ # Defaults to nil and saved in location specified by config.assets.prefix
+ # config.assets.manifest = YOUR_PATH
+
+ # Specifies the header that your server uses for sending files
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # See everything in the log (default is :info)
+ # config.log_level = :debug
+
+ # Prepend all log lines with the following tags
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server
+ # config.action_controller.asset_host = "http://assets.example.com"
+
+ # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
+ # config.assets.precompile += %w( search.js )
+
+ # Disable delivery errors, bad email addresses will be ignored
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable threaded mode
+ # config.threadsafe!
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation can not be found)
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners
+ config.active_support.deprecation = :notify
+
+ # Log the query plan for queries taking more than this (works
+ # with SQLite, MySQL, and PostgreSQL)
+ # config.active_record.auto_explain_threshold_in_seconds = 0.5
+end
37 config/environments/test.rb
@@ -0,0 +1,37 @@
+TestShortcut::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Configure static asset server for tests with Cache-Control for performance
+ config.serve_static_assets = true
+ config.static_cache_control = "public, max-age=3600"
+
+ # Log error messages when you accidentally call methods on nil
+ config.whiny_nils = true
+
+ # Show full error reports and disable caching
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment
+ config.action_controller.allow_forgery_protection = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Raise exception on mass assignment protection for Active Record models
+ config.active_record.mass_assignment_sanitizer = :strict
+
+ # Print deprecation notices to the stderr
+ config.active_support.deprecation = :stderr
+end
7 config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
15 config/initializers/inflections.rb
@@ -0,0 +1,15 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# ActiveSupport::Inflector.inflections do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+#
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections do |inflect|
+# inflect.acronym 'RESTful'
+# end
5 config/initializers/mime_types.rb
@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
+# Mime::Type.register_alias "text/html", :iphone
7 config/initializers/secret_token.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+TestShortcut::Application.config.secret_token = '1294b7d7d0b13a692bec8ae47c843cb53e7924e47677147ecb1ee95029ef98553ed836cd80c419a2dc799a1698314c2def2b654c9ca17cbd586ad327ccce354c'
8 config/initializers/session_store.rb
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+TestShortcut::Application.config.session_store :cookie_store, :key => '_test-shortcut_session'
+
+# Use the database for sessions instead of the cookie-based default,
+# which shouldn't be used to store highly confidential information
+# (create the session table with "rails generate session_migration")
+# TestShortcut::Application.config.session_store :active_record_store
14 config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+#
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters :format => [:json]
+end
+
+# Disable root element in JSON by default.
+ActiveSupport.on_load(:active_record) do
+ self.include_root_in_json = false
+end
5 config/locales/en.yml
@@ -0,0 +1,5 @@
+# Sample localization file for English. Add more files in this directory for other locales.
+# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+
+en:
+ hello: "Hello world"
70 config/routes.rb
@@ -0,0 +1,70 @@
+TestShortcut::Application.routes.draw do
+ resources :host_classes
+
+ resources :lookup_values
+
+ resources :lookup_keys
+
+ resources :puppetclasses
+
+ resources :hosts
+
+ root :to => "home", :action => "index"
+
+ # The priority is based upon order of creation:
+ # first created -> highest priority.
+
+ # Sample of regular route:
+ # match 'products/:id' => 'catalog#view'
+ # Keep in mind you can assign values other than :controller and :action
+
+ # Sample of named route:
+ # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
+ # This route can be invoked with purchase_url(:id => product.id)
+
+ # Sample resource route (maps HTTP verbs to controller actions automatically):
+ # resources :products
+
+ # Sample resource route with options:
+ # resources :products do
+ # member do
+ # get 'short'
+ # post 'toggle'
+ # end
+ #
+ # collection do
+ # get 'sold'
+ # end
+ # end
+
+ # Sample resource route with sub-resources:
+ # resources :products do
+ # resources :comments, :sales
+ # resource :seller
+ # end
+
+ # Sample resource route with more complex sub-resources
+ # resources :products do
+ # resources :comments
+ # resources :sales do
+ # get 'recent', :on => :collection
+ # end
+ # end
+
+ # Sample resource route within a namespace:
+ # namespace :admin do
+ # # Directs /admin/products/* to Admin::ProductsController
+ # # (app/controllers/admin/products_controller.rb)
+ # resources :products
+ # end
+
+ # You can have the root of your site routed with "root"
+ # just remember to delete public/index.html.
+ # root :to => 'welcome#index'
+
+ # See how all your routes lay out with "rake routes"
+
+ # This is a legacy wild controller route that's not recommended for RESTful applications.
+ # Note: This route will make all actions in every controller accessible via GET requests.
+ # match ':controller(/:action(/:id))(.:format)'
+end
9 db/migrate/20120806143308_create_hosts.rb
@@ -0,0 +1,9 @@
+class CreateHosts < ActiveRecord::Migration
+ def change
+ create_table :hosts do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
9 db/migrate/20120806143329_create_puppetclasses.rb
@@ -0,0 +1,9 @@
+class CreatePuppetclasses < ActiveRecord::Migration
+ def change
+ create_table :puppetclasses do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
12 db/migrate/20120806143338_create_lookup_keys.rb
@@ -0,0 +1,12 @@
+class CreateLookupKeys < ActiveRecord::Migration
+ def change
+ create_table :lookup_keys do |t|
+ t.string :key
+ t.string :default_value
+ t.references :puppetclass
+
+ t.timestamps
+ end
+ add_index :lookup_keys, :puppetclass_id
+ end
+end
12 db/migrate/20120806143343_create_lookup_values.rb
@@ -0,0 +1,12 @@
+class CreateLookupValues < ActiveRecord::Migration
+ def change
+ create_table :lookup_values do |t|
+ t.string :value
+ t.string :matcher
+ t.references :lookup_key
+
+ t.timestamps
+ end
+ add_index :lookup_values, :lookup_key_id
+ end
+end
10 db/migrate/20120806143359_create_host_classes.rb
@@ -0,0 +1,10 @@
+class CreateHostClasses < ActiveRecord::Migration
+ def change
+ create_table :host_classes do |t|
+ t.references :host
+ t.references :puppetclass
+ end
+ add_index :host_classes, :host_id
+ add_index :host_classes, :puppetclass_id
+ end
+end
56 db/schema.rb
@@ -0,0 +1,56 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended to check this file into your version control system.
+
+ActiveRecord::Schema.define(:version => 20120806143359) do
+
+ create_table "host_classes", :force => true do |t|
+ t.integer "host_id"
+ t.integer "puppetclass_id"
+ end
+
+ add_index "host_classes", ["host_id"], :name => "index_host_classes_on_host_id"
+ add_index "host_classes", ["puppetclass_id"], :name => "index_host_classes_on_puppetclass_id"
+
+ create_table "hosts", :force => true do |t|
+ t.string "name"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ create_table "lookup_keys", :force => true do |t|
+ t.string "key"
+ t.string "default_value"
+ t.integer "puppetclass_id"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ add_index "lookup_keys", ["puppetclass_id"], :name => "index_lookup_keys_on_puppetclass_id"
+
+ create_table "lookup_values", :force => true do |t|
+ t.string "key"
+ t.string "value"
+ t.string "matcher"
+ t.integer "lookup_key_id"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ add_index "lookup_values", ["lookup_key_id"], :name => "index_lookup_values_on_lookup_key_id"
+
+ create_table "puppetclasses", :force => true do |t|
+ t.string "name"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+end
7 db/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
+# Mayor.create(:name => 'Emanuel', :city => cities.first)
0  lib/assets/.gitkeep
No changes.
0