ledermann-rails-settings 2.4.3 → 2.6.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
  SHA256:
3
- metadata.gz: 54028088f04ee8257a762eb477193f71f0e04b3c6a8eddcbc573c8af673dfeb9
4
- data.tar.gz: 6a7de3c087fa34df61adf6e507763fc614ee3f2e7ee76071aacb1feeff8dfba9
3
+ metadata.gz: 525e4533dc661bea55c6e6803a14e977041d3028f84c9242a3507f8056caa6a4
4
+ data.tar.gz: 79f1e5eb504fba6da95b7f3b1d13576851de5e45be5cb1aad941f6a69b025ba9
5
5
  SHA512:
6
- metadata.gz: d39055f26f4772b7195a58f715948ded863581fbc5801bd05439964fa5ea2cf8b50b59f9947ded0ee01ccfd93e7170fe0951cb24155c4474f4e42cb8fdfaef5c
7
- data.tar.gz: 9594e0e206154db02d57ddcdc14088b678b4bb5c128940da0ac61b59145de372fcd915f7242c87cf6785d63c7f96f96e4623259fdb227842d5d11d2ed957e43c
6
+ metadata.gz: 642b112d09ca8c17ac941e7423b35c1bd03d686604219cb0c9f96f7e18791ed2fdf55c98ab4f0e0204aa0a85730968420e5726e82ef663797643c75605410b4e
7
+ data.tar.gz: 1582f37a35eb83b9bba14f9ed34aeb4a0eb1161e66d193584988e46b2cd246ca30f3ac252086e22a62c37fe172118271728606c001f9542b13e41c2b61420d73
@@ -0,0 +1,39 @@
1
+ name: Test
2
+
3
+ on:
4
+ - push
5
+ - pull_request
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ ruby_version:
15
+ - '3.0'
16
+ - '3.1'
17
+ - '3.2'
18
+ gemfile:
19
+ - gemfiles/rails_6_1.gemfile
20
+ - gemfiles/rails_7_0.gemfile
21
+ - gemfiles/rails_7_1.gemfile
22
+
23
+ name: Ruby ${{ matrix.ruby_version }} / Gemfile ${{ matrix.gemfile }}
24
+
25
+ env:
26
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
27
+ COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
28
+
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+
32
+ - name: Setup Ruby
33
+ uses: ruby/setup-ruby@v1
34
+ with:
35
+ ruby-version: ${{ matrix.ruby_version }}
36
+ bundler-cache: true
37
+
38
+ - name: RSpec
39
+ run: bundle exec rake
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2018 Georg Ledermann
1
+ Copyright (c) 2012-2023 Georg Ledermann
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Settings for Rails
2
2
 
