udongo 0.1.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8804f4bc7b8e851f44cccf95520180393c1edff7
4
- data.tar.gz: 36301436a4b6eee426dd7515c33a7d1eaf03ae38
3
+ metadata.gz: f653f73b0217efa872c2c95ba0783abc619759c7
4
+ data.tar.gz: 11a751bfb31b7bb8ad63e61deff0d68d9ad981c9
5
5
  SHA512:
6
- metadata.gz: 948078946e5c3c9cc5a00d9d9d04c81b40c14bd008653abf6b74f46739e7c2e07af9f23c46f1d0144d46a6a63ab93d42e46a79991a3bae4f04138f96a58a0760
7
- data.tar.gz: c3d3e61d44fb48f3bf62dd8a8b6e487a171115f1e2e1d9d5deb26517531d1e856f3b8727fbdffbd57530bb4216c6f0dd9270004676a249ef0182cb87331bc442
6
+ metadata.gz: 6fd818e7d16aed0a1577018f55f3fa5986480ee41498e7c8e752be3a3f3b4feff0cece1575c8968ec7f70e902658628b61aae95bf0b202b2b9934c3761152591
7
+ data.tar.gz: a7651642f1ad02aa54039ad91326a1d1913b8dedd50a95548f16f639a2a18c28064af4917f9fe1e08fe222d511cbc398ea44438c5e9352d8e0c6e7ca0ddf909c
@@ -25,7 +25,6 @@ module Concerns
25
25
  @model = model.find(params[:id]).decorate
26
26
  end
27
27
 
28
- # TODO refactor?
29
28
  def content_path
30
29
  column = @model.column
31
30
  path = "edit_translation_backend_#{column.row.rowable.class.to_s.downcase}_path"
@@ -8,6 +8,6 @@ class RedirectDecorator < Draper::Decorator
8
8
  end
9
9
 
10
10
  def summary
11
- "#{I18n.t('b.from')} #{object.source_uri} #{I18n.t('b.to')} #{object.destination_uri}"
11
+ "#{I18n.t('b.from')} #{object.source_uri} #{I18n.t('b.to').downcase} #{object.destination_uri}"
12
12
  end
13
13
  end
@@ -13,5 +13,5 @@ class Backend::PageTranslationForm < Reform::Form
13
13
  property :seo_slug, on: :seo
14
14
 
15
15
  validates :title, presence: true
16
- validates :seo_slug, presence: true # TODO only if necessary!
16
+ validates :seo_slug, presence: true
17
17
  end
@@ -7,19 +7,8 @@ module Concerns
7
7
  after_touch :flush_cache
8
8
 
9
9
  scope :find_in_cache, ->(value) {
10
- Rails.cache.fetch([name, value]) do
11
- o = find_by!(@cache_field => value)
12
-
13
- # If the model is translatable, we want all the translation fields in
14
- # every locale to be initialized. This way we avoid a separate query
15
- # for each of the fields in the translation collection.
16
- if o.respond_to?(:translatable?) && o.translatable?
17
- Udongo.config.locales.each do |l|
18
- name.constantize.translation_config.fields.each { |f| o.translation(l).send(f) }
19
- end
20
- end
21
-
22
- o
10
+ Rails.cache.fetch [name, value] do
11
+ find_by!(@cache_field => value)
23
12
  end
24
13
  }
25
14
  end
@@ -4,24 +4,32 @@ module Concerns
4
4
 
5
5
  included do
6
6
  has_many :stores, as: :storable, dependent: :destroy
7
- after_save { store.save }
8
- end
9
7
 
10
- def store
11
- @store_collection ||= Concerns::Storable::Collection.new(
12
- self, self.class.store_config
13
- )
8
+ after_save do
9
+ @store_collections.keys.each { |c| store(c).save } if @store_collections
10
+ end
14
11
  end
15
12
 
16
13
  def storable?
17
14
  true
18
15
  end
19
16
 
17
+ def store(collection = :default)
18
+ @store_collections = {} unless @store_collections
19
+
20
+ unless @store_collections[collection.to_sym]
21
+ @store_collections[collection.to_sym] = Concerns::Storable::Collection.new(
22
+ self, collection, self.class.store_config
23
+ )
24
+ end
25
+
26
+ @store_collections[collection.to_sym]
27
+ end
28
+
20
29
  module ClassMethods
