dynabute 0.0.3 → 0.0.4

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: edc3d0e7b6d1de057c81eee5df5be4b2d9d2b449
4
- data.tar.gz: 348d882a6cbc060a772d072a19f5f472f40cd792
3
+ metadata.gz: 910b9f2ed8ac706b8282dbb275c7fd0fa8211187
4
+ data.tar.gz: 41b543b260362e618c069e4e45710f8aab029ed2
5
5
  SHA512:
6
- metadata.gz: 8254f230e971e306d577cfa962daba8bf60a1138d88fd4508834fe301012ba6beb62aa004c01a1c700d6e95aa234a715a4bdf9003e294a67f541fddddeb2b945
7
- data.tar.gz: a19ec2cbf89b9be2004bc04f6a59e62519548f2cb6fbcc9c5ff8c955351cafa3ca693c0b0e89350dc79cbcda6b591afc65cbf9ca82d73a7da57a8c90b9776759
6
+ metadata.gz: 5a52e50202b61a60938286896c32c69e43333461eb45cb73396dc422174b716c2097a1665c5cd1f2f12dc1b26e1a9d9df660307d635bda7fa2871d1d61757e65
7
+ data.tar.gz: 692d24bcc54085516fb9187c55b108c8b8c255fae89bedc1d6203e05b265c850f86333d1c95114d6b606c5f1cc1f847f025d86ce26ef2739ed13867b50e1a42e
data/README.md CHANGED
@@ -14,30 +14,32 @@ then add some field definitions
14
14
  ```ruby
15
15
  User.dynabutes << Dynabute::Field.new( name: 'age', value_type: 'integer' )
16
16
  User.dynabutes << Dynabute::Field.new( name: 'skinny', value_type: 'boolean' )
17
- User.dynabutes << Dynabute::Field.new( name: 'personality', value_type: 'string', has_many: true )
17
+ User.dynabutes << Dynabute::Field.new( name: 'personalities', value_type: 'string', has_many: true )
18
18
  ```
19
19
 
20
20
  now set value
21
21
  ```ruby
22
22
  user = User.create
23
23
 
24
- user.build_dynabute_value( name: 'age' )
25
- # => <Dynabute::Values::IntegerValue:0x007faba5279540 id: nil, field_id: 1, dynabutable_id: 1, dynabutable_type: "User", value: nil>
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
+ ```
26
27
 
27
- user.build_dynabute_value( name: 'age' ).update( value: 35 )
28
+ check the value
29
+ ```ruby
28
30
  user.dynabute_value( name: 'age' ).value
29
- #=> 35
31
+ # => 35
30
32
  ```
31
33
 
32
34
  values can also be referenced by `dynabute_<field name>_value(s)`
33
35
  ```ruby
34
- user.dynabute_age_value
35
- # => <Dynabute::Values::IntegerValue:0x007faba5279540 id: 1, field_id: 1, dynabutable_id: 1, dynabutable_type: "User", value: 35>
36
+ user.dynabute_age_value.value
37
+ # => 35
36
38
  ```
37
39
 
38
40
  nested attributes of glory
39
41
  ```ruby
40
- personality_field_id = User.dynabutes.find_by( name: 'personality' ).id
42
+ personality_field_id = User.dynabutes.find_by( name: 'personalities' ).id
41
43
  user.update(
42
44
  dynabute_values_attributes: [
43
45
  { name: 'age', value: 36 }, #=> tell us which field to update by `name:`
@@ -48,13 +50,39 @@ user.update(
48
50
  )
49
51
  ```
50
52
 
51
- check all dynabute values
53
+ `select` value_type is also available
52
54
  ```ruby
53
- user.dynabute_values
54
- #=> [#<Dynabute::Values::IntegerValue:0x007ff4230e90d8 id: 1, field_id: 1, dynabutable_id: 1, dynabutable_type: "User", value: 36>,
55
- #<Dynabute::Values::BooleanValue:0x007fd03ecb84f8 id: 1, field_id: 2, dynabutable_id: 1, dynabutable_type: "User", value: false>,
56
- #<Dynabute::Values::StringValue:0x007fd03b347ef8 id: 1, field_id: 3, dynabutable_id: 1, dynabutable_type: "User", value: "introverted">,
57
- #<Dynabute::Values::StringValue:0x007fd03e992080 id: 1, field_id: 3, dynabutable_id: 1, dynabutable_type: "User", value: "stingy">]
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
+ ```
58
+
59
+ list the available options for a field
60
+ ```ruby
61
+ User.dynabutes.find_by(name: gender).options
62
+ # => [#<Dynabute::Option:0x007ff53e2e1f90 id: 1, field_id: 4, label: "male">,
63
+ # #<Dynabute::Option:0x007ff53e2e1568 id: 2, field_id: 4, label: "female">]
64
+ ```
65
+
66
+ set value
67
+ ```ruby
68
+ male = User.dynabutes.find_by(name: 'gender').options.find_by(label: 'male')
69
+ hobbies = User.dynabutes.find_by(name: 'hobbies').options
70
+
71
+ user.update(dynabute_values_attributes: [
72
+ { name: 'gender', value: male.id },
73
+ { name: 'hobbies', value: hobbies[0].id },
74
+ { name: 'hobbies', value: hobbies[1].id }
75
+ ])
76
+ ```
77
+
78
+ check out the selected options
79
+ ```ruby
80
+ user.dynabute_value(name: 'gender').option
81
+ # => <Dynabute::Option:0x007ff53e2e1f90 id: 1, field_id: 4, label: "male">,
82
+
83
+ user.dynabute_value(name: 'hobbies').map(&:option)
84
+ # => [#<Dynabute::Option:0x007fb26c4467d8 id: 5, field_id: 5, label: "running">,
85
+ # #<Dynabute::Option:0x007fb26c446238 id: 6, field_id: 5, label: "swimming">]
58
86
  ```
