property_sets 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -6,112 +6,131 @@ This gem is a way for you to use a basic "key/value" store for storing attribute
6
6
 
7
7
  You configure the allowed stored properties by specifying these in the model:
8
8
 
9
- class Account < ActiveRecord::Base
10
- property_set :settings do
11
- property :version, :default => "v1.0"
12
- property :featured, :protected => true
13
- property :activated
14
- end
15
-
16
- property_set :texts do
17
- property :epilogue
18
- end
19
- end
9
+ ```ruby
10
+ class Account < ActiveRecord::Base
11
+ property_set :settings do
12
+ property :version, :default => "v1.0"
13
+ property :featured, :protected => true
14
+ property :activated
15
+ end
16
+
17
+ property_set :texts do
18
+ property :epilogue
19
+ end
20
+ end
21
+ ```
20
22
 
21
23
  The declared properties can then be accessed runtime via the defined association:
22
24
 
23
- # Return the value of the version record for this account, or the default value if not set
24
- account.settings.version
25
+ ```ruby
26
+ # Return the value of the version record for this account, or the default value if not set
27
+ account.settings.version
25
28
 
26
- # Update the version record with given value
27
- account.settings.version = "v1.1"
29
+ # Update the version record with given value
30
+ account.settings.version = "v1.1"
28
31
 
29
- # Query the truth value of the property
30
- account.settings.featured?
32
+ # Query the truth value of the property
33
+ account.settings.featured?
31
34
 
32
- # Short hand for setting one or more values
33
- account.settings.set(:version => "v1.2", :activated => true)
35
+ # Short hand for setting one or more values
36
+ account.settings.set(:version => "v1.2", :activated => true)
37
+ ```
34
38
 
35
39
  ### Validations
36
40
 
37
41
  Property sets supports standard AR validations, although in a somewhat manual fashion.
38
42
 
39
- class Account < ActiveRecord::Base
40
- property_set :settings do
41
- property :version, :default => "v1.0"
42
- property :featured, :protected => true
43
+ ```ruby
44
+ class Account < ActiveRecord::Base
45
+ property_set :settings do
46
+ property :version, :default => "v1.0"
47
+ property :featured, :protected => true
43
48
 
44
- validates_format_of :value, :with => /v\d+\.\d+/, :message => "of version is invalid",
45
- :if => Proc.new { |r| r.name.to_sym == :version }
46
- end
47
- end
49
+ validates_format_of :value, :with => /v\d+\.\d+/, :message => "of version is invalid",
50
+ :if => Proc.new { |r| r.name.to_sym == :version }
51
+ end
52
+ end
53
+ ```
48
54
 
49
- On +account.save+ this will result in an error record being added. You can also inspect the
50
- setting record using +account.settings.version_record+
55
+ On `account.save` this will result in an error record being added. You can also inspect the
56
+ setting record using `account.settings.version_record`
51
57
 
52
58
  ### Bulk operations
53
59
 
54
60
  Stored properties can also be updated with the update_attributes and update_attributes! methods by
55
61
  enabling nested attributes. Like this (from the test cases):
56
62
 
57
- @account.texts_attributes = [
58
- { :name => "foo", :value => "1" },
59
- { :name => "bar", :value => "0" }
60
- ]
63
+ ```ruby
64
+ @account.texts_attributes = [
65
+ { :name => "foo", :value => "1" },
66
+ { :name => "bar", :value => "0" }
67
+ ]
68
+ ```
61
69
 
62
70
  And for existing records:
63
71
 
64
- @account.update_attributes!(:texts_attributes => [
65
- { :id => @account.texts.foo.id, :name => "foo", :value => "0" },
66
- { :id => @account.texts.bar.id, :name => "bar", :value => "1" }
67
- ])
72
+ ```ruby
73
+ @account.update_attributes!(:texts_attributes => [
74
+ { :id => @account.texts.foo.id, :name => "foo", :value => "0" },
75
+ { :id => @account.texts.bar.id, :name => "bar", :value => "1" }
76
+ ])
77
+ ```
68
78
 