21
- def storable_field(name, klass, default = nil)
22
- delegate name, to: :store
23
- delegate "#{name}=", to: :store
24
- store_config.add(name, klass, default)
30
+ def storable_field(name, type, default = nil)
31
+ delegate name, "#{name}=", to: :store
32
+ store_config.add name, type, default
25
33
  end
26
34
 
27
35
  def store_config
@@ -1,116 +1,61 @@
1
1
  module Concerns
2
2
  module Storable
3
3
  class Collection
4
- def initialize(parent, config)
4
+ def initialize(parent, category, config)
5
5
  @parent = parent
6
- @config = config
7
- @stores = {}
8
- end
9
-
10
- def method_missing(method_sym, *arguments, &block)
11
- ascii_name = method_sym.to_s.gsub('=', '').to_sym
12
-
13
- if @config.fields.keys.include?(ascii_name)
14
- if method_sym.to_s.include?('=')
15
- write(ascii_name, arguments.first)
16
- else
17
- read(method_sym)
18
- end
19
- else
20
- super
21
- end
22
- end
23
-
24
- def read(field)
25
- field = field.to_sym
26
- init_field(field.to_sym)
27
- object = @stores[field]
28
-
29
- unless object.value.nil?
30
- return object.value if klasses_match(@config.fields[field][:klass], object.value)
31
- end
32
-
33
- object.value = Marshal.load(Marshal.dump(@config.fields[field][:default]))
34
- object.value
35
- end
36
-
37
- def write(field, value)
38
- field = field.to_sym
39
- init_field(field)
40
- value = transform_value(@config.fields[field][:klass], value)
6
+ @category = category
41
7
 
42
- @stores[field].value = value
8
+ init_attributes(config)
9
+ init_values(config)
43
10
  end
44
11
 
45
12
  def save
