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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +28 -0
- data/app/assets/javascripts/pinkman.js +10 -0
- data/app/assets/javascripts/pinkman_base/ajax.coffee +90 -0
- data/app/assets/javascripts/pinkman_base/collection.coffee +387 -0
- data/app/assets/javascripts/pinkman_base/common.coffee +56 -0
- data/app/assets/javascripts/pinkman_base/controller.coffee +164 -0
- data/app/assets/javascripts/pinkman_base/glue.coffee +15 -0
- data/app/assets/javascripts/pinkman_base/handlebars.js +4608 -0
- data/app/assets/javascripts/pinkman_base/hogan.js +576 -0
- data/app/assets/javascripts/pinkman_base/markup.js +483 -0
- data/app/assets/javascripts/pinkman_base/mixins.coffee +37 -0
- data/app/assets/javascripts/pinkman_base/object.js.coffee.erb +195 -0
- data/app/assets/javascripts/pinkman_base/pinkman.coffee +131 -0
- data/app/assets/javascripts/pinkman_base/render.coffee.erb +80 -0
- data/app/assets/javascripts/pinkman_base/tools.coffee +4 -0
- data/app/helpers/pinkman_helper.rb +48 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/generators/pinkman/USAGE +16 -0
- data/lib/generators/pinkman/api_generator.rb +60 -0
- data/lib/generators/pinkman/install_generator.rb +25 -0
- data/lib/generators/pinkman/model_generator.rb +41 -0
- data/lib/generators/pinkman/resource_generator.rb +15 -0
- data/lib/generators/pinkman/serializer_generator.rb +33 -0
- data/lib/generators/pinkman/templates/api.rb.erb +87 -0
- data/lib/generators/pinkman/templates/api_controller.rb +2 -0
- data/lib/generators/pinkman/templates/collection.js.erb +5 -0
- data/lib/generators/pinkman/templates/object.js.erb +3 -0
- data/lib/generators/pinkman/templates/serializer.rb.erb +15 -0
- data/lib/pinkman.rb +57 -0
- data/lib/pinkman/serializer.rb +6 -0
- data/lib/pinkman/serializer/base.rb +42 -0
- data/lib/pinkman/serializer/scope.rb +48 -0
- data/lib/pinkman/version.rb +3 -0
- data/pinkman.gemspec +46 -0
- data/public/javascripts/pinkman.min.js +1 -0
- data/public/jquery.pinkman.min.js +0 -0
- data/public/pinkman.min.js +29 -0
- 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
|
data/bin/console
ADDED
@@ -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
|
data/bin/setup
ADDED
@@ -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,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
|
data/lib/pinkman.rb
ADDED
@@ -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
|