59
87
 
60
88
  ## Installation
@@ -29,8 +29,8 @@ module Dynabute
29
29
 
30
30
  def dynabute_values
31
31
  @dynabute_values ||= dynabute_fields
32
- .group_by{|f| f.value_type}
33
- .map { |type, fields|
32
+ .group_by{|f| f.value_type }
33
+ .map { |_, fields|
34
34
  fields.first.value_class.where(field_id: fields.map(&:id), dynabutable_id: id)
35
35
  }.flatten.compact
36
36
  end
@@ -45,9 +45,9 @@ module Dynabute
45
45
  end
46
46
  end
47
47
 
48
- def build_dynabute_value(name: nil, id: nil, field: nil)
48
+ def build_dynabute_value(name: nil, id: nil, field: nil, **rest)
49
49
  field = find_field(name, id, field)
50
- send(Util.value_relation_name(field.value_type)).build(field_id: field.id)
50
+ send(Util.value_relation_name(field.value_type)).build(field_id: field.id, **rest)
51
51
  end
52
52
 
53
53
  def method_missing(*args)
@@ -4,20 +4,18 @@ require 'dynabute/joins'
4
4
  module Dynabute
5
5
  class Field < ActiveRecord::Base
6
6
  include Joins::Field
7
- def self.table_name_prefix; 'dynabute_'; end
8
-
7
+ def self.table_name_prefix; Util.table_name_prefix; end
9
8
  TYPES = %w(string integer boolean datetime select)
10
9
  validates :value_type, inclusion: {in: TYPES}
11
- scope :for, ->(klass){ where(target_model: klass) }
10
+ validates :name, presence: true, uniqueness: { scope: :target_model }
11
+ validates_presence_of :target_model
12
12
  has_many :options, class_name: 'Dynabute::Option', dependent: :destroy
13
13
  accepts_nested_attributes_for :options, allow_destroy: true
14
- def is_select?
15
- ['select'].include? value_type
16
- end
14
+
15
+ scope :for, ->(klass){ where(target_model: klass) }
17
16
 
18
17
  def value_class
19
- type = is_select? ? :integer : value_type
20
- Util.value_class_name(type).safe_constantize
18
+ Util.value_class_name(value_type).safe_constantize
21
19
  end
22
20
 
23
21
  def self.<<(records)
@@ -15,6 +15,7 @@ module Dynabute
15
15
  collect_fields(@attributes_list)
16
16
  @attributes_list.each do |attrs|
17
17
  field = resolve_field(attrs)
18
+ next if field.nil?
18
19
  next let_go(field, attrs) if field.has_many
19
20
  next let_go(field, attrs) if attrs[:id].present?
20
21
  desperados.push([attrs, field])
@@ -1,6 +1,11 @@
1
+ require 'dynabute/util'
2
+
1
3
  module Dynabute
2
4
  class Option < ActiveRecord::Base
3
- belongs_to :dynabute_field, class_name: 'Dynabute::Field'
4
- validates_presence_of :label
5
+ def self.table_name_prefix; Util.table_name_prefix; end
6
+ belongs_to :field, class_name: 'Dynabute::Field'
7
+ has_many :values, class_name: Util.value_class_name(:select), foreign_key: 'value'
8
+ validates :label, presence: true, uniqueness: { scope: ['field_id'] }
9
+ validate Util.nested_attributable_presence_validator(:field_id, :field)
5
10
  end
6
11
  end
data/lib/dynabute/util.rb CHANGED
@@ -1,21 +1,31 @@
1
1
  module Dynabute
2
- module Util
3
- def value_class_name(type)
4
- name = %i(select).include?(type.to_sym) ? :integer : type
5
- "Dynabute::Values::#{name.to_s.classify}Value"
6
- end
7
- module_function :value_class_name
2
+ class Util
3
+ class << self
4
+ def nested_attributable_presence_validator(id_attr, id_relation_accessor, halt: false)
5
+ return -> {
6
+ attr = id_attr.to_sym
7
+ if (persisted? && self[attr].nil?) || (new_record? && send(id_relation_accessor).nil?)
8
+ errors[attr] << I18n.t('errors.messages.blank')
9
+ return fail(:abort) if(halt)
10
+ end
11
+ }
12
+ end
13
+
14
+ def table_name_prefix
15
+ 'dynabute_'
16
+ end
8
17
 
9
- def value_relation_name(type)
10
- %i(select).include?(type.to_sym) ?
11
- :integer_values :
18
+ def value_class_name(type)
19
+ "Dynabute::Values::#{type.to_s.classify}Value"
20
+ end
21
+
22
+ def value_relation_name(type)
12
23
  "#{type}_values".to_sym
13
- end
14
- module_function :value_relation_name
24
+ end
15
25
 
16
- def all_value_relation_names
17
- Dynabute::Field::TYPES.map{|t| Util.value_relation_name(t).uniq }
26
+ def all_value_relation_names
27
+ Dynabute::Field::TYPES.map{|t| Util.value_relation_name(t).uniq }
28
+ end
18
29
  end
19
- module_function :all_value_relation_names
20
30
  end
21
31
  end
@@ -1,14 +1,19 @@
1
+ require 'dynabute/util'
2
+
1
3
  module Dynabute::Values
2
4
  module Base
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- def self.table_name_prefix; 'dynabute_'; end
8
+ def self.table_name_prefix; Dynabute::Util.table_name_prefix; end
7
9
  belongs_to :dynabutable, polymorphic: true
8
- belongs_to :dynabute_field, class_name: 'Dynabute::Field'
10
+ belongs_to :field, class_name: 'Dynabute::Field'
11
+ validate Dynabute::Util.nested_attributable_presence_validator(:field_id, :field)
12
+ validate Dynabute::Util.nested_attributable_presence_validator(:dynabutable_id, :dynabutable)
13
+ validate Dynabute::Util.nested_attributable_presence_validator(:dynabutable_type, :dynabutable)
9
14
 
10
15
  def value_type
11
- dynabute_field.value_type
16
+ field.value_type
12
17
  end
13
18
  end
14
19
 
@@ -0,0 +1,17 @@
1
+ module Dynabute
2
+ module Values
3
+ class SelectValue < ActiveRecord::Base
4
+ include Dynabute::Values::Base
5
+ belongs_to :option, class_name: "Dynabute::Option", foreign_key: 'value'
6
+ validate :ensure_option_is_in_same_field
7
+
8
+ def ensure_option_is_in_same_field
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')
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -3,3 +3,4 @@ require('dynabute/values/boolean_value')
3
3
  require('dynabute/values/datetime_value')
4
4
  require('dynabute/values/integer_value')
5
5
  require('dynabute/values/string_value')
6
+ require('dynabute/values/select_value')
@@ -1,3 +1,3 @@
1
1
  module Dynabute
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
@@ -44,4 +44,19 @@ class CreateDynabutes < ActiveRecord::Migration[5.1]
44
44
  add_index "dynabute_datetime_values", ["dynabutable_id"], name: "dynabute_datetime_values_on_recordable_id", using: :btree
45
45
  add_index "dynabute_datetime_values", ["dynabutable_id", "field_id"], name: "dynabute_datetime_values_on_record_id_and_recordable_id", using: :btree
46
46
  end
47
+
48
+ create_table "dynabute_select_values", force: :cascade do |t|
49
+ t.integer "field_id", limit: 4
50
+ t.integer "dynabutable_id", limit: 4
51
+ t.string "dynabutable_type", limit: 50
52
+ t.integer "value"
53
+ end
54
+ add_index "dynabute_select_values", ["dynabutable_id"], name: "dynabute_select_values_on_recordable_id", using: :btree
55
+ add_index "dynabute_select_values", ["dynabutable_id", "field_id"], name: "dynabute_select_values_on_record_id_and_recordable_id", using: :btree
56
+
57
+ create_table "dynabute_options", force: :cascade do |t|
58
+ t.integer "field_id", limit: 4
59
+ t.string "label"
60
+ t.index ["field_id"], name: "index_dynabute_options_on_field_id"
61
+ end
47
62
  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.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liooo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-25 00:00:00.000000000 Z
11
+ date: 2017-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -116,6 +116,7 @@ files:
116
116
  - lib/dynabute/values/boolean_value.rb
117
117
  - lib/dynabute/values/datetime_value.rb
118
118
  - lib/dynabute/values/integer_value.rb
119
+ - lib/dynabute/values/select_value.rb
119
120
  - lib/dynabute/values/string_value.rb
120
121
  - lib/dynabute/version.rb
121
122
  - lib/generators/dynabute/install_generator.rb