46
- @stores.map { |field,object| object.save }
47
- end
48
-
49
- private
50
-
51
- def init_field(field)
52
- unless @stores[field.to_sym]
53
- raise "The field '#{field.to_s}' is not allowed." unless @config.allowed?(field)
54
-
55
- @stores[field] = ::Store.find_or_create_by!(
13
+ attributes.each do |name,value|
14
+ tmp = ::Store.find_or_initialize_by(
15
+ collection: @category,
56
16
  storable_type: @parent.class.name,
57
17
  storable_id: @parent.id,
58
- klass: @config.fields[field.to_sym][:klass],
59
- name: field
18
+ name: name
60
19
  )
61
- end
62
- end
63
20
 
64
- def klasses_match(klass, value)
65
- Concerns::Storable::Config::KLASSES[klass].include? value.class
66
- end
67
-
68
- def transform_value(klass, value)
69
- send("#{klass}_value", value)
21
+ tmp.value = value
22
+ tmp.save!
23
+ end
70
24
  end
71
25
 
72
- def string_value(value)
73
- value.to_s if value.is_a?(String) || value.is_a?(Symbol)
74
- end
26
+ def delete
27
+ ::Store.where(
28
+ storable_type: @parent.class,
29
+ storable_id: @parent.id,
30
+ collection: @category,
31
+ ).each { |s| s.destroy }
75
32
 
76
- def integer_value(value)
77
- value if value.is_a?(Fixnum)
33
+ reset_values
78
34
  end
79
35
 
80
- def float_value(value)
81
- value if value.is_a?(Float)
82
- end
36
+ private
83
37
 
84
- def array_value(value)
85
- value if value.is_a?(Array)
86
- end
38
+ def init_attributes(config)
39
+ extend(Virtus.model)
87
40
 
88
- def boolean_value(value)
89
- if value === true || value == '1' || value == 1
90
- true
91
- elsif value === false || value == '0' || value == 0
92
- false
41
+ config.fields.each do |field,options|
42
+ attribute field, options[:type], default: options[:default], lazy: true
93
43
  end
94
44
  end
95
45
 
96
- def date_value(value)
97
- return value if value.is_a?(Date)
98
-
99
- begin
100
- Date.parse(value)
101
- rescue
102
- nil
46
+ def init_values(config)
47
+ ::Store.where(
48
+ storable_type: @parent.class,
49
+ storable_id: @parent.id,
50
+ collection: @category,
51
+ ).pluck(:name, :value).each do |field, value|
52
+ send "#{field}=", value if config.allowed?(field)
103
53
  end
104
54
  end
105
55
 
106
- def date_time_value(value)
107
- return value if value.is_a?(DateTime)
108
-
109
- begin
110
- DateTime.parse(value)
111
- rescue
112
- nil
113
- end
56
+ def reset_values
57
+ attributes.keys.each { |k| send("#{k}=", nil) }
58
+ true
114
59
  end
115
60
  end
116
61
  end
@@ -3,38 +3,17 @@ module Concerns
3
3
  class Config
4
4
  attr_reader :fields
5
5
 
6
- KLASSES = {
7
- array: [Array],
8
- boolean: [TrueClass, FalseClass],
9
- date: [Date],
10
- date_time: [DateTime],
11
- float: [Float],
12
- integer: [Fixnum],
13
- string: [String]
14
- }
15
-
16
6
  def initialize
17
7
  @fields = {}
18
8
  end
19
9
 
20
- def add(field, klass, default = nil)
21
- raise "#{klass} is not a valid storable config klass" unless valid_klass?(klass)
22
-
23
- @fields[field.to_sym] = {
24
- klass: klass.to_sym,
25
- default: default
26
- }
10
+ def add(field, type, default = nil)
11
+ @fields[field.to_sym] = { type: type, default: default }
27
12
  end
28
13
 
29
14
  def allowed?(field)
30
15
  @fields.keys.include?(field.to_sym)
31
16
  end
32
-
33
- private
34
-
35
- def valid_klass?(value)
36
- KLASSES.keys.include?(value.to_sym)
37
- end
38
17
  end
39
18
  end
40
19
  end
@@ -3,36 +3,48 @@
3
3
  module Concerns
4
4
  module Translatable
5
5
  extend ActiveSupport::Concern
6
+ include Concerns::Storable
6
7
 
7
8
  included do
8
9
  serialize :locales, Array
9
- has_many :translations, as: :translatable, dependent: :destroy
10
- scope :within_locale, ->(locale) { where('locales LIKE ?', "%#{locale}%")}
11
- end
12
10
 
13
- def translation(locale = I18n.locale)
14
- @translation_collections = {} unless @translation_collections
15
- @translation_collections[locale.to_sym] ||= Concerns::Translatable::Collection.new(
16
- self, self.class.translation_config, locale
17
- )
11
+ after_save do
12
+ locales = ::Store.where(
13
+ storable_type: self.class,
14
+ storable_id: self.id,
15
+ name: self.class.translatable_fields_list
16
+ ).pluck(:collection).uniq
17
+
18
+ update_column :locales, locales
19
+ end
20
+
21
+ scope :with_locale, ->(locale) { where('locales LIKE ?', "%#{locale}%")}
18
22
  end
19
23
 
20
24
  def translatable?
21
25
  true
22
26
  end
23
27
 
28
+ def translation(locale = I18n.locale)
29
+ store(locale)
30
+ end
31
+
24
32
  module ClassMethods
25
- def translatable_field(name)
26
- delegate name, to: :translation
27
- translation_config.add(name)
33
+ def translatable_field(name, type = String, default = nil)
34
+ delegate name, "#{name}=", to: :translation
35
+ self.store_config.add name, type, default
36
+
37
+ unless translatable_fields_list.include?(name.to_sym)
38
+ translatable_fields_list << name.to_sym
39
+ end
28
40
  end
29
41
 
30
42
  def translatable_fields(*args)
31
43
  args.each { |name| translatable_field(name) }
32
44
  end
33
45
 
34
- def translation_config
35
- @translation_config ||= Concerns::Translatable::Config.new
46
+ def translatable_fields_list
47
+ @translatable_fields_list ||= []
36
48
  end
37
49
  end
38
50
  end
@@ -5,7 +5,6 @@ class FormSubmission < ActiveRecord::Base
5
5
  has_many :data, foreign_key: :submission_id, class_name: 'FormSubmissionData'
6
6
 
7
7
  validates :form, presence: true
8
- # TODO: belongs_to :visitor
9
8
 
10
9
  def data_object
11
10
  data.inject(OpenStruct.new) do |stack, d|
@@ -3,8 +3,8 @@ class Store < ActiveRecord::Base
3
3
 
4
4
  serialize :value
5
5
 
6
- validates :name, :klass, presence: true
6
+ validates :collection, :name, presence: true
7
7
  validates :name,
8
8
  uniqueness: { case_sensitive: false,
9
- scope: [:storable_type, :storable_id] }
9
+ scope: [:collection, :storable_type, :storable_id] }
10
10
  end