69
79
  Using nested attributes is subject to implementing your own security measures for mass update assignments.
70
80
  Alternatively, it is possible to use a custom hash structure:
71
81
 
72
- params = {
73
- :settings => { :version => "v4.0", :featured => "1" },
74
- :texts => { :epilogue => "Wibble wobble" }
75
- }
76
- @account.update_attributes(params)
82
+ ```ruby
83
+ params = {
84
+ :settings => { :version => "v4.0", :featured => "1" },
85
+ :texts => { :epilogue => "Wibble wobble" }
86
+ }
77
87
 
78
- The above will not update +featured+ as this has the protected flag set and is hence protected from
88
+ @account.update_attributes(params)
89
+ ```
90
+
91
+ The above will not update `featured` as this has the protected flag set and is hence protected from
79
92
  mass updates.
80
93
 
81
94
  ### View helpers
82
95
 
83
96
  We support a couple of convenience mechanisms for building forms and putting the values into the above hash structure. So far, only support check boxes and radio buttons:
84
97
 
85
- <% form_for(:account, :html => { :method => :put }) do |f| %>
86
- <h3><%= f.property_set(:settings).check_box :activated %> Activated?</h3>
87
- <h3><%= f.property_set(:settings).radio_button :hot, "yes" %> Hot</h3>
88
- <h3><%= f.property_set(:settings).radio_button :not, "no" %> Not</h3>
89
- <h3><%= f.property_set(:settings).select :level, [["One", 1], ["Two", 2]] %></h3>
90
- <% end %>
98
+ ```erb
99
+ <% form_for(:account, :html => { :method => :put }) do |f| %>
100
+ <h3><%= f.property_set(:settings).check_box :activated %> Activated?</h3>
101
+ <h3><%= f.property_set(:settings).radio_button :hot, "yes" %> Hot</h3>
102
+ <h3><%= f.property_set(:settings).radio_button :not, "no" %> Not</h3>
103
+ <h3><%= f.property_set(:settings).select :level, [["One", 1], ["Two", 2]] %></h3>
104
+ <% end %>
105
+ ```
91
106
 
92
107
  ## Installation
93
108
 
94
109
  Install the gem in your rails project by putting it in your Gemfile:
95
110
 
96
- gem "property_sets"
111
+ ```
112
+ gem "property_sets"
113
+ ```
97
114
 
98
115
  Also remember to create the storage table(s), if for example you are going to be using this with an accounts model and a "settings" property set, you can define the table like:
99
116
 
100
- create_table :account_settings do |t|
101
- t.integer :account_id, :null => false
102
- t.string :name, :null => false
103
- t.string :value
104
- t.timestamps
105
- end
117
+ ```ruby
118
+ create_table :account_settings do |t|
119
+ t.integer :account_id, :null => false
120
+ t.string :name, :null => false
121
+ t.string :value
122
+ t.timestamps
123
+ end
106
124
 
107
- add_index :account_settings, [ :account_id, :name ], :unique => true
125
+ add_index :account_settings, [ :account_id, :name ], :unique => true
126
+ ```
108
127
 
109
128
  ## Requirements
110
129
 
111
130
  * ActiveRecord
112
131
  * ActiveSupport
113
132
 
114
- ## License
133
+ ## License and copyright
115
134
 
116
135
  Copyright 2013 Zendesk
117
136
 
@@ -4,14 +4,13 @@ module ActionView
4
4
  module Helpers
5
5
  class FormBuilder
6
6
  class PropertySetFormBuilderProxy
7
- attr_accessor :property_set
8
- attr_accessor :template
9
- attr_accessor :object_name
10
-
11
- def initialize(property_set, template, object_name)
12
- self.property_set = property_set
13
- self.template = template
14
- self.object_name = object_name
7
+ attr_reader :property_set, :template, :object_name, :object
8
+
9
+ def initialize(property_set, template, object_name, object)
10
+ @property_set = property_set
11
+ @template = template
12
+ @object_name = object_name
13
+ @object = object
15
14
  end
