kms_models 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +37 -0
  4. data/app/assets/javascripts/kms_models/application/controllers/entries_controller.coffee +91 -0
  5. data/app/assets/javascripts/kms_models/application/controllers/fields_controller.coffee.erb +42 -0
  6. data/app/assets/javascripts/kms_models/application/controllers/models_controller.coffee +42 -0
  7. data/app/assets/javascripts/kms_models/application/routes.coffee.erb +67 -0
  8. data/app/assets/javascripts/kms_models/application.js +15 -0
  9. data/app/assets/javascripts/templates/entries/edit.html.slim +9 -0
  10. data/app/assets/javascripts/templates/entries/form.html.slim +3 -0
  11. data/app/assets/javascripts/templates/entries/index.html.slim +21 -0
  12. data/app/assets/javascripts/templates/entries/new.html.slim +5 -0
  13. data/app/assets/javascripts/templates/fields/belongs_to_field.html.slim +7 -0
  14. data/app/assets/javascripts/templates/fields/checkbox_field.html.slim +4 -0
  15. data/app/assets/javascripts/templates/fields/file_field.html.slim +8 -0
  16. data/app/assets/javascripts/templates/fields/has_many_field.html.slim +7 -0
  17. data/app/assets/javascripts/templates/fields/string_field.html.slim +3 -0
  18. data/app/assets/javascripts/templates/fields/text_field.html.slim +3 -0
  19. data/app/assets/javascripts/templates/help/models_variables.html.slim +10 -0
  20. data/app/assets/javascripts/templates/models/edit.html.slim +6 -0
  21. data/app/assets/javascripts/templates/models/fields.html.slim +36 -0
  22. data/app/assets/javascripts/templates/models/form.html.slim +10 -0
  23. data/app/assets/javascripts/templates/models/index.html.slim +20 -0
  24. data/app/assets/javascripts/templates/models/new.html.slim +6 -0
  25. data/app/assets/stylesheets/kms_models/application.css +15 -0
  26. data/app/controllers/kms/models/entries_controller.rb +49 -0
  27. data/app/controllers/kms/models/models_controller.rb +51 -0
  28. data/app/helpers/kms_models/application_helper.rb +4 -0
  29. data/app/models/kms/belongs_to_field.rb +9 -0
  30. data/app/models/kms/checkbox_field.rb +4 -0
  31. data/app/models/kms/entry.rb +64 -0
  32. data/app/models/kms/field.rb +12 -0
  33. data/app/models/kms/file_field.rb +10 -0
  34. data/app/models/kms/has_many_field.rb +9 -0
  35. data/app/models/kms/model.rb +22 -0
  36. data/app/models/kms/models_wrapper.rb +14 -0
  37. data/app/models/kms/page_decorator.rb +18 -0
  38. data/app/models/kms/string_field.rb +4 -0
  39. data/app/models/kms/text_field.rb +4 -0
  40. data/app/serializers/kms/entry_serializer.rb +23 -0
  41. data/app/serializers/kms/simple_model_serializer.rb +5 -0
  42. data/app/uploaders/entry_file_uploader.rb +51 -0
  43. data/app/views/layouts/kms_models/application.html.erb +14 -0
  44. data/config/initializers/ability.rb +7 -0
  45. data/config/initializers/externals.rb +1 -0
  46. data/config/initializers/help.rb +1 -0
  47. data/config/initializers/resources.rb +6 -0
  48. data/config/locales/en.yml +52 -0
  49. data/config/locales/ru.yml +52 -0
  50. data/config/routes.rb +11 -0
  51. data/db/migrate/20150409124420_create_kms_models.rb +10 -0
  52. data/db/migrate/20150409125056_create_kms_fields.rb +13 -0
  53. data/db/migrate/20150413143711_create_kms_entries.rb +10 -0
  54. data/db/migrate/20150820080436_add_label_field_to_kms_models.rb +5 -0
  55. data/db/migrate/20150820132142_add_slug_to_kms_entries.rb +6 -0
  56. data/db/migrate/20150821201250_fix_models_column_name.rb +5 -0
  57. data/db/migrate/20150901115303_add_class_name_to_kms_fields.rb +5 -0
  58. data/db/migrate/20150910081440_add_position_to_kms_entries.rb +5 -0
  59. data/lib/drops/kms/entry_drop.rb +67 -0
  60. data/lib/drops/kms/models_wrapper_drop.rb +12 -0
  61. data/lib/generators/kms_models/install/install_generator.rb +17 -0
  62. data/lib/kms/models/engine.rb +15 -0
  63. data/lib/kms/models/version.rb +5 -0
  64. data/lib/kms_models.rb +6 -0
  65. data/lib/tasks/kms_models_tasks.rake +4 -0
  66. data/test/dummy/README.rdoc +28 -0
  67. data/test/dummy/Rakefile +6 -0
  68. data/test/dummy/app/assets/javascripts/application.js +13 -0
  69. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  70. data/test/dummy/app/controllers/application_controller.rb +5 -0
  71. data/test/dummy/app/helpers/application_helper.rb +2 -0
  72. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  73. data/test/dummy/bin/bundle +3 -0
  74. data/test/dummy/bin/rails +4 -0
  75. data/test/dummy/bin/rake +4 -0
  76. data/test/dummy/bin/setup +29 -0
  77. data/test/dummy/config/application.rb +26 -0
  78. data/test/dummy/config/boot.rb +5 -0
  79. data/test/dummy/config/database.yml +25 -0
  80. data/test/dummy/config/environment.rb +5 -0
  81. data/test/dummy/config/environments/development.rb +41 -0
  82. data/test/dummy/config/environments/production.rb +79 -0
  83. data/test/dummy/config/environments/test.rb +42 -0
  84. data/test/dummy/config/initializers/assets.rb +11 -0
  85. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  86. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  87. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  88. data/test/dummy/config/initializers/inflections.rb +16 -0
  89. data/test/dummy/config/initializers/mime_types.rb +4 -0
  90. data/test/dummy/config/initializers/session_store.rb +3 -0
  91. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  92. data/test/dummy/config/locales/en.yml +23 -0
  93. data/test/dummy/config/routes.rb +4 -0
  94. data/test/dummy/config/secrets.yml +22 -0
  95. data/test/dummy/config.ru +4 -0
  96. data/test/dummy/public/404.html +67 -0
  97. data/test/dummy/public/422.html +67 -0
  98. data/test/dummy/public/500.html +66 -0
  99. data/test/dummy/public/favicon.ico +0 -0
  100. data/test/integration/navigation_test.rb +10 -0
  101. data/test/kms_models_test.rb +7 -0
  102. data/test/test_helper.rb +19 -0
  103. metadata +238 -0