@@ -0,0 +1,106 @@
1
+ en:
2
+ b:
3
+ actions: Actions
4
+ add: Add
5
+ admins: Admins
6
+ advanced: Advanced
7
+ cancel: Cancel
8
+ content: Content
9
+ current_image: Current image
10
+ custom_title: Custom title
11
+ custom_url: Custom URL
12
+ delete: Delete
13
+ description: Description
14
+ destination: Destination
15
+ down: Down
16
+ edit: Edit
17
+ email: E-mail
18
+ emails: E-mails
19
+ email_template: E-mail template
20
+ email_templates: E-mail templates
21
+ enabled?: Enabled?
22
+ extra: Extra
23
+ first_name: First name
24
+ flexible_content: Flexible content
25
+ forms: Forms
26
+ from: From
27
+ general: General
28
+ html_content: HTML content
29
+ last_name: Last name
30
+ locale: Locale
31
+ login: Login
32
+ logout: Logout
33
+ move: Move
34
+ name: Name
35
+ navigation: Navigation
36
+ new: New
37
+ none: None
38
+ not_yet_sent: Not yet sent
39
+ page: Page
40
+ pages: Pages
41
+ password: Password
42
+ plain_content: Plain content
43
+ recipient: Recipient
44
+ redirect: Redirect
45
+ redirects: Redirects
46
+ restart_webserver: Restart webserver
47
+ save: Save
48
+ search: Search
49
+ sender: Sender
50
+ sent_at: Sent at
51
+ settings: Settings
52
+ snippet: Snippet
53
+ snippets: Snippets
54
+ source: Source
55
+ status: Status
56
+ status_code: Status code
57
+ subject: Subject
58
+ tags: Tags
59
+ title: Title
60
+ to: To
61
+ up: Up
62
+ used: Used
63
+ variables: Variables
64
+ view: View
65
+
66
+ msg:
67
+ added: '%s was added.'
68
+ admins:
69
+ account_details: Account details
70
+ added: The admin was added.
71
+ deleted: The admin was deleted.
72
+ personal_details: Personal details
73
+ changes_saved: The changes have been saved.
74
+ confirm: Are you sure?
75
+ content_types:
76
+ image: Image
77
+ text: Text
78
+ deleted: '%s was deleted.'
79
+ edited: '%s was edited.'
80
+ flexible_content:
81
+ add_column: Add column
82
+ add_row: Add row
83
+ add_text: Add text
84
+ delete_row: Delete row
85
+ edit_column: Edit column
86
+ edit_image: Edit image
87
+ edit_text: Edit text
88
+ explanation: With this module you can create flexible responsive content. Click the button below to create the first row.
89
+ forgot_password: Forgot password?
90
+ help_texts:
91
+ status_code: More info about the use of status codes.
92
+ incorrect_login: Incorret login credentials.
93
+ navigation:
94
+ added: The navigation item was added.
95
+ custom: Custom
96
+ deleted: The navigation item was deleted.
97
+ no_items: There are no items.
98
+
99
+ saved: '%s was saved.'
100
+ seo: SEO
101
+ status_codes:
102
+ '301': 301 (Moved Permanently)
103
+ '303': 303 (See Other)
104
+ '307': 307 (Temporary Redirect)
105
+ webserver:
106
+ restarted: The webserver was restarted.
@@ -0,0 +1,68 @@
1
+ en:
2
+ simple_form:
3
+ "yes": 'Yes'
4
+ "no": 'No'
5
+ required:
6
+ text: 'required'
7
+ mark: '*'
8
+ # You can uncomment the line below if you need to overwrite the whole required html.
9
+ # When using html, text and mark won't be used.
10
+ # html: '<abbr title="required">*</abbr>'
11
+ error_notification:
12
+ default_message: 'Please check the errors below:'
13
+
14
+ labels:
15
+ defaults:
16
+ caption: Caption
17
+ category: Category
18
+ content: Content
19
+ description: Description
20
+ disabled: Disabled
21
+ email: E-mail
22
+ extra: Extra
23
+ first_name: First name
24
+ html_content: HTML content
25
+ identifier: Internal name
26
+ label: Label
27
+ last_name: Last name
28
+ message: Message
29
+ name: Name
30
+ password: Password
31
+ password_confirmation: Password confirmation
32
+ phone: Phone
33
+ plain_content: Plain content
34
+ seo_title: Page title
35
+ seo_slug: Custom URL
36
+ seo_description: Description
37
+ seo_keywords: Keywords
38
+ seo_custom: Extra meta-tags
39
+ subject: Subject
40
+ subtitle: Subtitle
41
+ summary: Summary
42
+ title: Title
43
+ visible: Visible?
44
+ width: Width
45
+ url: URL
46
+
47
+ content_column:
48
+ content_type: Type
49
+ width_xs: Width (extra small)
50
+ width_sm: Width (small)
51
+ width_md: Width (medium)
52
+ width_lg: Width (large)
53
+ width_xl: Width (extra large)
54
+
55
+ email_template:
56
+ from_email: Sender e-mail address
57
+ from_name: Sender name
58
+
59
+ navigation_item:
60
+ page_id: Page
61
+ path: URL
62
+
63
+ page:
64
+ parent_id: Parent page
65
+
66
+ redirect:
67
+ destination_uri: Destination
68
+ source_uri: Source
@@ -0,0 +1,6 @@
1
+ class AddCollectionToStore < ActiveRecord::Migration
2
+ def change
3
+ add_column :stores, :collection, :string, after: 'storable_id'
4
+ add_index :stores, :collection
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ class RemoveKlassFromStores < ActiveRecord::Migration
2
+ def change
3
+ remove_column :stores, :klass
4
+ add_index :stores, [:collection, :storable_id, :storable_type], name: 'idx_storable'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class RemoveTranslationModel < ActiveRecord::Migration
2
+ def change
3
+ drop_table :translations
4
+ end
5
+ end
@@ -28,7 +28,6 @@ class Udongo::FormGenerator < Rails::Generators::Base
28
28
 