16
15
 
17
16
  def check_box(property, options = {}, checked_value = "1", unchecked_value = "0")
@@ -46,29 +45,33 @@ module ActionView
46
45
  template.select("#{object_name}[#{property_set}]", property, choices, { :selected => current_value }, html_options )
47
46
  end
48
47
 
48
+ private
49
+
49
50
  def prepare_id_name(property, options)
50
51
  throw "Invalid options type #{options.inspect}" unless options.is_a?(Hash)
51
52
 
52
53
  options.clone.tap do |prepared_options|
53
- instance = template.instance_variable_get("@#{object_name}")
54
-
55
- throw "No @#{object_name} in scope" if instance.nil?
56
- throw "The property_set_check_box only works on models with property set #{property_set}" unless instance.respond_to?(property_set)
57
-
54
+ prepared_options[:object] = object || fetch_target_object
58
55
  prepared_options[:id] ||= "#{object_name}_#{property_set}_#{property}"
59
56
  prepared_options[:name] = "#{object_name}[#{property_set}][#{property}]"
60
- prepared_options[:object] = instance
61
57
  end
62
58
  end
63
59
 
60
+ def fetch_target_object
61
+ instance = template.instance_variable_get("@#{object_name}")
62
+
63
+ throw "No @#{object_name} in scope" if instance.nil?
64
+ throw "The property_set_check_box only works on models with property set #{property_set}" unless instance.respond_to?(property_set)
65
+
66
+ instance
67
+ end
68
+
64
69
  def prepare_options(property, options, &block)
65
70
  options = prepare_id_name(property, options)
66
71
  options[:checked] = yield(options[:object].send(property_set))
67
72
  options
68
73
  end
69
74
 
70
- private
71
-
72
75
  def cast_boolean(value)
73
76
  case value
74
77
  when TrueClass then '1'
@@ -80,7 +83,7 @@ module ActionView
80
83
  end
81
84
 
82
85
  def property_set(identifier)
83
- PropertySetFormBuilderProxy.new(identifier, @template, @object_name)
86
+ PropertySetFormBuilderProxy.new(identifier, @template, object_name, object)
84
87
  end
85
88
 
86
89
  end
@@ -1,4 +1,4 @@
1
- Gem::Specification.new "property_sets", "1.0.4" do |s|
1
+ Gem::Specification.new "property_sets", "1.0.5" do |s|
2
2
  s.summary = "Property sets for ActiveRecord."
3
3
  s.description = "This gem is an ActiveRecord extension which provides a convenient interface for managing per row properties."
4
4
  s.authors = ["Morten Primdahl"]
@@ -11,8 +11,6 @@ class TestViewExtensions < ActiveSupport::TestCase
11
11
  @template = stub
12
12
  @builder = ActionView::Helpers::FormBuilder.new(@object_name, @object, @template, {}, 'proc')
13
13
  @proxy = @builder.property_set(@property_set)
14
-
15
- @template.stubs(:instance_variable_get).with("@#{@object_name}").returns(@object)
16
14
  end
17
15
 
18
16
  should "provide a form builder proxy" do
@@ -20,6 +18,17 @@ class TestViewExtensions < ActiveSupport::TestCase
20
18
  assert_equal @property_set, @proxy.property_set
21
19
  end
22
20
 
21
+ should "fetch the target object when not available" do
22
+ @builder = ActionView::Helpers::FormBuilder.new(@object_name, nil, @template, {}, 'proc')
23
+ @proxy = @builder.property_set(@property_set)
24
+
25
+ @object.stubs(@property_set).returns(stub(@property => 'value'))
26
+ @template.stubs(:hidden_field)
27
+
28
+ @template.expects(:instance_variable_get).with("@#{@object_name}").returns(@object)
29
+ @proxy.hidden_field(@property)
30
+ end
31
+
23
32
  context "#check_box" do
24
33
  context "when called with checked true for a truth value" do
25
34
  setup do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: property_sets
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-09 00:00:00.000000000 Z
12
+ date: 2013-04-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport