Skip to content

Commit

Permalink
Merge pull request #2170 from tvdeyen/support-ingredients-element-hel…
Browse files Browse the repository at this point in the history
…pers

Return ingredients value if element asked for ingredient
  • Loading branch information
tvdeyen authored Aug 11, 2021
2 parents 95c93b8 + c9dc4ac commit 64194df
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 14 deletions.
14 changes: 8 additions & 6 deletions app/helpers/alchemy/elements_block_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,23 @@ def content(name)
# If the element uses +ingredients+ it returns the +value+ of the ingredient record.
#
def ingredient(name)
element.ingredient(name).presence || element.ingredient_by_role(name)&.value
element.ingredient(name)
end

deprecate ingredient: :value, deprecator: Alchemy::Deprecation

# Returns the value of one of the element's ingredients.
#
def value(name)
element.ingredient_by_role(name)&.value
element.value_for(name)
end

# Returns true if the given content or ingredient has been filled by the user.
# Returns true if the given content or ingredient has a value.
#
def has?(name)
element.has_ingredient?(name) || element.has_value_for?(name)
if element.ingredient_definitions.any?
element.has_value_for?(name)
else
element.has_ingredient?(name)
end
end

# Return's the given content's essence.
Expand Down
17 changes: 14 additions & 3 deletions app/models/alchemy/element/element_essences.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,28 @@ class Element < BaseRecord
module ElementEssences
# Returns the contents essence value (aka. ingredient) for passed content name.
def ingredient(name)
content = content_by_name(name)
return nil if content.blank?
ing = ingredient_by_role(name)
if ing
Alchemy::Deprecation.warn <<~WARN
Using `element.ingredient` to get the value of an ingredient is deprecated and will change in Alchemy 6.1
If you want to read the value of an elements ingredient please use `element.value_for(:ingredient_role)` instead.
The next version of Alchemy will return a `Alchemy::Ingredient` record instead.
WARN
ing.value
else
content = content_by_name(name)
return nil if content.blank?

content.ingredient
content.ingredient
end
end

# True if the element has a content for given name,
# that has an essence value (aka. ingredient) that is not blank.
def has_ingredient?(name)
ingredient(name).present?
end
deprecate has_ingredient?: :has_value_for?, deprecator: Alchemy::Deprecation

# Returns all essence errors in the format of:
#
Expand Down
7 changes: 6 additions & 1 deletion app/models/alchemy/element/element_ingredients.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ module ElementIngredients
validates_associated :ingredients, on: :update
end

# The value of an ingredient of the element by role
def value_for(role)
ingredient_by_role(role)&.value
end

# Find first ingredient from element by given role.
def ingredient_by_role(role)
ingredients.detect { |ingredient| ingredient.role == role.to_s }
Expand Down Expand Up @@ -87,7 +92,7 @@ def ingredients_with_errors
# True if the element has a ingredient for given name
# that has a non blank value.
def has_value_for?(role)
ingredient_by_role(role)&.value.present?
value_for(role).present?
end

# Ingredient validation error messages
Expand Down
16 changes: 14 additions & 2 deletions spec/helpers/alchemy/elements_block_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,24 @@ module Alchemy
let(:ingredient) { element.ingredients.first }

it "should return the ingredients value" do
expect(ingredient).to receive(:value).and_call_original
subject.ingredient(:headline)
Alchemy::Deprecation.silenced do
expect(ingredient).to receive(:value).and_call_original
subject.ingredient(:headline)
end
end
end
end

describe "#value" do
let(:element) { create(:alchemy_element, :with_ingredients) }
let(:ingredient) { element.ingredients.first }

it "should return the ingredients value" do
expect(element).to receive(:value_for).and_call_original
subject.value(:headline)
end
end

describe "#has?" do
context "with element having contents" do
it "should delegate to the element's #has_ingredient? method" do
Expand Down
30 changes: 30 additions & 0 deletions spec/models/alchemy/element_ingredients_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,36 @@
end
end

describe "#value_for" do
let!(:element) { create(:alchemy_element, :with_ingredients) }

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

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

it { expect(element.value_for(:headline)).to be_nil }
end

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

it "should return value" do
expect(element.value_for(:headline)).to eq("Headline")
end
end
end

context "role not existing" do
it { expect(element.value_for(:foo)).to be_nil }
end
end

describe "#has_value_for?" do
let!(:element) { create(:alchemy_element, :with_ingredients) }

Expand Down
23 changes: 21 additions & 2 deletions spec/models/alchemy/element_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -721,8 +721,27 @@ module Alchemy
context "retrieving contents, essences and ingredients" do
let(:element) { create(:alchemy_element, :with_contents, name: "news") }

it "should return an ingredient by name" do
expect(element.ingredient("news_headline")).to eq(EssenceText.first.ingredient)
describe "#ingredient" do
context "with contents" do
let(:essence) { element.content_by_name(:news_headline) }

it "returns a contents value by name" do
expect(essence).to receive(:ingredient).and_call_original
element.ingredient("news_headline")
end
end

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

it "returns a ingredients value by name" do
Alchemy::Deprecation.silenced do
expect(ingredient).to receive(:value).and_call_original
element.ingredient("headline")
end
end
end
end

it "should return the content for rss title" do
Expand Down

0 comments on commit 64194df

Please sign in to comment.