29
29
  @fields.each do |field|
30
30
  field_object = f.fields.create!(locales: Udongo.config.locales, name: field.name, field_type: field.type)
31
- # TODO: validations
32
31
  #field_object.validations.create!(locales: Udongo.config.locales, validation_class: 'Udongo::FormValidations::Required')
33
32
  end
34
33
 
@@ -1,4 +1,3 @@
1
- # TODO: Find a proper solution to autorequire (udongo) classes
2
1
  require 'udongo/engine'
3
2
  require 'udongo/config'
4
3
  require 'udongo/breadcrumb'
@@ -22,6 +21,7 @@ require 'ransack'
22
21
  require 'ckeditor'
23
22
  require 'responders'
24
23
  require 'will_paginate'
24
+ require 'virtus'
25
25
 
26
26
  module Udongo
27
27
  PATH = File.expand_path('../../', __FILE__)
@@ -1,6 +1,4 @@
1
1
  class Udongo::ObjectPath
2
- # TODO it would be better if this always expects an array, that way this could
3
- # be rewritten a lot cleaner.
4
2
  def self.find(object)
5
3
  unless object.is_a?(Array)
6
4
  return cleanup("#{object.class.name.underscore}_path")
@@ -1,3 +1,3 @@
1
1
  module Udongo
2
- VERSION = '0.1.0'
2
+ VERSION = '1.0.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: udongo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Davy Hellemans
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-31 00:00:00.000000000 Z
12
+ date: 2016-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -419,6 +419,26 @@ dependencies:
419
419
  - - ">="
420
420
  - !ruby/object:Gem::Version
421
421
  version: 3.0.6
422
+ - !ruby/object:Gem::Dependency
423
+ name: virtus
424
+ requirement: !ruby/object:Gem::Requirement
425
+ requirements:
426
+ - - "~>"
427
+ - !ruby/object:Gem::Version
428
+ version: '1.0'
429
+ - - ">="
430
+ - !ruby/object:Gem::Version
431
+ version: 1.0.5
432
+ type: :runtime
433
+ prerelease: false
434
+ version_requirements: !ruby/object:Gem::Requirement
435
+ requirements:
436
+ - - "~>"
437
+ - !ruby/object:Gem::Version
438
+ version: '1.0'
439
+ - - ">="
440
+ - !ruby/object:Gem::Version
441
+ version: 1.0.5
422
442
  - !ruby/object:Gem::Dependency
423
443
  name: sqlite3
424
444
  requirement: !ruby/object:Gem::Requirement
