Skip to content

Commit

Permalink
Fixes #432 - Create association on locale change
Browse files Browse the repository at this point in the history
According to the docs, calling MyPage.instance.header
should get the header text for current locale.
However, the associations are set up in a singleton
for a default locale and never modified.

The language-specific methods like MyPage.instance.header_en
still work, but it would be nice to have fae handle the locale
for us.

This change checks for languages in fae_fields for page
and dynamically changes the association if the locale change
is detected.
  • Loading branch information
xprazak2 committed Feb 9, 2019
1 parent 901345d commit 8b785da
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 30 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ gem 'sass', require: 'sass'
group :test, :development do
gem 'rspec-rails', '~> 3.6.0'
gem 'pry'
gem 'pry-byebug'
end

group :test do
Expand Down
7 changes: 6 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ GEM
debug_inspector (>= 0.0.1)
browser (2.5.3)
builder (3.2.3)
byebug (10.0.2)
capistrano (3.10.1)
airbrussh (>= 1.0.0)
i18n
Expand Down Expand Up @@ -226,6 +227,9 @@ GEM
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-byebug (3.6.0)
byebug (~> 10.0)
pry (~> 0.10)
public_suffix (3.0.2)
rack (2.0.4)
rack-test (1.0.0)
Expand Down Expand Up @@ -368,6 +372,7 @@ DEPENDENCIES
guard-rspec (~> 4.7.3)
mysql2
pry
pry-byebug
rails (~> 5.2.0)
rails-controller-testing
rails-perftest
Expand All @@ -381,4 +386,4 @@ DEPENDENCIES
yarjuf

BUNDLED WITH
1.13.0
1.16.5
73 changes: 44 additions & 29 deletions app/models/fae/static_page.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
module Fae
class StaticPage < ActiveRecord::Base

include Fae::BaseModelConcern
include Fae::StaticPageConcern

validates :title, presence: true

@singleton_is_setup = false
@current_locale = I18n.locale

def self.instance
setup_dynamic_singleton
setup_dynamic_methods
row = includes(fae_fields.keys).references(fae_fields.keys).find_by_slug(@slug)
row = create(title: @slug.titleize, slug: @slug) if row.blank?
row
Expand All @@ -31,50 +30,67 @@ def as_json(options={})

private

def self.setup_dynamic_singleton
return if @singleton_is_setup

def self.setup_dynamic_methods
fae_fields.each do |name, value|
type = value.is_a?(Hash) ? value[:type] : value
languages = value.try(:[], :languages)

if languages.present?
languages.each do |lang|
# Save with suffix for form fields
define_association("#{name}_#{lang}", type)
define_validations("#{name}_#{lang}", type, value[:validates]) if supports_validation(type, value)
end
# Save with lookup to have default language return in front-end use (don't need to worry about validations here)
default_language = Rails.application.config.i18n.default_locale || languages.first
define_association(name, type, "#{name}_#{default_language}")
else
# Normal content_blocks
define_association(name, type)
define_validations(name, type, value[:validates]) if supports_validation(type, value)
languages = value.try(:[], :languages) || []
process_field(languages, name, type, value)
end
@current_locale = I18n.locale
end

def self.process_field(languages, name, type, value)
return methods_without_lang(name, type, value) if languages.empty?
process_field_with_lang languages, name, type, value
end

def self.process_field_with_lang(languages, name, type, value)
methods_with_lang(languages, name, type, value)

if I18n.locale != @current_locale
define_association(name, type, "#{name}_#{I18n.locale}")
end
end

def self.methods_with_lang(languages, name, type, value)
languages.each do |lang|
# Save with suffix for form fields
define_association("#{name}_#{lang}", type)
if supports_validation(type, value)
define_validations("#{name}_#{lang}", type, value[:validates])
end
end
end

@singleton_is_setup = true
def self.methods_without_lang(name, type, value)
define_association(name, type)
if supports_validation(type, value)
define_validations(name, type, value[:validates])
end
end

def self.define_association(name, type, locale_name = nil)
locale_name ||= name

send :has_one, name.to_sym, -> { where(attached_as: locale_name.to_s)}, as: poly_sym(type), class_name: type.to_s, dependent: :destroy
send :accepts_nested_attributes_for, name, allow_destroy: true
send :define_method, :"#{name}_content", -> { send(name.to_sym).try(:content) }
end

def self.define_validations(name, type, validations)
unique_method_name = "is_#{self.name.underscore}_#{name.to_s}?".to_sym
slug = @slug
validations[:if] = unique_method_name
return if type.validators.any? do |val|
val.options[:if] == unique_method_name(name)
end
validations[:if] = unique_method_name(name)
type.validates(:content, validations)
type.send(:define_method, unique_method_name) do
contentable.slug == slug && attached_as == name.to_s if contentable.present?
type.send(:define_method, unique_method_name(name)) do
contentable.slug == @slug && attached_as == name.to_s if contentable.present?
end
end

def unique_method_name(name)
"is_#{self.name.underscore}_#{name.to_s}?".to_sym
end

def self.supports_validation(type, value)
# validations are only supported on Fae::TextField and Fae::TextArea
poly_sym(type) == :contentable && value.try(:[], :validates).present?
Expand Down Expand Up @@ -104,6 +120,5 @@ def field_json(assoc)
return assoc_obj.as_json
end
end

end
end

0 comments on commit 8b785da

Please sign in to comment.