Skip to content

Commit

Permalink
Remove custom build and create methods from Ingredient
Browse files Browse the repository at this point in the history
Now that we removed abstract_class from the ingredient class
we can use all the Rails defaults to create an ingredient instances.
  • Loading branch information
tvdeyen committed Aug 12, 2021
1 parent 8d548ea commit df4115b
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 180 deletions.
7 changes: 5 additions & 2 deletions app/models/alchemy/element/element_ingredients.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,11 @@ def ingredient_error_messages

# Builds ingredients for this element as described in the +elements.yml+
def build_ingredients
self.ingredients = ingredient_definitions.map do |attributes|
Ingredient.build(role: attributes[:role], element: self)
ingredient_definitions.each do |attributes|
ingredients.build(
role: attributes[:role],
type: Alchemy::Ingredient.normalize_type(attributes[:type]),
)
end
end
end
Expand Down
72 changes: 16 additions & 56 deletions app/models/alchemy/ingredient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class DefinitionError < StandardError; end
belongs_to :element, touch: true, class_name: "Alchemy::Element", inverse_of: :ingredients
belongs_to :related_object, polymorphic: true, optional: true

before_validation(on: :create) { self.value ||= default_value }

validates :type, presence: true
validates :role, presence: true

Expand All @@ -32,32 +34,6 @@ class DefinitionError < StandardError; end
scope :videos, -> { where(type: "Alchemy::Ingredients::Video") }

class << self
# Builds concrete ingredient class as described in the +elements.yml+
def build(attributes = {})
element = attributes[:element]
raise ArgumentError, "No element given. Please pass element in attributes." if element.nil?
raise ArgumentError, "No role given. Please pass role in attributes." if attributes[:role].nil?

definition = element.ingredient_definition_for(attributes[:role])
if definition.nil?
raise DefinitionError,
"No definition found for #{attributes[:role]}. Please define #{attributes[:role]} on #{element[:name]}."
end

ingredient_class = Ingredient.ingredient_class_by_type(definition[:type])
ingredient_class.new(
type: Ingredient.normalize_type(definition[:type]),
value: default_value(definition),
role: definition[:role],
element: element,
)
end

# Creates concrete ingredient class as described in the +elements.yml+
def create(attributes = {})
build(attributes).tap(&:save)
end

# Defines getter and setter method aliases for related object
#
# @param [String|Symbol] The name of the alias
Expand All @@ -77,20 +53,6 @@ def related_object_alias(name, class_name:)
end
end

# Returns an ingredient class by type
#
# Raises NameError if there is no such class in the
# +Alchemy::Ingredients+ module namespace.
#
# If you add custom ingredient class,
# put them in the +Alchemy::Ingredients+ module namespace
#
# @param [String] The ingredient class name to constantize
# @return [Class]
def ingredient_class_by_type(ingredient_type)
normalize_type(ingredient_type).constantize
end

# Modulize ingredient type
#
# Makes sure the passed ingredient type is in the +Alchemy::Ingredients+
Expand All @@ -111,22 +73,6 @@ def translated_label_for(role, element_name = nil)
default: Alchemy.t("ingredient_roles.#{role}", default: role.humanize),
)
end

private

# Returns the default value from ingredient definition
#
# If the value is a symbol it gets passed through i18n
# inside the +alchemy.default_ingredient_texts+ scope
def default_value(definition)
default = definition[:default]
case default
when Symbol
Alchemy.t(default, scope: :default_ingredient_texts)
else
default
end
end
end

# Compatibility method for access from element
Expand Down Expand Up @@ -219,5 +165,19 @@ def preview_ingredient?
def hint_translation_attribute
role
end

# Returns the default value from ingredient definition
#
# If the value is a symbol it gets passed through i18n
# inside the +alchemy.default_ingredient_texts+ scope
def default_value
default = definition[:default]
case default
when Symbol
Alchemy.t(default, scope: :default_ingredient_texts)
else
default
end
end
end
end
5 changes: 4 additions & 1 deletion lib/alchemy/upgrader/tasks/ingredients_migrator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ def create_ingredients
next unless content

essence = content.essence
ingredient = Alchemy::Ingredient.build(role: ingredient_definition[:role], element: element)
ingredient = element.ingredients.build(
role: ingredient_definition[:role],
type: Alchemy::Ingredient.normalize_type(ingredient_definition[:type]),
)
belongs_to_associations = essence.class.reflect_on_all_associations(:belongs_to)
if belongs_to_associations.any?
ingredient.related_object = essence.public_send(belongs_to_associations.first.name)
Expand Down
2 changes: 1 addition & 1 deletion spec/controllers/alchemy/admin/elements_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ module Alchemy
end

let(:element) { create(:alchemy_element, :with_ingredients) }
let(:ingredient) { element.ingredients.first }
let(:ingredient) { element.ingredient_by_role(:headline) }
let(:ingredients_attributes) { { 0 => { id: ingredient.id, value: "Title" } } }
let(:element_params) { { tag_list: "Tag 1", public: false, ingredients_attributes: ingredients_attributes } }

Expand Down
7 changes: 4 additions & 3 deletions spec/controllers/alchemy/admin/ingredients_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,12 @@
end

it_behaves_like "having crop action", model_class: Alchemy::Ingredient do
let(:picture) { build_stubbed(:alchemy_picture) }

let(:croppable_resource) do
Alchemy::Ingredient.build(
type: "Alchemy::Ingredients::Picture",
Alchemy::Ingredients::Picture.new(
element: element,
attachment: attachment,
picture: picture,
role: "picture",
)
end
Expand Down
4 changes: 2 additions & 2 deletions spec/decorators/alchemy/ingredient_editor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

RSpec.describe Alchemy::IngredientEditor do
let(:element) { build(:alchemy_element, name: "element_with_ingredients") }
let(:ingredient) { Alchemy::Ingredients::Text.build(role: "headline", element: element) }
let(:ingredient) { Alchemy::Ingredients::Text.new(role: "headline", element: element) }
let(:ingredient_editor) { described_class.new(ingredient) }

describe "#ingredient" do
Expand Down Expand Up @@ -190,7 +190,7 @@
let(:element) { build(:alchemy_element, name: "all_you_can_eat_ingredients") }

let(:ingredient) do
Alchemy::Ingredients::Html.build(
Alchemy::Ingredients::Html.new(
role: "html",
element: element,
)
Expand Down
2 changes: 1 addition & 1 deletion spec/helpers/alchemy/admin/ingredients_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

describe Alchemy::Admin::IngredientsHelper do
let(:element) { build_stubbed(:alchemy_element, name: "element_with_ingredients") }
let(:ingredient) { Alchemy::Ingredients::Text.build(role: "headline", element: element) }
let(:ingredient) { Alchemy::Ingredients::Text.new(role: "headline", element: element) }
let(:ingredient_editor) { Alchemy::IngredientEditor.new(ingredient) }

describe "#ingredient_label" do
Expand Down
2 changes: 1 addition & 1 deletion spec/helpers/alchemy/elements_block_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ module Alchemy

context "with element having ingredients" do
let(:element) { create(:alchemy_element, :with_ingredients) }
let(:ingredient) { element.ingredients.first }
let(:ingredient) { element.ingredient_by_role(:headline) }

it "should return the ingredients value" do
Alchemy::Deprecation.silenced do
Expand Down
11 changes: 3 additions & 8 deletions spec/models/alchemy/element_ingredients_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
let!(:element) { create(:alchemy_element, :with_ingredients) }

context "with role existing" do
let(:ingredient) { element.ingredients.first }
let(:ingredient) { element.ingredient_by_role(:headline) }

context "with blank value" do
before do
Expand Down Expand Up @@ -100,19 +100,15 @@
let!(:element) { create(:alchemy_element, :with_ingredients) }

context "with role existing" do
let(:ingredient) { element.ingredients.first }
let(:ingredient) { element.ingredient_by_role(:headline) }

context "with blank value" do
before do
expect(ingredient).to receive(:value) { nil }
end

it { expect(element.has_value_for?(:headline)).to be(false) }
end

context "with value present" do
before do
expect(ingredient).to receive(:value) { "Headline" }
ingredient.value = "Headline"
end

it "should return ingredient" do
Expand Down Expand Up @@ -163,7 +159,6 @@
expect(element.ingredient_error_messages).to eq([
"Please enter a headline for all you can eat",
"Text is invalid",
"Please select something else",
])
end
end
Expand Down
Loading

0 comments on commit df4115b

Please sign in to comment.