@@ -567,8 +587,6 @@ files:
567
587
  - app/models/concerns/storable/config.rb
568
588
  - app/models/concerns/taggable.rb
569
589
  - app/models/concerns/translatable.rb
570
- - app/models/concerns/translatable/collection.rb
571
- - app/models/concerns/translatable/config.rb
572
590
  - app/models/concerns/visible.rb
573
591
  - app/models/content_column.rb
574
592
  - app/models/content_image.rb
@@ -594,7 +612,6 @@ files:
594
612
  - app/models/store.rb
595
613
  - app/models/tag.rb
596
614
  - app/models/tagged_item.rb
597
- - app/models/translation.rb
598
615
  - app/uploaders/ckeditor_attachment_file_uploader.rb
599
616
  - app/uploaders/ckeditor_picture_uploader.rb
600
617
  - app/uploaders/content_image_uploader.rb
@@ -663,6 +680,8 @@ files:
663
680
  - config/initializers/simple_form_bootstrap.rb
664
681
  - config/locales/de.yml
665
682
  - config/locales/en.yml
683
+ - config/locales/en_backend.yml
684
+ - config/locales/en_forms.yml
666
685
  - config/locales/fr.yml
667
686
  - config/locales/nl.yml
668
687
  - config/locales/nl_backend.yml
@@ -725,6 +744,9 @@ files:
725
744
  - db/migrate/20160205132009_reoraganize_snippet_html_fields.rb
726
745
  - db/migrate/20160303141417_add_data_to_logs.rb
727
746
  - db/migrate/20160513110925_addd_more_column_widths.rb
747
+ - db/migrate/20160601111729_add_collection_to_store.rb
748
+ - db/migrate/20160601115312_remove_klass_from_stores.rb
749
+ - db/migrate/20160601200049_remove_translation_model.rb
728
750
  - lib/generators/udongo/form/form_generator.rb
729
751
  - lib/generators/udongo/form/templates/form.rb
730
752
  - lib/tasks/task_extras.rb
@@ -1,60 +0,0 @@
1
- module Concerns
2
- module Translatable
3
- class Collection
4
- def initialize(parent, config, locale)
5
- @parent = parent
6
- @config = config
7
- @locale = locale
8
- @translations = {}
9
- end
10
-
11
- def method_missing(method_sym, *arguments, &block)
12
- ascii_name = method_sym.to_s.gsub('=', '').to_sym
13
-
14
- if @config.fields.include?(ascii_name)
15
- if method_sym.to_s.include?('=')
16
- write(ascii_name, arguments.first)
17
- else
18
- read(method_sym)
19
- end
20
- else
21
- super
22
- end
23
- end
24
-
25
- def read(field)
26
- init_field(field.to_sym)
27
- @translations[field.to_sym].value
28
- end
29
-
30
- def write(field, value)
31
- init_field(field.to_sym)
32
- @translations[field.to_sym].value = value
33
- end
34
-
35
- def save
36
- @translations.map { |field,object| object.save }
37
-
38
- @parent.update_attribute(
39
- :locales,
40
- @parent.translations.where.not(value: nil).pluck(:locale).uniq.sort
41
- )
42
- end
43
-
44
- private
45
-
46
- def init_field(field)
47
- unless @translations[field.to_sym]
48
- raise "The field '#{field.to_s}' is not allowed." unless @config.allowed?(field)
49
-
50
- @translations[field] = Translation.find_or_create_by!(
51
- translatable_type: @parent.class.name,
52
- translatable_id: @parent.id,
53
- locale: @locale,
54
- name: field
55
- )
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,19 +0,0 @@
1
- module Concerns
2
- module Translatable
3
- class Config
4
- attr_reader :fields
5
-
6
- def initialize
7
- @fields = []
8
- end
9
-
10
- def add(field)
11
- @fields << field.to_sym unless @fields.include?(field.to_sym)
12
- end
13
-
14
- def allowed?(field)
15
- @fields.include?(field.to_sym)
16
- end
17
- end
18
- end
19
- end
@@ -1,10 +0,0 @@
1
- class Translation < ActiveRecord::Base
2
- include Concerns::Locale
3
-
4
- belongs_to :translatable, polymorphic: true, touch: true
5
-
6
- validates :locale, :name, presence: true
7
- validates :name,
8
- uniqueness: { case_sensitive: false,
9
- scope: [:translatable_type, :translatable_id, :locale] }
10
- end