ledermann-rails-settings 2.4.3 → 2.6.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
  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