mongoid_scribe 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1589a51bcfcc3ef3e9fb957353e132e0f925450b
4
+ data.tar.gz: 01b1cbee0553e66b3828e69afcb0682d0ec5e8b6
5
+ SHA512:
6
+ metadata.gz: 37b5260974b8330a98a8db17206e8ff2f4d049b2d298037b8967fdfa8014b4b0f948c6ae01b50de7c751c32dce6b25f9a9ea91aaa57286f08ac2ef1c883ce95f
7
+ data.tar.gz: 25da9b12f09eb54592c08303577ae19be422a0d39c9cbfa6d5338be12c26f0904928470ff361595de8d9d3108bbd0a07080ba063ce5e34d191a6084fb3c8679c
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Nick DeSteffen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # Mongoid Scribe
2
+
3
+ Mongoid Scribe is a Rails Engine that provides a DSL for setting up simple admin interfaces to edit MongoDB documents. No configuration is required in order to get a basic form, however you can override any form you want to provide a more custom and usable interface.
4
+
5
+ ### Generator
6
+ To generate an initializer:
7
+
8
+ `bundle exec rails generate mongoid_scribe:install`
9
+
10
+ ### Configuration
11
+
12
+ ```ruby
13
+ Mongoid::Scribe.configure do
14
+
15
+ authenticate_with :admin_required
16
+
17
+ mount_at "/admin/documents"
18
+
19
+ resources exclude: [:user_roles]
20
+
21
+ form_configuration_for User do
22
+ field :first_name
23
+ field :last_name
24
+ field :favorite_color, values: User::COLORS
25
+ field :email, type: :email
26
+ field :home_city_id
27
+ field :visitied_city_ids: values: ->(user) { user.visited_cities }, label: :name, value: :id
28
+ end
29
+
30
+ index_configuration_for User do
31
+ column :first_name
32
+ column :last_Name
33
+ column :email
34
+ column :city, value: ->(user) { user.city.name }
35
+ end
36
+
37
+ end
38
+ ```
39
+
40
+ ### Usage
41
+ In your application visit: **/documents**
42
+
43
+ ### Options
44
+ `authenticate_with`: Provide a controller filter for granting / denying access
45
+ `form_configuration_for Class`: Allows you to specify the fields that you want on the form for the specified class
46
+ `index_configuration_for Class`: Allows you to specify the columns that are displayed on the index page
47
+ `mount_at`: Endpoint where editor is mounted (default is **/documents**)
48
+ `resources`: Include or exclude specific models from the editor interface
49
+
50
+ ### Notes
51
+ In development mode set `preload_models: true`
52
+
53
+ Styled using [Base](http://matthewhartman.github.io/base/docs/index.html)
@@ -0,0 +1,10 @@
1
+ module Mongoid
2
+ module Scribe
3
+ class ApplicationController < ::ApplicationController
4
+ include DocumentsHelper
5
+
6
+ before_filter Mongoid::Scribe.authentication_filter
7
+
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,50 @@
1
+ module Mongoid
2
+ module Scribe
3
+ class DocumentsController < ApplicationController
4
+
5
+ layout "mongoid/scribe/layouts/application"
6
+
7
+ before_filter :setup_klass, except: [:all]
8
+
9
+ def all
10
+ end
11
+
12
+ def index
13
+ @documents = @klass.all
14
+ end
15
+
16
+ def edit
17
+ @document = @klass.find(params[:id])
18
+ end
19
+
20
+ def update
21
+ @document = @klass.find(params[:id])
22
+ @document.update_attributes(document_params)
23
+
24
+ redirect_to document_path(params[:type], @document.id)
25
+ end
26
+
27
+ def show
28
+ @document = @klass.find(params[:id])
29
+ end
30
+
31
+ def destroy
32
+ @document = @klass.find(params[:id])
33
+ @document.destroy
34
+
35
+ redirect_to documents_path(params[:type])
36
+ end
37
+
38
+ private
39
+
40
+ def document_params
41
+ params.require(params[:type].to_sym).permit!
42
+ end
43
+
44
+ def setup_klass
45
+ @klass = params[:type].classify.constantize
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,19 @@
1
+ module Mongoid
2
+ module Scribe
3
+ module DocumentsHelper
4
+
5
+ def model_param(model)
6
+ model.to_s.underscore.downcase
7
+ end
8
+
9
+ def relation_label(relation)
10
+ if relation.respond_to?(:slug)
11
+ return relation.slug
12
+ else
13
+ return relation.id
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ <div class="section header">
2
+ <div class="container clear">
3
+ <h1 class='logo'>All Documents</h1>
4
+ </div>
5
+ </div>
6
+
7
+ <table>
8
+ <thead>
9
+ <tr>
10
+ <th>Type</th>
11
+ <th>Count</th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ <% Mongoid::Scribe.models.each do |model| %>
16
+ <tr>
17
+ <td><%= link_to model_param(model), documents_path(model_param(model)) %></td>
18
+ <td><%= model.count %></td>
19
+ </tr>
20
+ <% end %>
21
+ </tbody>
22
+ </table>
@@ -0,0 +1,22 @@
1
+ <% content_for :navigation do %>
2
+ <%= link_to "All Documents", document_listing_path, class: "button orange-button mobile-full" %>
3
+ <%= link_to @klass.to_s.pluralize, documents_path(model_param(@klass)), class: "button orange-button mobile-full" %>
4
+ <%= link_to @document.id, document_path(model_param(@klass), @document.id), class: "button orange-button mobile-full" %>
5
+ <% end %>
6
+
7
+ <div class="section header">
8
+ <div class="container clear">
9
+ <h1 class='logo'>Editing: <%= @document.id %></h1>
10
+ </div>
11
+ </div>
12
+
13
+ <%= form_for @document, url: update_document_path(model_param(@klass), @document) do |form| %>
14
+ <fieldset class='row'>
15
+ <% Mongoid::Scribe.fields_for(@klass).each_pair do |name, config| %>
16
+ <%= Mongoid::Scribe::Builders::Field.new(form, @klass, @document, name, config).field %>
17
+ <% end %>
18
+ <%= link_to("Cancel", document_path(model_param(@klass), @document), class: "button orange-button mobile-full") %>
19
+ <%= form.submit("Update #{@klass}", class: "button orange-button mobile-full") %>
20
+ </fieldset>
21
+ <% end %>
22
+
@@ -0,0 +1,34 @@
1
+ <% content_for :navigation do %>
2
+ <%= link_to "All Documents", document_listing_path, class: "button orange-button mobile-full" %>
3
+ <% end %>
4
+
5
+ <div class="section header">
6
+ <div class="container clear">
7
+ <h1 class='logo'><%= @klass.name.pluralize %></h1>
8
+ </div>
9
+ </div>
10
+
11
+ <table>
12
+ <thead>
13
+ <tr>
14
+ <% Mongoid::Scribe.index_for(@klass).each_pair do |header, config| %>
15
+ <th><%= header.to_s.humanize %></th>
16
+ <% end %>
17
+ <th>Actions</th>
18
+ </tr>
19
+ </thead>
20
+ <tbody>
21
+ <% @documents.each do |document| %>
22
+ <tr>
23
+ <% Mongoid::Scribe.index_for(@klass).each_pair do |header, config| %>
24
+ <td><%= Mongoid::Scribe::Builders::Table.new(document, header, config).cell %></td>
25
+ <% end %>
26
+ <td>
27
+ <%= link_to "View", document_path(model_param(@klass), document) %> |
28
+ <%= link_to "Edit", edit_document_path(model_param(@klass), document) %> |
29
+ <%= link_to "Destroy", destroy_document_path(model_param(@klass), document), method: :delete, data: {confirm: "Are you sure you want to destroy this record?"} %>
30
+ </td>
31
+ </tr>
32
+ <% end %>
33
+ </tbody>
34
+ </table>
@@ -0,0 +1,25 @@
1
+ <% content_for :navigation do %>
2
+ <%= link_to "All Documents", document_listing_path, class: "button orange-button mobile-full" %>
3
+ <%= link_to @klass.to_s.pluralize, documents_path(model_param(@klass)), class: "button orange-button mobile-full" %>
4
+ <% end %>
5
+
6
+ <div class="section header">
7
+ <div class="container clear">
8
+ <h1 class='logo'>Viewing: <%= @document.id %></h1>
9
+ </div>
10
+ </div>
11
+ <%= link_to "Edit", edit_document_path(model_param(@klass), @document.id), class: "button orange-button mobile-full" %>
12
+
13
+ <table>
14
+ <% @klass.fields.each do |attribute, meta| %>
15
+ <tr>
16
+ <td class='key'><%= attribute %></td>
17
+ <td><%= @document.send(attribute) %></td>
18
+ </tr>
19
+ <% end %>
20
+ </table>
21
+
22
+ <h3>Relations:</h3>
23
+ <% @klass.relations.each do |relation, meta| %>
24
+ <%= Mongoid::Scribe::Builders::Relation.new(@document, relation).listing %>
25
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <%= csrf_meta_tags %>
5
+ <%= stylesheet_link_tag "base/style", "base/doc", "base/custom" %>
6
+ </head>
7
+ <body>
8
+ <div class="container content-inner">
9
+ <%= yield :navigation %>
10
+ <%= yield %>
11
+ </div>
12
+ <%= javascript_include_tag "jquery", "jquery_ujs" %>
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,10 @@
1
+ Mongoid::Scribe::Engine.routes.draw do
2
+
3
+ get "/", to: "documents#all", as: :document_listing
4
+ get "/:type/:id/edit", to: "documents#edit", as: :edit_document
5
+ get "/:type/:id", to: "documents#show", as: :document
6
+ put "/:type/:id/edit", to: "documents#update", as: :update_document
7
+ get "/:type", to: "documents#index", as: :documents
8
+ delete "/:type/:id", to: "documents#destroy", as: :destroy_document
9
+
10
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators'
2
+
3
+ module MongoidScribe
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ desc "Generate Mongoid Scribe Initializer"
9
+
10
+ def generate_initializer
11
+ copy_file "config/initializers/mongoid_scribe.rb", "config/initializers/mongoid_scribe.rb"
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ Mongoid::Scribe.configure do
2
+
3
+ ## authenticate_with :admin_required
4
+
5
+ ## mount_at "/documents"
6
+
7
+ ## resources include: [:user]
8
+
9
+ ## form_configuration_for User do
10
+ ## field :first_name
11
+ ## field :last_name
12
+ ## field :email, type: :email
13
+ ## field :city_id, values: -> { City.all }, label: :name, value: :id
14
+ ## field :favorite_color, values: User::COLORS
15
+ ## end
16
+
17
+ ## index_configuration_for User do
18
+ ## column :first_name
19
+ ## column :last_name
20
+ ## column :email, value: ->(user) { "<a href='mailto:#{user.email}'>#{user.email}</a>".html_safe }
21
+ ## end
22
+
23
+ end
@@ -0,0 +1,85 @@
1
+ module Mongoid
2
+ module Scribe
3
+ module Builders
4
+ class Field
5
+ include ActionView::Helpers::FormHelper
6
+ include ActionView::Context
7
+
8
+ def initialize(form, klass, document, name, config)
9
+ @form = form
10
+ @klass = klass
11
+ @document = document
12
+ @name = name.to_s
13
+ @config = config
14
+ @label_method = @config.fetch(:label, :id)
15
+ @value_method = @config.fetch(:value, :id)
16
+ @type = @config.fetch(:type, nil)
17
+ end
18
+
19
+ def field
20
+ return nil if private_field?
21
+
22
+ if @klass.fields[@name].type == Boolean
23
+ form_field = @form.check_box(@name)
24
+ elsif @klass.fields[@name].type == Integer
25
+ form_field = @form.number_field(@name)
26
+ elsif @type == :textarea
27
+ form_field = @form.text_area(@name)
28
+ elsif (@name =~ /email/) || (@type == :email)
29
+ form_field = @form.email_field(@name)
30
+ elsif @klass.fields[@name].type == Array && values
31
+ form_field = checkbox_array
32
+ elsif values && values.is_a?(Mongoid::Criteria)
33
+ form_field = @form.collection_select(@name, values, @value_method, @label_method)
34
+ elsif values
35
+ form_field = @form.select(@name, values)
36
+ else
37
+ form_field = @form.text_field(@name)
38
+ end
39
+
40
+ return content_tag(:div, (label + form_field).html_safe, class: 'control-group')
41
+ end
42
+
43
+ private
44
+
45
+ def values
46
+ return @values if @values
47
+ @values = @config.fetch(:values, nil)
48
+ if @values.respond_to?(:call) && @values.arity == 1
49
+ @values = @values.call(@document)
50
+ elsif @values.respond_to?(:call)
51
+ @values = @values.call
52
+ elsif class_name = @document.relations.values.detect{ |data| data.key == @name }.try(:class_name)
53
+ @values = class_name.constantize.all
54
+ end
55
+ end
56
+
57
+ def label
58
+ @form.label(@name, class: "stacked")
59
+ end
60
+
61
+ def private_field?
62
+ return true if @name.start_with?("_")
63
+ return true if ["created_at", "updated_at"].include?(@name)
64
+ return false
65
+ end
66
+
67
+ def field_name(model)
68
+ model.to_s.underscore.downcase
69
+ end
70
+
71
+ def checkbox_array
72
+ values.each_with_index.map do |record, index|
73
+ dom_id = "#{field_name(record.class.name)}_#{index}"
74
+ checked = @document.send(@name).include?(record.send(@value_method))
75
+ label_tag(record.send(@label_method), nil, for: dom_id, class: "stacked") do
76
+ check_box_tag("#{field_name(@klass)}[#{@name}][]", record.send(@value_method), checked, id: dom_id) +
77
+ content_tag(:span, record.send(@label_method))
78
+ end
79
+ end.join("\n").html_safe
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,40 @@
1
+ module Mongoid
2
+ module Scribe
3
+ module Builders
4
+ class Relation
5
+ include ActionView::Helpers::TagHelper
6
+ include ActionView::Helpers::UrlHelper
7
+ include ActionView::Context
8
+
9
+ def initialize(document, relation)
10
+ @document = document
11
+ @relation = relation
12
+ end
13
+
14
+ def listing
15
+ output = content_tag(:h4, @relation)
16
+ Array(@document.send(@relation)).sort_by(&:created_at).each do |record|
17
+ link = link_to(relation_label(record), Mongoid::Scribe::Engine.routes.url_helpers.document_path(model_param(record.class.name), record.send(:id)))
18
+ output += content_tag(:p, link)
19
+ end
20
+ return output.html_safe
21
+ end
22
+
23
+ private
24
+
25
+ def relation_label(relation)
26
+ if relation.respond_to?(:slug)
27
+ return relation.slug
28
+ else
29
+ return relation.id
30
+ end
31
+ end
32
+
33
+ def model_param(model)
34
+ model.to_s.underscore.downcase
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ module Mongoid
2
+ module Scribe
3
+ module Builders
4
+ class Table
5
+
6
+ def initialize(document, header, config)
7
+ @document = document
8
+ @header = header
9
+ @config = config
10
+ end
11
+
12
+ def header
13
+ end
14
+
15
+ def cell
16
+ if @config[:value] && @config[:value].respond_to?(:call)
17
+ return @config[:value].call(@document)
18
+ else
19
+ return @document.send(@header)
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ module Mongoid
2
+ module Scribe
3
+
4
+ class FormConfiguration < Configuration
5
+ def field(name, options={})
6
+ @configuration[name] = options
7
+ end
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Mongoid
2
+ module Scribe
3
+
4
+ class IndexConfiguration < Configuration
5
+ def column(name, options={})
6
+ @configuration[name] = options
7
+ end
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module Mongoid
2
+ module Scribe
3
+ class Configuration
4
+
5
+ def initialize(document_class, configuration, &block)
6
+ @document_class = document_class
7
+ @configuration = configuration
8
+ end
9
+
10
+ def evaluate(&block)
11
+ @self_before_instance_eval = eval("self", block.binding)
12
+ instance_eval(&block)
13
+ end
14
+
15
+ def method_missing(method, *args, &block)
16
+ @self_before_instance_eval.send(method, *args, &block)
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Mongoid
2
+ module Scribe
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Mongoid::Scribe
5
+
6
+ initializer :assets, group: :all do |app|
7
+ app.config.assets.precompile += ["base/style.css", "base/doc.css", "base/custom.css", "jquery.js", "jquery_ujs.js"]
8
+ end
9
+
10
+ config.after_initialize do |app|
11
+ app.routes.prepend do
12
+ mount Mongoid::Scribe::Engine => Mongoid::Scribe.endpoint
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module Mongoid
2
+ module Scribe
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,82 @@
1
+ require "mongoid/scribe/version"
2
+ require "mongoid/scribe/engine"
3
+ require "mongoid/scribe/configuration"
4
+ require "mongoid/scribe/configuration/form_configuration"
5
+ require "mongoid/scribe/configuration/index_configuration"
6
+ require "mongoid/scribe/builders/field"
7
+ require "mongoid/scribe/builders/table"
8
+ require "mongoid/scribe/builders/relation"
9
+
10
+ module Mongoid
11
+ module Scribe
12
+ extend ActiveSupport::Autoload
13
+
14
+ mattr_accessor :form_configuration
15
+ @@form_configuration = {}
16
+
17
+ mattr_accessor :index_configuration
18
+ @@index_configuration = {}
19
+
20
+ mattr_accessor :authentication_filter
21
+ @@authentication_filter = nil
22
+
23
+ mattr_accessor :endpoint
24
+ @@endpoint = "/documents"
25
+
26
+ mattr_accessor :models
27
+ @@models = Mongoid.models
28
+
29
+ def self.configure(&block)
30
+ instance_eval(&block)
31
+ end
32
+
33
+ def self.fields_for(klass)
34
+ default_fields = {}
35
+ klass.fields.each_pair do |name, options|
36
+ default_fields[name.to_s] = {}
37
+ end
38
+ @@form_configuration.fetch(klass, default_fields)
39
+ end
40
+
41
+ def self.index_for(klass)
42
+ default_fields = {}
43
+ klass.fields.each_pair do |name, options|
44
+ next if name.start_with?("_")
45
+ default_fields[name.to_s] = {}
46
+ end
47
+ @@index_configuration.fetch(klass, default_fields)
48
+ end
49
+
50
+ def self.form_configuration_for(document_class, &block)
51
+ @@form_configuration[document_class] = {}
52
+ config = FormConfiguration.new(document_class, @@form_configuration[document_class])
53
+ config.evaluate(&block)
54
+ end
55
+
56
+ def self.index_configuration_for(document_class, &block)
57
+ @@index_configuration[document_class] = {}
58
+ config = IndexConfiguration.new(document_class, @@index_configuration[document_class])
59
+ config.evaluate(&block)
60
+ end
61
+
62
+ def self.authenticate_with(filter)
63
+ @@authentication_filter = filter
64
+ end
65
+
66
+ def self.mount_at(endpoint)
67
+ @@endpoint = endpoint
68
+ end
69
+
70
+ def self.resources(options={})
71
+ ::Rails::Mongoid.load_models(Rails.application)
72
+ if options[:include]
73
+ @@models = Mongoid.models.select{ |model| Array(options[:include]).include?(model.to_s.underscore.downcase.to_sym) }
74
+ elsif options[:exclude]
75
+ @@models = Mongoid.models.reject{ |model| Array(options[:exclude]).include?(model.to_s.underscore.downcase.to_sym) }
76
+ else
77
+ @@models = Mongoid.models
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1 @@
1
+ require 'mongoid/scribe'