kms_models 0.6.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 (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