udongo 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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