dynabute 0.0.14 → 0.0.15

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
- SHA1:
3
- metadata.gz: e500db1ec87147a5c3b98c618a0565fcd6d5d5df
4
- data.tar.gz: c86dd66d2800a4f0a12e427517b7dc9bd9649bfa
2
+ SHA256:
3
+ metadata.gz: e2f0aa518cab55eb4e4f2530660132ab9719b5ecb751f556d338662fb0668157
4
+ data.tar.gz: 3890334d7ff87796ec5c8e9f6bda8e219377a082de93854ea14930384eace26b
5
5
  SHA512:
6
- metadata.gz: 82e3ba478d55bf152caeb557d5270a4cbc3c747e1c668784443fac2dd0fb80186a49966271bd2391a03c0fd4958d1548add8da7d0ba644f5723c9cefca0fefea
7
- data.tar.gz: 18fe68bafa50280d9115d9a2e96a08910bae149d0cc620f15dc91baa537b79b334194a6b97d8ae2f2e7fb9908bf956ec517d335f84327977a32b53775a4c4ad4
6
+ metadata.gz: 95015958c27c3de3af3d286440ec71d463bd0e517099eb1be4128f347c75e2bc22dff339e3e09ffe5062f29271a17b041a9cb5ba29f70433842232c58642eb3d
7
+ data.tar.gz: cb46b6dca7dc04ce5362b85313d1d8665cc4273fe6ea78b0622332ffe29ebe393ad40d2df34af179d53992218082233ecf9ff416906b066898c712e1a6b7d0af
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Dynabute
2
- Dynamically add attributes on Relational Database backed ActiveRecord, without hash serialization and bullshits
2
+ Dynamically add attributes on Relational Database backed ActiveRecord, without hash serialization and bullshits.
3
+
4
+ Try messing with a [working demo](https://dynabute-demo.herokuapp.com).
3
5
 
4
6
  ## Usage
5
7
 
@@ -12,17 +14,17 @@ end
12
14
 
13
15
  then add some field definitions
14
16
  ```ruby
15
- User.dynabutes << Dynabute::Field.new( name: 'age', value_type: 'integer' )
16
- User.dynabutes << Dynabute::Field.new( name: 'skinny', value_type: 'boolean' )
17
- User.dynabutes << Dynabute::Field.new( name: 'personalities', value_type: 'string', has_many: true )
17
+ User.dynabutes.create( name: 'age', value_type: 'integer' )
18
+ User.dynabutes.create( name: 'skinny', value_type: 'boolean' )
19
+ User.dynabutes.create( name: 'personalities', value_type: 'string', has_many: true )
18
20
  ```
19
21
 
20
22
  now set value
21
23
  ```ruby
22
24
  user = User.create
23
25
 
24
- user.build_dynabute_value( name: 'age', value: 35 ).save
25
- # => <Dynabute::Values::IntegerValue:0x007faba5279540 id: 1, field_id: 1, dynabutable_id: 1, dynabutable_type: "User", value: 35>
26
+ user.set_dynabute_value( name: 'age', value: 35 ).save
27
+ # => true
26
28
  ```
27
29
 
28
30
  check the value
@@ -50,13 +52,13 @@ user.update(
50
52
  )
51
53
  ```
52
54
 
53
- `select` value_type is also available
55
+ `select` value_type is also available
54
56
  ```ruby
55
- User.dynabutes << Dynabute::Field.new( name: 'gender', value_type: 'select', options_attributes: [ { label: 'male' }, { label: 'female' } ] )
56
- User.dynabutes << Dynabute::Field.new( name: 'hobbies', has_many: true, value_type: 'select', options_attributes: [ { label: 'running' }, { label: 'swimming' }, { label: 'hiking' } ] )
57
+ User.dynabutes.create( name: 'gender', value_type: 'select', options_attributes: [ { label: 'male' }, { label: 'female' } ] )
58
+ User.dynabutes.create( name: 'hobbies', has_many: true, value_type: 'select', options_attributes: [ { label: 'running' }, { label: 'swimming' }, { label: 'hiking' } ] )
57
59
  ```
58
60
 
59
- list the available options for a field
61
+ list the available options for a field
60
62
  ```ruby
61
63
  User.dynabutes.find_by(name: gender).options
62
64
  # => [#<Dynabute::Option:0x007ff53e2e1f90 id: 1, field_id: 4, label: "male">,
@@ -74,7 +76,7 @@ user.update(dynabute_values_attributes: [
74
76
  { name: 'hobbies', value: hobbies[1].id }
75
77
  ])
76
78
  ```
77
-
79
+
78
80
  check out the selected options
79
81
  ```ruby
80
82
  user.dynabute_value(name: 'gender').option
@@ -84,7 +86,16 @@ user.dynabute_value(name: 'hobbies').map(&:option)
84
86
  # => [#<Dynabute::Option:0x007fb26c4467d8 id: 5, field_id: 5, label: "running">,
85
87
  # #<Dynabute::Option:0x007fb26c446238 id: 6, field_id: 5, label: "swimming">]
86
88
  ```
87
-
89
+
90
+ remove value
91
+
92
+ ```
93
+ user.remove_dynabute_value(name: 'age')
94
+ # => #<Dynabute::Values::StringValue:0x0000 ... dynabutable_type: "User", value: 35>
95
+ ```
96
+
97
+
98
+
88
99
  ## Installation
89
100
  Add this line to your application's Gemfile:
90
101
 
@@ -98,9 +109,22 @@ $ bundle install
98
109
  $ rails generate dynabute:install
99
110
  $ rake db:migrate
100
111
  ```
112
+ ## Contributors
113
+
114
+ [<img src="https://github.com/CrAsH1101.png" width="60px;"/><br /><sub><a href="https://github.com/CrAsH1101">CrAsH1101</a></sub>](https://github.com/CrAsH1101)
101
115
 
102
116
  ## Contributing
103
- yea?
117
+
118
+ #### Rspec: set test environment
119
+ ```bash
120
+ $ bundle install
121
+ $ cd spec/dummy/
122
+ $ RAILS_ENV=test bundle exec rake db:create
123
+ $ RAILS_ENV=test bundle exec rake db:migrate
124
+ $ cd ../../
125
+ $ bundle exec rspec
126
+ ```
127
+
104
128
 
105
129
  ## License
106
130
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -4,6 +4,7 @@ require 'dynabute/nested_attributes'
4
4
 
5
5
  module Dynabute
6
6
  module Dynabutable
7
+ class ValueNotFound < StandardError; end
7
8
  extend ActiveSupport::Concern
8
9
 
9
10
  included do
@@ -11,7 +12,7 @@ module Dynabute
11
12
  include NestedAttributes::API
12
13
 
13
14
  (Dynabute::Field::TYPES).each do |t|
14
- has_many Util.value_relation_name(t), class_name: Util.value_class_name(t), as: :dynabutable, inverse_of: 'dynabutable'
15
+ has_many Util.value_relation_name(t), class_name: Util.value_class_name(t), as: :dynabutable, inverse_of: 'dynabutable', dependent: :delete_all
15
16
  accepts_nested_attributes_for Util.value_relation_name(t), reject_if: proc{ |param| param[:value].blank? }, allow_destroy: true
16
17
  end
17
18
 
@@ -36,18 +37,73 @@ module Dynabute
36
37
  end
37
38
 
38
39
  def dynabute_value(name: nil, field_id: nil, field: nil)
39
- field = find_field(name, field_id, field)
40
-
41
- if field.has_many
42
- send(Util.value_relation_name(field.value_type)).select{|v| v.field_id == field.id }
40
+ field_obj = find_field(name, field_id, field)
41
+ field_values = send(Util.value_relation_name(field_obj.value_type))
42
+ field_value = if field_obj.has_many
43
+ field_values.select{ |v| v.field_id == field_obj.id }
43
44
  else
44
- send(Util.value_relation_name(field.value_type)).detect{|v| v.field_id == field.id }
45
+ field_values.detect{ |v| v.field_id == field_obj.id }
45
46
  end
47
+ field_value
46
48
  end
47
49
 
48
50
  def build_dynabute_value(name: nil, field_id: nil, field: nil, **rest)
49
- field = find_field(name, field_id, field)
50
- send(Util.value_relation_name(field.value_type)).build(field_id: field.id, **rest)
51
+ field_obj = find_field(name, field_id, field)
52
+ send(Util.value_relation_name(field_obj.value_type)).build(field_id: field_obj.id, **rest)
53
+ end
54
+
55
+ # Returns value attribute for specified field.
56
+ # If field can have multiple values for single target model object,
57
+ # an array of values is returned, unless specific value_id is provided.
58
+ def get_dynabute_value(name: nil, field_id: nil, field: nil, value_id: nil)
59
+ field_obj = find_field(name, field_id, field)
60
+ value_obj = dynabute_value(field: field_obj)
61
+ return unless value_obj
62
+ if field_obj.has_many && value_id
63
+ value_obj = value_obj.detect{|v| v.id == value_id}
64
+ end
65
+ value_obj.is_a?(Array) ? value_obj.map(&:value) : value_obj&.value
66
+ end
67
+
68
+ # Sets the value in the target model object nested attribute structure.
69
+ # If field can have multiple values for single target model object,
70
+ # a new value will be added, unless specific value_id is provided.
71
+ #
72
+ # This method does not store changes in the database. "save" method should
73
+ # be called on target model to store all changes, or individually on every
74
+ # value record returned by this method.
75
+ def set_dynabute_value(name: nil, field_id: nil, field: nil, value: nil, value_id: nil)
76
+ field_obj = find_field(name, field_id, field)
77
+ value_obj = dynabute_value(field: field_obj)
78
+ if field_obj.has_many
79
+ if value_id
80
+ value_obj = value_obj.detect{|v| v.id == value_id} if value_obj
81
+ fail ValueNotFound unless value_obj
82
+ else
83
+ value_obj = build_dynabute_value(field: field_obj)
84
+ end
85
+ else
86
+ value_obj ||= build_dynabute_value(field: field_obj)
87
+ end
88
+ value_obj.value = value
89
+ value_obj
90
+ end
91
+
92
+ # Removes value from database and keeps dynabute relations up-to-date.
93
+ # If field can have multiple values for single target model object,
94
+ # all values will be removed, unless specific value_id is provided.
95
+ #
96
+ # This method stores changes in the database
97
+ def remove_dynabute_value(name: nil, field_id: nil, field: nil, value_id: nil)
98
+ field_obj = find_field(name, field_id, field)
99
+ value_obj = dynabute_value(field: field_obj)
100
+ if value_obj && field_obj.has_many && value_id
101
+ value_obj = value_obj.detect{|v| v.id == value_id}
102
+ end
103
+ if value_obj
104
+ result_obj = send(Util.value_relation_name(field_obj.value_type)).destroy(value_obj)
105
+ value_obj.is_a?(Array) ? result_obj : result_obj.first
106
+ end
51
107
  end
52
108
 
53
109
  def method_missing(*args)
@@ -63,11 +119,34 @@ module Dynabute
63
119
  end
64
120
 
65
121
  private
122
+
66
123
  def find_field(name, id, field)
67
- name_or_id = {name: name, id: id}.compact
68
- return nil if name_or_id.blank? && field.blank?
69
- field_obj = field || Dynabute::Field.find_by(name_or_id.merge(target_model: self.class.to_s))
70
- fail Dynabute::FieldNotFound.new(name_or_id, field) if field_obj.nil?
124
+ # Validate field argument
125
+ if field
126
+ unless field.is_a?(Dynabute::Field)
127
+ fail ArgumentError, 'Argument field must be Dynabute::Field'
128
+ end
129
+ return field
130
+ end
131
+ name_or_id = {}
132
+ # Validate name argument
133
+ if name
134
+ unless name.is_a?(String) || name.is_a?(Symbol)
135
+ fail ArgumentError, 'Argument name must be String or Symbol'
136
+ end
137
+ name_or_id[:name] = name.to_s
138
+ end
139
+ # Validate id argument
140
+ if id
141
+ unless id.is_a?(Integer)
142
+ fail ArgumentError, 'Argument id must be Integer'
143
+ end
144
+ name_or_id[:id] = id
145
+ end
146
+ name_or_id.reject!{ |k, v| v.blank? }
147
+ fail ArgumentError, 'Invalid arguments' if name_or_id.blank?
148
+ field_obj = Dynabute::Field.find_by(name_or_id.merge(target_model: self.class.to_s))
149
+ fail Dynabute::FieldNotFound.new(name_or_id) if field_obj.nil?
71
150
  field_obj
72
151
  end
73
152
 
@@ -22,15 +22,6 @@ module Dynabute
22
22
  TYPES
23
23
  end
24
24
 
25
- def self.<<(records)
26
- if records.respond_to? :each
27
- records.each {|r| r.update!(target_model: get_parent_class_name) }
28
- else
29
- records.update!(target_model: get_parent_class_name)
30
- end
31
- all
32
- end
33
-
34
25
  private
35
26
  def self.get_parent_class_name
36
27
  all.where_clause.binds.detect{|w| w.name == 'target_model'}.try(:value)
data/lib/dynabute/util.rb CHANGED
@@ -5,7 +5,7 @@ module Dynabute
5
5
  return -> {
6
6
  attr = id_attr.to_sym
7
7
  if (persisted? && self[attr].nil?) || (new_record? && send(id_relation_accessor).nil?)
8
- errors[attr] << I18n.t('errors.messages.blank')
8
+ errors.add(attr, I18n.t('errors.messages.blank'))
9
9
  return fail(:abort) if(halt)
10
10
  end
11
11
  }
@@ -21,7 +21,7 @@ module Dynabute::Values
21
21
  def reject_duplication_for_has_one
22
22
  return if field.has_many
23
23
  return unless self.class.exists?(field_id: field_id, dynabutable_id: dynabutable_id, dynabutable_type: dynabutable_type)
24
- self.errors[:base] << 'Multiple records for has_one relationship detected'
24
+ self.errors.add(:base, 'Multiple records for has_one relationship detected')
25
25
  throw :abort
26
26
  end
27
27
  end
@@ -7,8 +7,9 @@ module Dynabute
7
7
 
8
8
  def ensure_option_is_in_same_field
9
9
  if option && (option.field_id != field_id)
10
- errors[:value] << I18n.t('errors.messages.dynabutes.wrong_field_option',
11
- default: 'is pointing to the option for other dynabute field')
10
+ errors.add(:value, I18n.t('errors.messages.dynabutes.wrong_field_option',
11
+ default: 'is pointing to the option for other dynabute field')
12
+ )
12
13
  end
13
14
  end
14
15
 
@@ -1,3 +1,3 @@
1
1
  module Dynabute
2
- VERSION = '0.0.14'
2
+ VERSION = '0.0.15'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynabute
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liooo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-02 00:00:00.000000000 Z
11
+ date: 2025-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '5'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '5'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sqlite3
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: rspec-rails
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '5'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '5'
97
97
  description: Dynamically add attributes on ActiveRecord.
98
98
  email:
99
99
  - ryoyamada3@gmail.com
@@ -141,8 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  - !ruby/object:Gem::Version
142
142
  version: '0'
143
143
  requirements: []
144
- rubyforge_project:
145
- rubygems_version: 2.6.12
144
+ rubygems_version: 3.0.3.1
146
145
  signing_key:
147
146
  specification_version: 4
148
147
  summary: DYNAmic attriBUTEs for ActiveRecord