diff --git a/app/models/alchemy/essence_node.rb b/app/models/alchemy/essence_node.rb new file mode 100644 index 0000000000..b39a8e6ec4 --- /dev/null +++ b/app/models/alchemy/essence_node.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Alchemy + class EssenceNode < BaseRecord + NODE_ID = /\A\d+\z/ + + acts_as_essence( + ingredient_column: :node, + preview_text_column: :node_name, + belongs_to: { + class_name: "Alchemy::Node", + foreign_key: :node_id, + inverse_of: :essence_nodes, + optional: true + } + ) + + delegate :name, to: :node, prefix: true + + def ingredient=(node) + case node + when NODE_ID + self.node = Alchemy::Page.new(id: node) + when Alchemy::Node + self.node = node + else + super + end + end + end +end diff --git a/app/models/alchemy/node.rb b/app/models/alchemy/node.rb index 7649a5d64a..8ef38f8ed2 100644 --- a/app/models/alchemy/node.rb +++ b/app/models/alchemy/node.rb @@ -11,6 +11,8 @@ class Node < BaseRecord belongs_to :language, class_name: 'Alchemy::Language' belongs_to :page, class_name: 'Alchemy::Page', optional: true, inverse_of: :nodes + has_many :essence_nodes, class_name: "Alchemy::Node", inverse_of: :node + validates :name, presence: true, if: -> { page.nil? } validates :url, format: { with: VALID_URL_REGEX }, unless: -> { url.nil? } diff --git a/app/views/alchemy/essences/_essence_node_editor.html.erb b/app/views/alchemy/essences/_essence_node_editor.html.erb new file mode 100644 index 0000000000..0dee2f0e82 --- /dev/null +++ b/app/views/alchemy/essences/_essence_node_editor.html.erb @@ -0,0 +1,21 @@ +<%# + Available locals: + * content (The object the essence is linked to the element) + * html_options + + Please consult Alchemy::Content.rb docs for further methods on the content object +%> +
+ <%= content_label(content) %> + <%= select_tag( + content.form_field_name, + options_from_collection_for_select( + local_assigns.fetch(:options, {})[:nodes] || Alchemy::Node.where(site: Alchemy::Site.current), + :id, + :name, + content.essence.node_id + ), + include_blank: t(".none"), + class: "alchemy_selectbox essence_editor_select full_width" + ) %> +
diff --git a/app/views/alchemy/essences/_essence_node_view.html.erb b/app/views/alchemy/essences/_essence_node_view.html.erb new file mode 100644 index 0000000000..dfe27342d0 --- /dev/null +++ b/app/views/alchemy/essences/_essence_node_view.html.erb @@ -0,0 +1,2 @@ +<%# The content object holds the essence %> +<%= content.ingredient %> diff --git a/db/migrate/20200423073425_create_alchemy_essence_nodes.rb b/db/migrate/20200423073425_create_alchemy_essence_nodes.rb new file mode 100644 index 0000000000..43ed9668bf --- /dev/null +++ b/db/migrate/20200423073425_create_alchemy_essence_nodes.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class CreateAlchemyEssenceNodes < ActiveRecord::Migration[5.2] + def change + create_table :alchemy_essence_nodes do |t| + t.integer "node_id" + t.index ["node_id"], name: "index_alchemy_essence_nodes_on_node_id" + t.timestamps + end + add_foreign_key "alchemy_essence_nodes", "alchemy_nodes", column: "node_id" + end +end diff --git a/spec/dummy/db/migrate/20200423073425_create_alchemy_essence_nodes.rb b/spec/dummy/db/migrate/20200423073425_create_alchemy_essence_nodes.rb new file mode 120000 index 0000000000..7c19075432 --- /dev/null +++ b/spec/dummy/db/migrate/20200423073425_create_alchemy_essence_nodes.rb @@ -0,0 +1 @@ +../../../../db/migrate/20200423073425_create_alchemy_essence_nodes.rb \ No newline at end of file diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb index 9f941565cf..74697e085d 100644 --- a/spec/dummy/db/schema.rb +++ b/spec/dummy/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_02_26_213334) do +ActiveRecord::Schema.define(version: 2020_04_23_073425) do create_table "alchemy_attachments", force: :cascade do |t| t.string "name" @@ -110,6 +110,13 @@ t.integer "updater_id" end + create_table "alchemy_essence_nodes", force: :cascade do |t| + t.integer "node_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["node_id"], name: "index_alchemy_essence_nodes_on_node_id" + end + create_table "alchemy_essence_pages", force: :cascade do |t| t.integer "page_id" t.datetime "created_at", null: false @@ -360,6 +367,7 @@ add_foreign_key "alchemy_contents", "alchemy_elements", column: "element_id", on_update: :cascade, on_delete: :cascade add_foreign_key "alchemy_elements", "alchemy_pages", column: "page_id", on_update: :cascade, on_delete: :cascade + add_foreign_key "alchemy_essence_nodes", "alchemy_nodes", column: "node_id" add_foreign_key "alchemy_essence_pages", "alchemy_pages", column: "page_id" add_foreign_key "alchemy_nodes", "alchemy_languages", column: "language_id" add_foreign_key "alchemy_nodes", "alchemy_pages", column: "page_id", on_delete: :cascade diff --git a/spec/models/alchemy/essence_node_spec.rb b/spec/models/alchemy/essence_node_spec.rb new file mode 100644 index 0000000000..b37b9e1ae3 --- /dev/null +++ b/spec/models/alchemy/essence_node_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Alchemy::EssenceNode, type: :model do + it { is_expected.to belong_to(:ingredient_association).optional.class_name('Alchemy::Node') } + + describe '#ingredient' do + let(:node) { build(:alchemy_node) } + + subject { described_class.new(node: node).ingredient } + + it { is_expected.to eq(node) } + end + + describe '#preview_text' do + let(:node) { build(:alchemy_node) } + + subject { described_class.new(node: node).preview_text } + + it { is_expected.to eq(node.name) } + end +end