3
- [![Build Status](https://travis-ci.org/ledermann/rails-settings.svg?branch=master)](https://travis-ci.org/ledermann/rails-settings)
3
+ [![Build Status](https://github.com/ledermann/rails-settings/actions/workflows/main.yml/badge.svg)](https://github.com/ledermann/rails-settings/actions)
4
4
  [![Code Climate](https://codeclimate.com/github/ledermann/rails-settings.svg)](https://codeclimate.com/github/ledermann/rails-settings)
5
5
  [![Coverage Status](https://coveralls.io/repos/ledermann/rails-settings/badge.svg?branch=master)](https://coveralls.io/r/ledermann/rails-settings?branch=master)
6
6
 
@@ -8,9 +8,8 @@ Ruby gem to handle settings for ActiveRecord instances by storing them as serial
8
8
 
9
9
  ## Requirements
10
10
 
11
- * Ruby 1.9.3 or newer
12
- * Rails 3.1 or newer (including Rails 5.2)
13
-
11
+ - Ruby 3.0 or newer
12
+ - Rails 6.1 or newer (including Rails 7.0)
14
13
 
15
14
  ## Installation
16
15
 
@@ -27,7 +26,6 @@ rails g rails_settings:migration
27
26
  rake db:migrate
28
27
  ```
29
28
 
30
-
31
29
  ## Usage
32
30
 
33
31
  ### Define settings
@@ -65,6 +63,26 @@ class ProjectSettingObject < RailsSettings::SettingObject
65
63
  end
66
64
  ```
67
65
 
66
+ In case you need to define settings separatedly for the same models, you can use the persistent option
67
+
68
+ ```ruby
69
+ module UserDashboardConcern
70
+ extend ActiveSupport::Concern
71
+
72
+ included do
73
+ has_settings persistent: true do |s|
74
+ s.key :dashboard
75
+ end
76
+ end
77
+ end
78
+
79
+ class User < ActiveRecord::Base
80
+ has_settings persistent: true do |s|
81
+ s.key :calendar
82
+ end
83
+ end
84
+ ```
85
+
68
86
  ### Set settings
69
87
 
70
88
  ```ruby
@@ -79,11 +97,10 @@ or
79
97
 
80
98
  ```ruby
81
99
  user = User.find(1)
82
- user.settings(:dashboard).update_attributes! :theme => 'black'
83
- user.settings(:calendar).update_attributes! :scope => 'all', :display => 'daily'
100
+ user.settings(:dashboard).update! :theme => 'black'
101
+ user.settings(:calendar).update! :scope => 'all', :display => 'daily'
84
102
  ```
85
103
 
86
-
87
104
  ### Get settings
88
105
 
89
106
  ```ruby
@@ -102,7 +119,7 @@ user.settings(:calendar).scope
102
119
 
103
120
  ```ruby
104
121
  user = User.find(1)
105
- user.settings(:dashboard).update_attributes! :theme => nil
122
+ user.settings(:dashboard).update! :theme => nil
106
123
 
107
124
  user.settings(:dashboard).view = nil
108
125
  user.settings(:dashboard).save!
@@ -118,13 +135,14 @@ User.without_settings
118
135
  # => all users without having any setting
119
136
 
120
137
  User.with_settings_for(:calendar)
121
- # => all users having a setting for 'calender'
138
+ # => all users having a setting for 'calendar'
122
139
 
123
140
  User.without_settings_for(:calendar)
124
141
  # => all users without having settings for 'calendar'
125
142
  ```
126
143
 
127
144
  ### Eager Loading
145
+
128
146
  ```ruby
129
147
  User.includes(:setting_objects)
130
148
  # => Eager load setting_objects when querying many users
@@ -136,16 +154,14 @@ Version 2 is a complete rewrite and has a new DSL, so it's **not** compatible wi
136
154
 
137
155
  If you don't want to upgrade, you find the old version in the [1.x](https://github.com/ledermann/rails-settings/commits/1.x) branch. But don't expect any updates there.
138
156
 
139
-
140
157
  ## Changelog
141
158
 
142
159
  See https://github.com/ledermann/rails-settings/releases
143
160
 
144
-
145
161
  ## License
146
162
 
147
163
  MIT License
148
164
 
149
- Copyright (c) 2012-2018 [Georg Ledermann](http://www.georg-ledermann.de)
165
+ Copyright (c) 2012-2023 [Georg Ledermann](https://ledermann.dev)
150
166
 
151
167
  This gem is a complete rewrite of [rails-settings](https://github.com/Squeegy/rails-settings) by [Alex Wayne](https://github.com/Squeegy)
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'activerecord', '~> 5.1.0'
3
+ gem 'activerecord', '~> 6.1.2'
4
+ gem "sqlite3", "~> 1.4"
4
5
 
5
6
  gemspec :path => "../"
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'activerecord', '~> 3.1.12'
3
+ gem 'activerecord', '~> 7.0.0'
4
+ gem "sqlite3", "~> 1.4"
4
5
 
5
6
  gemspec :path => "../"
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 7.1.0.beta1'
4
+ gem "sqlite3", "~> 1.4"
5
+
6
+ gemspec :path => "../"
@@ -5,18 +5,19 @@ module RailsSettings
5
5
  class MigrationGenerator < Rails::Generators::Base
6
6
  include Rails::Generators::Migration
7
7
 
8
- desc "Generates migration for rails-settings"
8
+ desc 'Generates migration for rails-settings'
9
9
  source_root File.expand_path('../templates', __FILE__)
10
10
 
11
11
  def create_migration_file
12
- migration_template 'migration.rb', 'db/migrate/rails_settings_migration.rb'
12
+ migration_template 'migration.rb',
13
+ 'db/migrate/rails_settings_migration.rb'
13
14
  end
14
15
 
15
16
  def self.next_migration_number(dirname)
16
17
  if ActiveRecord::Base.timestamped_migrations
17
- Time.now.utc.strftime("%Y%m%d%H%M%S")
18
+ Time.now.utc.strftime('%Y%m%d%H%M%S')
18
19
  else
19
- "%.3d" % (current_migration_number(dirname) + 1)
20
+ '%.3d' % (current_migration_number(dirname) + 1)
20
21
  end
21
22
  end
22
23
  end
@@ -1,18 +1,12 @@
1
- MIGRATION_BASE_CLASS = if ActiveRecord::VERSION::MAJOR >= 5
2
- ActiveRecord::Migration[5.0]
3
- else
4
- ActiveRecord::Migration
5
- end
6
-
7
- class RailsSettingsMigration < MIGRATION_BASE_CLASS
1
+ class RailsSettingsMigration < ActiveRecord::Migration[5.0]
8
2
  def self.up
9
3
  create_table :settings do |t|
10
- t.string :var, :null => false
11
- t.text :value
12
- t.references :target, :null => false, :polymorphic => true
13
- t.timestamps :null => true
4
+ t.string :var, null: false
5
+ t.text :value
6
+ t.references :target, null: false, polymorphic: true
7
+ t.timestamps null: true
14
8
  end
15
- add_index :settings, [ :target_type, :target_id, :var ], :unique => true
9
+ add_index :settings, %i[target_type target_id var], unique: true
16
10
  end
17
11
 
18
12
  def self.down
@@ -3,19 +3,23 @@ module RailsSettings
3
3
  def self.included(base)
4
4
  base.class_eval do
5
5
  has_many :setting_objects,
6
- :as => :target,
7
- :autosave => true,
8
- :dependent => :delete_all,
9
- :class_name => self.setting_object_class_name
6
+ as: :target,
7
+ autosave: true,
8
+ dependent: :delete_all,
9
+ class_name: self.setting_object_class_name
10
10
 
11
11
  def settings(var)
12
12
  raise ArgumentError unless var.is_a?(Symbol)
13
- raise ArgumentError.new("Unknown key: #{var}") unless self.class.default_settings[var]
13
+ unless self.class.default_settings[var]
14
+ raise ArgumentError.new("Unknown key: #{var}")
15
+ end
14
16
 
15
17
  if RailsSettings.can_protect_attributes?
16
- setting_objects.detect { |s| s.var == var.to_s } || setting_objects.build({ :var => var.to_s }, :without_protection => true)
18
+ setting_objects.detect { |s| s.var == var.to_s } ||
19
+ setting_objects.build({ var: var.to_s }, without_protection: true)
17
20
  else
18
- setting_objects.detect { |s| s.var == var.to_s } || setting_objects.build(:var => var.to_s, :target => self)
21
+ setting_objects.detect { |s| s.var == var.to_s } ||
22
+ setting_objects.build(var: var.to_s, target: self)
19
23
  end
20
24
  end
21
25
 
@@ -27,9 +31,12 @@ module RailsSettings
27
31
  end
28
32
  end
29
33
 
30
- def settings?(var=nil)
34
+ def settings?(var = nil)
31
35
  if var.nil?
32
- setting_objects.any? { |setting_object| !setting_object.marked_for_destruction? && setting_object.value.present? }
36
+ setting_objects.any? do |setting_object|
37
+ !setting_object.marked_for_destruction? &&
38
+ setting_object.value.present?
39
+ end
33
40
  else
34
41
  settings(var).value.present?
35
42
  end
@@ -38,7 +45,9 @@ module RailsSettings
38
45
  def to_settings_hash
39
46
  settings_hash = self.class.default_settings.dup
40
47
  settings_hash.each do |var, vals|
41
- settings_hash[var] = settings_hash[var].merge(settings(var.to_sym).value)
48
+ settings_hash[var] = settings_hash[var].merge(
49
+ settings(var.to_sym).value,
50
+ )
42
51
  end
43
52
  settings_hash
44
53
  end
@@ -8,25 +8,45 @@ module RailsSettings
8
8
  raise ArgumentError unless klass
9
9
 
10
10
  @klass = klass
11
- @klass.class_attribute :default_settings, :setting_object_class_name
12
- @klass.default_settings = {}
13
- @klass.setting_object_class_name = options[:class_name] || 'RailsSettings::SettingObject'
11
+
12
+ if options[:persistent]
13
+ unless @klass.methods.include?(:default_settings)
14
+ @klass.class_attribute :default_settings
15
+ end
16
+ else
17
+ @klass.class_attribute :default_settings
18
+ end
19
+
20
+ @klass.class_attribute :setting_object_class_name
21
+ @klass.default_settings ||= {}
22
+ @klass.setting_object_class_name =
23
+ options[:class_name] || 'RailsSettings::SettingObject'
14
24
 
15
25
  if block_given?
16
26
  yield(self)
17
27
  else
18
- keys.each do |k|
19
- key(k)
20
- end
28
+ keys.each { |k| key(k) }
21
29
  end
22
30
 
23
- raise ArgumentError.new('has_settings: No keys defined') if @klass.default_settings.blank?
31
+ if @klass.default_settings.blank?
32
+ raise ArgumentError.new('has_settings: No keys defined')
33
+ end
24
34
  end
25
35
 
26
- def key(name, options={})
27
- raise ArgumentError.new("has_settings: Symbol expected, but got a #{name.class}") unless name.is_a?(Symbol)
28
- raise ArgumentError.new("has_settings: Option :defaults expected, but got #{options.keys.join(', ')}") unless options.blank? || (options.keys == [:defaults])
29
- @klass.default_settings[name] = (options[:defaults] || {}).stringify_keys.freeze
36
+ def key(name, options = {})
37
+ unless name.is_a?(Symbol)
38
+ raise ArgumentError.new(
39
+ "has_settings: Symbol expected, but got a #{name.class}",
40
+ )
41
+ end
42
+ unless options.blank? || (options.keys == [:defaults])
43
+ raise ArgumentError.new(
44
+ "has_settings: Option :defaults expected, but got #{options.keys.join(', ')}",
45
+ )
46
+ end
47
+ @klass.default_settings[name] = (
48
+ options[:defaults] || {}
49
+ ).stringify_keys.freeze
30
50
  end
31
51
  end
32
52
  end
@@ -2,28 +2,27 @@ module RailsSettings
2
2
  module Scopes
3
3
  def with_settings
4
4
  result = joins("INNER JOIN settings ON #{settings_join_condition}")
5
-
6
- if ActiveRecord::VERSION::MAJOR < 5
7
- result.uniq
8
- else
9
- result.distinct
10
- end
5
+ result.distinct
11
6
  end
12
7
 
13
8
  def with_settings_for(var)
14
9
  raise ArgumentError.new('Symbol expected!') unless var.is_a?(Symbol)
15
- joins("INNER JOIN settings ON #{settings_join_condition} AND settings.var = '#{var}'")
10
+ joins(
11
+ "INNER JOIN settings ON #{settings_join_condition} AND settings.var = '#{var}'",
12
+ )
16
13
  end
17
14
 
18
15
  def without_settings
19
- joins("LEFT JOIN settings ON #{settings_join_condition}").
20
- where('settings.id IS NULL')
16
+ joins("LEFT JOIN settings ON #{settings_join_condition}").where(
17
+ 'settings.id IS NULL',
18
+ )
21
19
  end
22
20
 
23
21
  def without_settings_for(var)
24
22
  raise ArgumentError.new('Symbol expected!') unless var.is_a?(Symbol)
25
- joins("LEFT JOIN settings ON #{settings_join_condition} AND settings.var = '#{var}'").
26
- where('settings.id IS NULL')
23
+ joins(
24
+ "LEFT JOIN settings ON #{settings_join_condition} AND settings.var = '#{var}'",
25
+ ).where('settings.id IS NULL')
27
26
  end
28
27
 
29
28
  def settings_join_condition
@@ -2,18 +2,22 @@ module RailsSettings
2
2
  class SettingObject < ActiveRecord::Base
3
3
  self.table_name = 'settings'
4
4
 
5
- belongs_to :target, :polymorphic => true
5
+ belongs_to :target, polymorphic: true
6
6
 
7
7
  validates_presence_of :var, :target_type
8
8
  validate do
9
- errors.add(:value, "Invalid setting value") unless value.is_a? Hash
9
+ errors.add(:value, 'Invalid setting value') unless value.is_a? Hash
10
10
 
11
11
  unless _target_class.default_settings[var.to_sym]
12
12
  errors.add(:var, "#{var} is not defined!")
13
13
  end
14
14
  end
15
15
 
16
- serialize :value, Hash
16
+ if ActiveRecord.version >= Gem::Version.new('7.1.0.beta1')
17
+ serialize :value, type: Hash
18
+ else
19
+ serialize :value, Hash
20
+ end
17
21
 
18
22
  if RailsSettings.can_protect_attributes?
19
23
  # attr_protected can not be used here because it touches the database which is not connected yet.
@@ -21,10 +25,10 @@ module RailsSettings
21
25
  attr_accessible
22
26
  end
23
27
 
24
- REGEX_SETTER = /\A([a-z]\w+)=\Z/i
25
- REGEX_GETTER = /\A([a-z]\w+)\Z/i
28
+ REGEX_SETTER = /\A([a-z]\w*)=\Z/i
29
+ REGEX_GETTER = /\A([a-z]\w*)\Z/i
26
30
 
27
- def respond_to?(method_name, include_priv=false)
31
+ def respond_to?(method_name, include_priv = false)
28
32
  super || method_name.to_s =~ REGEX_SETTER || _setting?(method_name)
29
33
  end
30
34
 
@@ -32,7 +36,7 @@ module RailsSettings
32
36
  if block_given?
33
37
  super
34
38
  else
35
- if attribute_names.include?(method_name.to_s.sub('=',''))
39
+ if attribute_names.include?(method_name.to_s.sub('=', ''))
36
40
  super
37
41
  elsif method_name.to_s =~ REGEX_SETTER && args.size == 1
38
42
  _set_value($1, args.first)
@@ -44,23 +48,48 @@ module RailsSettings
44
48
  end
45
49
  end
46
50
 
47
- protected
51
+ protected
52
+
48
53
  if RailsSettings.can_protect_attributes?
49
54
  # Simulate attr_protected by removing all regular attributes
50
55
  def sanitize_for_mass_assignment(attributes, role = nil)
51
- attributes.except('id', 'var', 'value', 'target_id', 'target_type', 'created_at', 'updated_at')
56
+ attributes.except(
57
+ 'id',
58
+ 'var',
59
+ 'value',
60
+ 'target_id',
61
+ 'target_type',
62
+ 'created_at',
63
+ 'updated_at',
64
+ )
52
65
  end
53
66
  end
54
67
 
55
- private
68
+ private
69
+
56
70
  def _get_value(name)
57
71
  if value[name].nil?
58
- _target_class.default_settings[var.to_sym][name]
72
+ default_value = _get_default_value(name)
73
+ _deep_dup(default_value)
59
74
  else
60
75
  value[name]
61
76
  end
62
77
  end
63
78
 
79
+ def _get_default_value(name)
80
+ default_value = _target_class.default_settings[var.to_sym][name]
81
+
82
+ if default_value.respond_to?(:call)
83
+ default_value.call(target)
84
+ else
85
+ default_value
86
+ end
87
+ end
88
+
89
+ def _deep_dup(nested_hashes_and_or_arrays)
90
+ Marshal.load(Marshal.dump(nested_hashes_and_or_arrays))
91
+ end
92
+
64
93
  def _set_value(name, v)
65
94
  if value[name] != v
66
95
  value_will_change!
@@ -1,3 +1,3 @@
1
1
  module RailsSettings
2
- VERSION = '2.4.3'
2
+ VERSION = '2.6.0'
3
3
  end
@@ -1,9 +1,8 @@
1
1
  module RailsSettings
2
- # In Rails 3, attributes can be protected by `attr_accessible` and `attr_protected`
3
2
  # In Rails 4, attributes can be protected by using the gem `protected_attributes`
4
3
  # In Rails 5, protecting attributes is obsolete (there are `StrongParameters` only)
5
4
  def self.can_protect_attributes?
6
- (ActiveRecord::VERSION::MAJOR == 3) || defined?(ProtectedAttributes)
5
+ defined?(ProtectedAttributes)
7
6
  end
8
7
  end
9
8
 
@@ -20,4 +19,3 @@ ActiveRecord::Base.class_eval do
20
19
  extend RailsSettings::Scopes
21
20
  end
22
21
  end
23
-
@@ -4,26 +4,27 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'rails-settings/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
- gem.name = 'ledermann-rails-settings'
8
- gem.version = RailsSettings::VERSION
9
- gem.licenses = ['MIT']
10
- gem.authors = ['Georg Ledermann']
11
- gem.email = ['mail@georg-ledermann.de']
12
- gem.description = %q{Settings gem for Ruby on Rails}
13
- gem.summary = %q{Ruby gem to handle settings for ActiveRecord instances by storing them as serialized Hash in a separate database table. Namespaces and defaults included.}
14
- gem.homepage = 'https://github.com/ledermann/rails-settings'
15
- gem.required_ruby_version = '>= 1.9.3'
7
+ gem.name = 'ledermann-rails-settings'
8
+ gem.version = RailsSettings::VERSION
9
+ gem.licenses = ['MIT']
10
+ gem.authors = ['Georg Ledermann']
11
+ gem.email = ['georg@ledermann.dev']
12
+ gem.description = 'Settings gem for Ruby on Rails'
13
+ gem.summary =
14
+ 'Ruby gem to handle settings for ActiveRecord instances by storing them as serialized Hash in a separate database table. Namespaces and defaults included.'
15
+ gem.homepage = 'https://github.com/ledermann/rails-settings'
16
+ gem.required_ruby_version = '>= 3.0'
16
17
 
17
- gem.files = `git ls-files`.split($/)
18
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.files = `git ls-files`.split($/)
19
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
20
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
21
  gem.require_paths = ['lib']
21
22
 
22
- gem.add_dependency 'activerecord', '>= 3.1'
23
+ gem.add_dependency 'activerecord', '>= 6.1'
23
24
 
24
25
  gem.add_development_dependency 'rake'
25
26
  gem.add_development_dependency 'sqlite3'
26
27
  gem.add_development_dependency 'rspec'
27
- gem.add_development_dependency 'coveralls'
28
- gem.add_development_dependency 'simplecov', RUBY_VERSION < '2' ? '~> 0.11.2' : '>= 0.11.2'
28
+ gem.add_development_dependency 'coveralls_reborn'
29
+ gem.add_development_dependency 'simplecov', '>= 0.11.2'
29
30
  end