@@ -0,0 +1,64 @@
1
+ module Kms
2
+ class Entry < ActiveRecord::Base
3
+ include Liquor::Dropable
4
+ extend ::FriendlyId
5
+ include CompileTemplates
6
+
7
+ friendly_id :slug_candidates, use: :slugged
8
+ belongs_to :model
9
+ after_save :store_files, if: :cache_names_present?
10
+
11
+ validates :slug, uniqueness: { scope: :model_id }
12
+
13
+ attr_reader :cache_names
14
+
15
+ def slug_candidates
16
+ [values[model.label_field]]
17
+ end
18
+
19
+ def permalink
20
+ templatable_page = Kms::Page.where(templatable_type: model.name).first
21
+ return nil unless templatable_page
22
+ Pathname.new(templatable_page.parent.fullpath).join(slug.to_s).to_s
23
+ end
24
+
25
+ def values
26
+ read_attribute(:values) || {}
27
+ end
28
+
29
+ def values=(new_values)
30
+ files_params = new_values.select { |_, v| v.is_a?(ActionDispatch::Http::UploadedFile) || v.is_a?(File) }
31
+ @cache_names ||= {}
32
+ files_params.each do |k, v|
33
+ uploader = EntryFileUploader.new(OpenStruct.new(model: self, field_name: k))
34
+ uploader.cache!(v)
35
+ @cache_names[k] = uploader.cache_name
36
+ files_params[k] = v.original_filename
37
+ end
38
+ super values.merge new_values.merge(files_params)
39
+ end
40
+
41
+ def method_missing(name, *args, &block)
42
+ model.fields.where(liquor_name: name.to_s).exists? ? values[name.to_s] : super
43
+ end
44
+
45
+ def respond_to_missing?(method_name, include_private = false)
46
+ model.fields.where(liquor_name: method_name.to_s).exists? || super
47
+ end
48
+
49
+ protected
50
+
51
+ def cache_names_present?
52
+ cache_names.present?
53
+ end
54
+
55
+ def store_files
56
+ values.each do |k, v|
57
+ next unless cache_names.keys.include? k
58
+ uploader = EntryFileUploader.new(OpenStruct.new(model: self, field_name: k))
59
+ uploader.retrieve_from_cache!(cache_names[k])
60
+ uploader.store!
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ module Kms
2
+ class Field < ActiveRecord::Base
3
+ belongs_to :model
4
+ scope :file_fields, -> { where(type: Kms::FileField.name) }
5
+ scope :checkbox_fields, -> { where(type: Kms::CheckboxField.name) }
6
+
7
+ def get_value(entry)
8
+ # OVERRIDE in subclasses if needed
9
+ entry.values[liquor_name]
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module Kms
2
+ class FileField < Field
3
+ def get_value(entry)
4
+ value = entry.values[liquor_name]
5
+ uploader = EntryFileUploader.new(OpenStruct.new(model: entry, field_name: liquor_name))
6
+ uploader.retrieve_from_store! value
7
+ uploader.url
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Kms
2
+ class HasManyField < Field
3
+ def get_value(entry)
4
+ entry_ids = entry.values[liquor_name]
5
+ association_records = Kms::Entry.where(id: entry_ids)
6
+ Liquor::DropDelegation.wrap_scope(association_records)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ module Kms
2
+ class Model < ActiveRecord::Base
3
+ has_many :fields, class_name: 'Kms::Field', dependent: :destroy
4
+ has_many :entries, class_name: 'Kms::Entry', dependent: :destroy
5
+ accepts_nested_attributes_for :fields, allow_destroy: true
6
+
7
+ def name
8
+ id.to_s
9
+ end
10
+
11
+ # Hacking hack
12
+ def model_name
13
+ value = kms_model_name
14
+ value.instance_eval do
15
+ def human(options={})
16
+ self
17
+ end
18
+ end
19
+ value
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Kms
2
+ class ModelsWrapper
3
+ include Liquor::Dropable
4
+
5
+ def method_missing(name, *args, &block)
6
+ model = Kms::Model.find_by(collection_name: name.to_s)
7
+ model ? model.entries.order('position') : super
8
+ end
9
+
10
+ def respond_to_missing?(method_name, include_private = false)
11
+ Kms::Model.where(collection_name: method_name.to_s).exists? || super
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ Kms::Page.class_eval do
2
+ # fetch item by slug
3
+ def fetch_item!(slug)
4
+ return nil unless templatable?
5
+ templatable_type.constantize.find_by_slug!(slug)
6
+ rescue NameError
7
+ Kms::Entry.find_by_slug!(slug)
8
+ end
9
+
10
+ # fetch items for templatable page
11
+ def fetch_items
12
+ templatable_type.constantize.all
13
+ rescue NameError
14
+ # in templatable_type we store id of Kms::Model object in this case
15
+ model = Kms::Model.find(templatable_type.to_i)
16
+ model.entries
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module Kms
2
+ class StringField < Field
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Kms
2
+ class TextField < Field
3
+ end
4
+ end
@@ -0,0 +1,23 @@
1
+ module Kms
2
+ class EntrySerializer < ActiveModel::Serializer
3
+ attributes :id, :values, :position, :slug
4
+
5
+ has_one :model, serializer: Kms::SimpleModelSerializer
6
+
7
+ # OPTIMIZE
8
+ def values
9
+ values_with_urls = object.values.dup
10
+ # prepare file fields
11
+ object.model.fields.file_fields.each do |file_field|
12
+ uploader = EntryFileUploader.new(OpenStruct.new(model: object, field_name: file_field.liquor_name))
13
+ uploader.retrieve_from_store! values_with_urls[file_field.liquor_name]
14
+ values_with_urls[file_field.liquor_name] = { url: uploader.url }
15
+ end
16
+ # prepare checkbox fields - cause PostgreSQL json stored as strings
17
+ object.model.fields.checkbox_fields.each do |checkbox_field|
18
+ values_with_urls[checkbox_field.liquor_name] = values_with_urls[checkbox_field.liquor_name] == 'true'
19
+ end
20
+ values_with_urls
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ module Kms
2
+ class SimpleModelSerializer < ActiveModel::Serializer
3
+ attributes :id, :label_field
4
+ end
5
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ class EntryFileUploader < CarrierWave::Uploader::Base
4
+
5
+ # Include RMagick or MiniMagick support:
6
+ # include CarrierWave::RMagick
7
+ # include CarrierWave::MiniMagick
8
+
9
+ # Choose what kind of storage to use for this uploader:
10
+ storage :file
11
+ # storage :fog
12
+
13
+ # Override the directory where uploaded files will be stored.
14
+ # This is a sensible default for uploaders that are meant to be mounted:
15
+ def store_dir
16
+ "uploads/#{model.model.class.to_s.underscore}/#{model.model.id}/#{model.field_name}"
17
+ end
18
+
19
+ # Provide a default URL as a default if there hasn't been a file uploaded:
20
+ # def default_url
21
+ # # For Rails 3.1+ asset pipeline compatibility:
22
+ # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
23
+ #
24
+ # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
25
+ # end
26
+
27
+ # Process files as they are uploaded:
28
+ # process :scale => [200, 300]
29
+ #
30
+ # def scale(width, height)
31
+ # # do something
32
+ # end
33
+
34
+ # Create different versions of your uploaded files:
35
+ # version :thumb do
36
+ # process :resize_to_fit => [50, 50]
37
+ # end
38
+
39
+ # Add a white list of extensions which are allowed to be uploaded.
40
+ # For images you might use something like this:
41
+ # def extension_white_list
42
+ # %w(jpg jpeg gif png)
43
+ # end
44
+
45
+ # Override the filename of the uploaded files:
46
+ # Avoid using model.id or version_name here, see uploader/store.rb for details.
47
+ # def filename
48
+ # "something.jpg" if original_filename
49
+ # end
50
+
51
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>KmsModels</title>
5
+ <%= stylesheet_link_tag "kms_models/application", media: "all" %>
6
+ <%= javascript_include_tag "kms_models/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,7 @@
1
+ if Kms::Model.table_exists?
2
+ Kms::Model.all.each do |model|
3
+ Kms::AbilityService.register do
4
+ can :manage, model
5
+ end
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ Kms::ExternalsRegistry.register(:models) {|_,_| Kms::ModelsWrapper.new.to_drop }
@@ -0,0 +1 @@
1
+ Kms::HelpService.register_templates Kms::Models::Engine, 'help/models_variables.html'
@@ -0,0 +1,6 @@
1
+ Kms::ResourceService.register(:models, Kms::Model, "fa-tasks")
2
+ if Kms::Model.table_exists?
3
+ Kms::Model.all.each do |model|
4
+ Kms::ResourceService.register(:models, model, "fa-tasks")
5
+ end
6
+ end
@@ -0,0 +1,52 @@
1
+ en:
2
+ models: "Models"
3
+ add_model: "Add Model"
4
+ new_model: "New Model"
5
+ edit_model: "Edit Model"
6
+ update_model: "Update Model"
7
+ add_entry: "Add Entry"
8
+ new_entry: "New Entry"
9
+ edit_entry: "Edit Entry"
10
+ update_entry: "Update Entry"
11
+ no_fields_yet: "No fields yet. Add first field using form below."
12
+ select_field_type: "Select field type"
13
+ select_model: "Select Model"
14
+ collection_name_field_hint: "You can access model collection like this: models.your_collection_name (ex., models.services)"
15
+ has_many_field_placeholder: "Select related objects..."
16
+ belongs_to_field_placeholder: "Select related object..."
17
+ field_types:
18
+ string: "String"
19
+ text: "Text"
20
+ checkbox: "Checkbox"
21
+ file: "File"
22
+ has_many: "Has many"
23
+ belongs_to: "Belongs to"
24
+ liquor_help:
25
+ variables:
26
+ models:
27
+ main_description: 'Variable "models" gives access to models collections of entries. You can access collection using model collection name - "Collection name (for Liquor)" field. For example, if you created some Model with "services" collection name, then you could iterate its collection using "for" tag like this:'
28
+ activerecord:
29
+ models:
30
+ kms/model:
31
+ one: "Model"
32
+ few: "Models"
33
+ many: "Models"
34
+ other: "Models"
35
+ kms/entry:
36
+ one: "Entry"
37
+ few: "Entries"
38
+ many: "Entries"
39
+ other: "Entries"
40
+ attributes:
41
+ kms/model:
42
+ kms_model_name: "Name"
43
+ collection_name: "Collection name (for Liquor)"
44
+ fields: "Fields"
45
+ label_field: "Label field (used for URL/slug generating)"
46
+ kms/field:
47
+ name: "Name"
48
+ liquor_name: "Name for Liquor"
49
+ type: "Type"
50
+ required: "Required"
51
+ kms/entry:
52
+ slug: "Slug"
@@ -0,0 +1,52 @@
1
+ ru:
2
+ models: "Модели"
3
+ add_model: "Добавить модель"
4
+ new_model: "Новая Модель"
5
+ edit_model: "Редактирование модели"
6
+ update_model: "Обновить модель"
7
+ add_entry: "Добавить элемент"
8
+ new_entry: "Новый Элемент"
9
+ edit_entry: "Редактирование Элемента"
10
+ update_entry: "Обновить элемент"
11
+ no_fields_yet: "Пока нет ни одного свойства. Добавьте первое свойство с помощью формы ниже."
12
+ select_field_type: "Выберите тип свойства"
13
+ select_model: "Выберите модель"
14
+ collection_name_field_hint: "К коллекции можно будет обратиться так: models.your_collection_name (напр., models.services)"
15
+ has_many_field_placeholder: "Выберите связанные объекты..."
16
+ belongs_to_field_placeholder: "Выберите связанный объект..."
17
+ field_types:
18
+ string: "Строка"
19
+ text: "Текст"
20
+ checkbox: "Чекбокс"
21
+ file: "Файл"
22
+ has_many: "Имеет много"
23
+ belongs_to: "Связано с"
24
+ liquor_help:
25
+ variables:
26
+ models:
27
+ main_description: 'Переменная models предоставляет доступ к коллекциям моделей, определённых пользователем на вкладке "Модели". Доступ осуществляется через название коллекции модели - поле "Название коллекции (для Liquor)" при создании модели. Например, если создана модель с названием коллекции services, то можно использовать for для итерации по элементам коллекции следующим образом:'
28
+ activerecord:
29
+ models:
30
+ kms/model:
31
+ one: "Модель"
32
+ few: "Модели"
33
+ many: "Моделей"
34
+ other: "Модели"
35
+ kms/entry:
36
+ one: "Элемент"
37
+ few: "Элемента"
38
+ many: "Элементов"
39
+ other: "Элементы"
40
+ attributes:
41
+ kms/model:
42
+ kms_model_name: "Название"
43
+ collection_name: "Название коллекции (для Liquor)"
44
+ fields: "Свойства"
45
+ label_field: "Поле, используемое для генерации ссылок на объекты"
46
+ kms/field:
47
+ name: "Название"
48
+ liquor_name: "Название для Liquor"
49
+ type: "Тип"
50
+ required: "Обязательное"
51
+ kms/entry:
52
+ slug: "Ссылка/URL"
data/config/routes.rb ADDED
@@ -0,0 +1,11 @@
1
+ Kms::Models::Engine.routes.draw do
2
+ constraints(format: "json") do
3
+ resources :models, format: true do
4
+ resources :entries, format: true do
5
+ member do
6
+ post '' => 'entries#update'
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ class CreateKmsModels < ActiveRecord::Migration
2
+ def change
3
+ create_table :kms_models do |t|
4
+ t.string :model_name
5
+ t.string :collection_name
6
+
7
+ t.timestamps null: false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ class CreateKmsFields < ActiveRecord::Migration
2
+ def change
3
+ create_table :kms_fields do |t|
4
+ t.string :name
5
+ t.string :liquor_name
6
+ t.string :type
7
+ t.boolean :required
8
+ t.belongs_to :model
9
+
10
+ t.timestamps null: false
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class CreateKmsEntries < ActiveRecord::Migration
2
+ def change
3
+ create_table :kms_entries do |t|
4
+ t.belongs_to :model, index: true
5
+ t.json :values
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class AddLabelFieldToKmsModels < ActiveRecord::Migration
2
+ def change
3
+ add_column :kms_models, :label_field, :string
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddSlugToKmsEntries < ActiveRecord::Migration
2
+ def change
3
+ add_column :kms_entries, :slug, :string
4
+ add_index :kms_entries, :slug, unique: true
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class FixModelsColumnName < ActiveRecord::Migration
2
+ def change
3
+ rename_column :kms_models, :model_name, :kms_model_name
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddClassNameToKmsFields < ActiveRecord::Migration
2
+ def change
3
+ add_column :kms_fields, :class_name, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddPositionToKmsEntries < ActiveRecord::Migration
2
+ def change
3
+ add_column :kms_entries, :position, :integer, default: 0, null: false
4
+ end
5
+ end
@@ -0,0 +1,67 @@
1
+ module Kms
2
+ class EntryDrop < Liquor::Drop
3
+
4
+ attributes :id, :created_at, :permalink, :model_collection_name
5
+ scopes :order
6
+
7
+ # overriding methods cause we work with 'json' column
8
+ class Scope
9
+ def find_by(_, fields={})
10
+ fields, = Liquor::Drop.unwrap_scope_arguments([ fields ])
11
+
12
+ json_queries = fields.map {|name, value| "values ->> '#{name}' = ?" }
13
+ result = @source.where(json_queries.join(" AND "), *fields.values.map(&:to_s)).first
14
+ Liquor::DropDelegation.wrap_element result if result
15
+ end
16
+
17
+ def find_all_by(_, fields={})
18
+ fields, = Liquor::Drop.unwrap_scope_arguments([ fields ])
19
+
20
+ json_queries = fields.map {|name, value| "values ->> '#{name}' = ?" }
21
+ result = @source.where(json_queries.join(" AND "), *fields.values.map(&:to_s))
22
+ Liquor::DropDelegation.wrap_scope(result)
23
+ end
24
+
25
+ def order(*args)
26
+ args = Liquor::Drop.unwrap_scope_arguments(args)
27
+ parsed_args = args.map do |arg|
28
+ order_clause = arg.split(' ')
29
+ if order_clause[0].in? ["id", "created_at", "updated_at", "position"]
30
+ order_clause.join(' ')
31
+ else
32
+ ["values ->> '#{order_clause[0]}'", order_clause[1].to_s].join(' ')
33
+ end
34
+ end
35
+ # we use reorder because by default we order by position
36
+ Liquor::DropDelegation.wrap_scope @source.reorder(*parsed_args)
37
+ end
38
+ end
39
+
40
+ def initialize(source)
41
+ self.class.instance_eval do
42
+ source.model.fields.pluck(:liquor_name).each do |field_name|
43
+ export field_name.to_sym
44
+ end
45
+ end
46
+ super(source)
47
+ end
48
+
49
+ def method_missing(name, *args, &block)
50
+ field = source.model.fields.find_by(liquor_name: name.to_s)
51
+ field ? field.get_value(source) : super
52
+ end
53
+
54
+ def respond_to_missing?(method_name, include_private = false)
55
+ source.model.fields.where(liquor_name: method_name.to_s).exists? || super
56
+ end
57
+
58
+ def created_at
59
+ source.created_at.to_s
60
+ end
61
+
62
+ def model_collection_name
63
+ source.model.collection_name
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,12 @@
1
+ module Kms
2
+ class ModelsWrapperDrop < Liquor::Drop
3
+ def self.register_model(collection_name)
4
+ has_many collection_name.to_sym
5
+ end
6
+
7
+ Kms::Model.pluck(:collection_name).each do |collection_name|
8
+ register_model collection_name
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ module KmsModels
2
+ class InstallGenerator < Rails::Generators::Base
3
+
4
+ source_root File.expand_path('../../../../../', __FILE__)
5
+
6
+ def insert_engine_routes
7
+ route %(
8
+ mount Kms::Models::Engine => '/kms'
9
+ )
10
+ end
11
+
12
+ def insert_javascript
13
+ append_file "app/assets/javascripts/application.js", "//= require kms_models/application\n"
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require "friendly_id"
2
+ module Kms
3
+ module Models
4
+ class Engine < ::Rails::Engine
5
+ engine_name 'kms_models'
6
+ isolate_namespace Kms::Models
7
+ config.autoload_paths += Dir["#{config.root}/lib/**/"]
8
+ config.to_prepare do
9
+ Dir.glob(File.join(File.dirname(__FILE__), "../../../app/**/*_decorator*.rb")) do |c|
10
+ require_dependency(c)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module Kms
2
+ module Models
3
+ VERSION = '0.6.0'
4
+ end
5
+ end
data/lib/kms_models.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "kms/models/engine"
2
+
3
+ module Kms
4
+ module Models
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :kms_models do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks