pinkman 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +41 -0
  8. data/Rakefile +28 -0
  9. data/app/assets/javascripts/pinkman.js +10 -0
  10. data/app/assets/javascripts/pinkman_base/ajax.coffee +90 -0
  11. data/app/assets/javascripts/pinkman_base/collection.coffee +387 -0
  12. data/app/assets/javascripts/pinkman_base/common.coffee +56 -0
  13. data/app/assets/javascripts/pinkman_base/controller.coffee +164 -0
  14. data/app/assets/javascripts/pinkman_base/glue.coffee +15 -0
  15. data/app/assets/javascripts/pinkman_base/handlebars.js +4608 -0
  16. data/app/assets/javascripts/pinkman_base/hogan.js +576 -0
  17. data/app/assets/javascripts/pinkman_base/markup.js +483 -0
  18. data/app/assets/javascripts/pinkman_base/mixins.coffee +37 -0
  19. data/app/assets/javascripts/pinkman_base/object.js.coffee.erb +195 -0
  20. data/app/assets/javascripts/pinkman_base/pinkman.coffee +131 -0
  21. data/app/assets/javascripts/pinkman_base/render.coffee.erb +80 -0
  22. data/app/assets/javascripts/pinkman_base/tools.coffee +4 -0
  23. data/app/helpers/pinkman_helper.rb +48 -0
  24. data/bin/console +14 -0
  25. data/bin/setup +8 -0
  26. data/lib/generators/pinkman/USAGE +16 -0
  27. data/lib/generators/pinkman/api_generator.rb +60 -0
  28. data/lib/generators/pinkman/install_generator.rb +25 -0
  29. data/lib/generators/pinkman/model_generator.rb +41 -0
  30. data/lib/generators/pinkman/resource_generator.rb +15 -0
  31. data/lib/generators/pinkman/serializer_generator.rb +33 -0
  32. data/lib/generators/pinkman/templates/api.rb.erb +87 -0
  33. data/lib/generators/pinkman/templates/api_controller.rb +2 -0
  34. data/lib/generators/pinkman/templates/collection.js.erb +5 -0
  35. data/lib/generators/pinkman/templates/object.js.erb +3 -0
  36. data/lib/generators/pinkman/templates/serializer.rb.erb +15 -0
  37. data/lib/pinkman.rb +57 -0
  38. data/lib/pinkman/serializer.rb +6 -0
  39. data/lib/pinkman/serializer/base.rb +42 -0
  40. data/lib/pinkman/serializer/scope.rb +48 -0
  41. data/lib/pinkman/version.rb +3 -0
  42. data/pinkman.gemspec +46 -0
  43. data/public/javascripts/pinkman.min.js +1 -0
  44. data/public/jquery.pinkman.min.js +0 -0
  45. data/public/pinkman.min.js +29 -0
  46. metadata +242 -0
@@ -0,0 +1,48 @@
1
+ module PinkmanHelper
2
+
3
+ def input hash, *args, &block
4
+ name = hash[:name]
5
+ tag('input',hash.merge(data: {pinkey: pinkey, action: name}, value: write(name)), *args, &block)
6
+ end
7
+
8
+ def template path
9
+ render partial: "pinkman/#{path}"
10
+ end
11
+
12
+ def wrap_in tag, &block
13
+ raw "\n{{# #{tag} }}\n \t #{capture(&block)} \n{{/ #{tag} }}\n" if block_given?
14
+ end
15
+
16
+ def collection &block
17
+ wrap_in('collection',&block)
18
+ end
19
+
20
+ def write string
21
+ raw("{{ #{string} }}")
22
+ end
23
+
24
+ def w *args
25
+ write(*args)
26
+ end
27
+
28
+ def pinkey
29
+ w('pinkey')
30
+ end
31
+
32
+ def p_if condition, &block
33
+ raw "\n{{#if #{condition}}}\n \t #{capture(&block)} \n{{/if}}\n" if block_given?
34
+ end
35
+
36
+ def p_then &block
37
+ capture(&block)
38
+ end
39
+
40
+ def p_else &block
41
+ raw "\n{{else}}\n \t #{capture(&block)}" if block_given?
42
+ end
43
+
44
+ def p_unless
45
+ end
46
+
47
+
48
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "pinkman"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,16 @@
1
+ Description:
2
+ pinkman generators
3
+
4
+ Api:
5
+ rails generate pinkman:api name
6
+
7
+ This will create an api controller and its routes.
8
+ app/controllers/api/pluralized_name_controller.rb
9
+
10
+ Model
11
+ rails generate pinkman:model name
12
+ Pinkman model: app/assets/javascripts/pinkman/models/name/name.js
13
+ Pinkman collection: app/assets/javascripts/pinkman/models/name/pluralized_name.js
14
+
15
+ Install
16
+ This creates common pinkman directories
@@ -0,0 +1,60 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Pinkman
4
+ class ApiGenerator < ::Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ argument :class_name, type: :string, default: "nameHere"
8
+
9
+ def generate_api_file
10
+ template "api.rb.erb", "app/controllers/api/#{controller_file_name}"
11
+ end
12
+
13
+ def insert_a_resource_in_routes
14
+ inject_into_file 'config/routes.rb', after: "namespace :api do" do
15
+ %/
16
+ resources :#{api_name} do
17
+ collection do
18
+ get 'search(\/:query)', action: 'search'
19
+ end
20
+ end
21
+ /
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def api_name
28
+ class_name.pluralize.underscore
29
+ end
30
+
31
+ def collection_name
32
+ api_name
33
+ end
34
+
35
+ def instance_name
36
+ class_name.underscore
37
+ end
38
+
39
+ def controller_name
40
+ api_name.camelize + "Controller"
41
+ end
42
+
43
+ def serializer_name
44
+ active_record_model_name + "Serializer"
45
+ end
46
+
47
+ def controller_file_name
48
+ api_name.underscore + "_controller.rb"
49
+ end
50
+
51
+ def params_method_name
52
+ instance_name + "_params"
53
+ end
54
+
55
+ def active_record_model_name
56
+ class_name.camelize
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,25 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Pinkman
4
+ class InstallGenerator < ::Rails::Generators::Base
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def create_directories
9
+ FileUtils.mkdir_p Rails.root.join('app','views','pinkman')
10
+ FileUtils.mkdir_p Rails.root.join('app','assets','javascripts','pinkman','models')
11
+ FileUtils.mkdir_p Rails.root.join('app','serializers')
12
+ FileUtils.mkdir_p Rails.root.join('app','controllers','api')
13
+ end
14
+
15
+ def create_api_routes
16
+ inject_into_file 'config/routes.rb', after: ".routes.draw do" do
17
+ ["\n \n \t" 'namespace :api do',"\tend"].join("\n")
18
+ end
19
+ end
20
+
21
+ def create_api_controller_file
22
+ copy_file "api_controller.rb", Rails.root.join('app','controllers','api_controller.rb')
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,41 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Pinkman
4
+ class ModelGenerator < ::Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ argument :class_name, type: :string, default: "nameHere"
8
+
9
+ def generate_files
10
+ template "object.js.erb", "app/assets/javascripts/pinkman/models/#{directory_name}/#{object_file_name}"
11
+ template "collection.js.erb", "app/assets/javascripts/pinkman/models/#{directory_name}/#{collection_file_name}"
12
+ end
13
+
14
+ private
15
+
16
+ def directory_name
17
+ class_name.pluralize.underscore
18
+ end
19
+
20
+ def object_class_name
21
+ class_name.camelize
22
+ end
23
+
24
+ def object_file_name
25
+ class_name.underscore + ".coffee"
26
+ end
27
+
28
+ def collection_class_name
29
+ class_name.pluralize.camelize
30
+ end
31
+
32
+ def collection_file_name
33
+ class_name.pluralize.underscore + ".coffee"
34
+ end
35
+
36
+ def guess_api_url
37
+ "api/#{class_name.pluralize.underscore}"
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Pinkman
4
+ class ResourceGenerator < ::Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ argument :class_name, type: :string, default: "nameHere"
8
+
9
+ def exec
10
+ generate "pinkman:api #{class_name}"
11
+ generate "pinkman:model #{class_name}"
12
+ generate "pinkman:serializer #{class_name}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Pinkman
4
+ class SerializerGenerator < ::Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ argument :class_name, type: :string, default: "nameHere"
8
+
9
+ def generate_file
10
+ template "serializer.rb.erb", "app/serializers/#{serializer_file_name}"
11
+ end
12
+
13
+ private
14
+
15
+ def api_name
16
+ class_name.pluralize.underscore
17
+ end
18
+
19
+ def serializer_name
20
+ active_record_model_name + "Serializer"
21
+ end
22
+
23
+ def serializer_file_name
24
+ active_record_model_name.underscore + "_serializer.rb"
25
+ end
26
+
27
+
28
+ def active_record_model_name
29
+ class_name.camelize
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,87 @@
1
+ class Api::<%= controller_name %> < ApiController
2
+
3
+ before_action :current_scope
4
+ before_action :permissions
5
+ before_action :set_objects
6
+
7
+ # To do: define the current scope the way you want
8
+ def current_scope
9
+ :all
10
+ end
11
+
12
+ # get api/<%= api_name %>
13
+ def index
14
+ <%= collection_name %> = <%= active_record_model_name %>.limit(params[:limit]).offset(params[:offset])
15
+ render json: <%= collection_name %>.json_for(current_scope)
16
+ end
17
+
18
+ # get api/<%= api_name %>/:id
19
+ def show
20
+ render json: @<%= instance_name %>.json_for(current_scope)
21
+ end
22
+
23
+ # get api/<%= api_name %>/search/:query
24
+ def search
25
+ if params[:query].present?
26
+ <%= collection_name %> = <%= active_record_model_name %>.search(params[:query]).limit(params[:limit]).offset(params[:offset])
27
+ render json: <%= collection_name %>.json_for(current_scope)
28
+ end
29
+ end
30
+
31
+ # post api/<%= api_name %>
32
+ def create
33
+ @<%= instance_name %>.assign_attributes <%= params_method_name %>
34
+ if @<%= instance_name %>.save
35
+ render json: @<%= instance_name %>.json_for(current_scope)
36
+ else
37
+ render json: {errors: @<%= instance_name %>.errors}
38
+ end
39
+ end
40
+
41
+ # put/patch api/<%= api_name %>/:id
42
+ def update
43
+ @<%= instance_name %>.assign_attributes <%= params_method_name %>
44
+ if @<%= instance_name %>.save
45
+ render json: @<%= instance_name %>.json_for(current_scope)
46
+ else
47
+ render json: {errors: @<%= instance_name %>.errors}
48
+ end
49
+ end
50
+
51
+
52
+ # delete api/<%= api_name %>/:id
53
+ def destroy
54
+ @<%= instance_name %>.destroy
55
+ render json: @<%= instance_name %>.json_for(current_scope)
56
+ end
57
+
58
+ protected
59
+
60
+ # --- begin permissions --- #
61
+
62
+ def permissions
63
+ unless <%= serializer_name %>.scope(current_scope).can_access? action_name
64
+ render json: {errors: 'You have no permission.'}
65
+ end
66
+ end
67
+
68
+ # --- end permissions --- #
69
+
70
+ def set_objects
71
+ if params[:id].present?
72
+ @<%= instance_name %> = <%= active_record_model_name %>.find params[:id]
73
+ else
74
+ @<%= instance_name %> = <%= active_record_model_name %>.new
75
+ end
76
+ end
77
+
78
+ def <%= params_method_name %>
79
+ if params['pink_obj']
80
+ params["pink_obj"].keep_if {|k,v| <%= serializer_name %>.scope(current_scope).can_write?(k)}
81
+ params["pink_obj"].permit!
82
+ else
83
+ {}
84
+ end
85
+ end
86
+
87
+ end
@@ -0,0 +1,2 @@
1
+ class ApiController < ApplicationController
2
+ end
@@ -0,0 +1,5 @@
1
+ class window.<%= collection_class_name %> extends Pinkman.collection
2
+ config:
3
+ api: '<%= guess_api_url %>' # you should confirm this
4
+ memberClass: ->
5
+ return (new <%= object_class_name %>)
@@ -0,0 +1,3 @@
1
+ class window.<%= object_class_name %> extends Pinkman.object
2
+ config:
3
+ api: '<%= guess_api_url %>' # you should confirm this
@@ -0,0 +1,15 @@
1
+ class <%= serializer_name %> < Pinkman::Serializer::Base
2
+
3
+ scope :all do |can|
4
+ can.read_attributes :all
5
+ can.write_attributes false
6
+ can.access_actions :index, :show
7
+ end
8
+
9
+ # scope :admin do |can|
10
+ # can.read_attributes :all
11
+ # can.write_attributes :all
12
+ # can.access_actions :all
13
+ # end
14
+
15
+ end
@@ -0,0 +1,57 @@
1
+ require 'pathname'
2
+ require 'rails'
3
+ require 'pinkman/serializer'
4
+ require 'pinkman/version'
5
+
6
+ module Pinkman
7
+
8
+ @@configuration = OpenStruct.new js_template_engine: 'handlebars'
9
+
10
+ def self.root
11
+ Pathname.new(File.dirname(__FILE__)).join('..')
12
+ end
13
+
14
+ def self.configuration
15
+ @@configuration
16
+ end
17
+
18
+ def self.setup
19
+ yield @@configuration
20
+ end
21
+
22
+ class Engine < ::Rails::Engine
23
+ config.after_initialize do
24
+ if defined? Slim
25
+ Slim::Engine.set_options attr_list_delims: {'(' => ')', '[' => ']'}
26
+ end
27
+
28
+ # Class method: serializer
29
+ ActiveRecord::Base.singleton_class.class_eval do
30
+ def serializer= value
31
+ @serializer = value
32
+ end
33
+
34
+ def serializer
35
+ @serializer || (begin eval(self.to_s + 'Serializer') rescue nil end)
36
+ end
37
+ end
38
+
39
+ # Active Record Relation: json_for
40
+ ActiveRecord::Relation.class_eval do
41
+ def json_for scope_name
42
+ a = ActiveModel::ArraySerializer.new(self, each_serializer: model.serializer, scope: scope_name)
43
+ a.to_json
44
+ end
45
+ end
46
+
47
+ # Instance method: json_for
48
+ ActiveRecord::Base.class_eval do
49
+ def json_for scope_name
50
+ s = self.class.serializer.new(self,scope: scope_name)
51
+ s.to_json
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ end