plain_old_model 0.1.0 → 0.1.2

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.
@@ -4,17 +4,19 @@ module PlainOldModel
4
4
  module AttributeAssignment
5
5
  module ClassMethods
6
6
  def has_one(attr_name, options={})
7
- if options[:class_name]
8
- associations[attr_name] = options[:class_name].to_s.capitalize unless options[:class_name].nil?
9
- else
10
- associations[attr_name] = attr_name.to_s.capitalize
11
- end
12
- attr_accessor attr_name
7
+ associations << HasOneAssociation.new(attr_name, options)
8
+ attr_accessor attr_name
9
+ end
10
+
11
+ def has_many(attr_name, options={})
12
+ associations << HasManyAssociation.new(attr_name, options)
13
+ attr_accessor attr_name
13
14
  end
14
15
 
15
16
  def associations
16
- @associations ||= {}
17
+ @associations ||= []
17
18
  end
19
+
18
20
  end
19
21
 
20
22
  def self.included(klass)
@@ -23,21 +25,65 @@ module PlainOldModel
23
25
 
24
26
  def assign_attributes(new_attributes, options = {})
25
27
  return unless new_attributes
26
- associations.each do |k, v|
27
- if new_attributes.include?(k)
28
- new_klass = k.to_s.camelcase.constantize.new(new_attributes[k])
28
+ associations.each do |association|
29
+ attr_name = association.attr_name
30
+ if new_attributes.include?(attr_name)
31
+ value = association.create_value_from_attributes(new_attributes[attr_name])
29
32
 
30
- respond_to?("#{k}=") ? (send("#{k}=", new_klass)) : (instance_variable_set("@#{k}".to_sym, new_klass))
31
- new_attributes = new_attributes.delete_if { |key, value| key == k }
33
+ set_attribute(attr_name, value)
34
+ new_attributes = new_attributes.delete_if { |key, value| key.to_s == attr_name.to_s }
32
35
  end
33
36
  end
34
- assignment(new_attributes, options)
37
+ assign_simple_attributes(new_attributes, options)
35
38
  end
36
39
 
37
40
  def associations
38
41
  self.class.associations
39
42
  end
40
43
 
44
+ class Association
45
+ attr_reader :attr_name
46
+
47
+ def initialize(attr_name, options)
48
+ @attr_name = attr_name
49
+ @options = options
50
+ end
51
+
52
+ def create_value_from_attributes(attributes)
53
+ if @options[:factory_method]
54
+ klass.send(@options[:factory_method], attributes)
55
+ else
56
+ klass.new(attributes)
57
+ end
58
+ end
59
+
60
+ def klass
61
+ if @options[:class_name]
62
+ @options[:class_name].to_s.camelcase.constantize
63
+ else
64
+ klass_from_attr_name
65
+ end
66
+ end
67
+
68
+ def klass_from_attr_name
69
+ @attr_name.to_s.camelcase.constantize
70
+ end
71
+ end
72
+
73
+ class HasOneAssociation < Association
74
+
75
+ end
76
+
77
+ class HasManyAssociation < Association
78
+ def create_value_from_attributes(items)
79
+ items.map{|item| super(item)}
80
+ end
81
+
82
+ def klass_from_attr_name
83
+ @attr_name.to_s.singularize.camelcase.constantize
84
+ end
85
+ end
86
+
41
87
  private
42
88
  def sanitize_attributes(attributes)
43
89
  sanitized_attributes = {}
@@ -49,17 +95,19 @@ module PlainOldModel
49
95
  sanitized_attributes
50
96
  end
51
97
 
52
- def assignment(attributes, options)
98
+ def assign_simple_attributes(attributes, options)
53
99
  attributes = sanitize_attributes(attributes).stringify_keys
54
100
 
55
101
  attributes.each do |k, v|
56
- if respond_to?("#{k}=")
57
- send("#{k}=", v)
58
- elsif respond_to?("#{k}")
59
- instance_variable_set("@#{k}".to_sym, v)
60
- else
61
- raise(Exception)
62
- end
102
+ set_attribute(k, v)
103
+ end
104
+ end
105
+
106
+ def set_attribute(attr_name, value)
107
+ if respond_to?("#{attr_name}=")
108
+ send("#{attr_name}=", value)
109
+ else
110
+ instance_variable_set("@#{attr_name}".to_sym, value)
63
111
  end
64
112
  end
65
113
  end
@@ -12,7 +12,7 @@ module PlainOldModel
12
12
  include ActiveModel::Conversion
13
13
  include PlainOldModel::AttributeAssignment
14
14
 
15
- def initialize(attributes = nil, options = {})
15
+ def initialize(attributes = {}, options = {})
16
16
  assign_attributes(attributes, options) if attributes
17
17
  end
18
18
 
@@ -1,3 +1,3 @@
1
1
  module PlainOldModel
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -37,45 +37,76 @@ describe PlainOldModel::Base do
37
37
  end
38
38
 
39
39
  describe "associations" do
40
- it "should return empty hash for unassociated class" do
41
- @person = Person.new()
42
- @person.associations.should == {}
40
+ it "should return empty array for unassociated class" do
41
+ @person = Continent.new
42
+ @person.associations.should == []
43
43
  end
44
44
  it "should provide all the associations when the class has associations" do
45
- @address = Address.new()
46
- @address.associations.should == {:country => "Country"}
47
- end
48
- it "should create a new instance and assign_attributes to the associated class" do
49
- @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India"}, :read_test => 'This should not be assigned',:write_test => "this shd be available"})
50
- @address.country.class.should == Country
51
- end
52
- it "should create the nested class instance and assign_attributes to the associated nested class" do
53
- @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India", :continent => {:name => "asia"}}, :read_test => 'This should not be assigned',:write_test => "this shd be available"})
54
- @address.country.continent.class.should == Continent
45
+ @address = Address.new
46
+ @address.associations.length.should == 1
47
+ @address.associations.first.attr_name.should == :country
55
48
  end
56
- it "should create a new instance and assign_attributes to the associated class" do
57
- @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India", :continent => {:name => "asia", :desc => {:this => "is a test", :actual_desc => "is another test"}}}, :read_test => 'This should not be assigned',:write_test => "this shd be available"})
58
- @address.country.continent.class.should == Continent
59
- @address.country.continent.name.should == "asia"
60
- @continent = @address.country.continent
61
- @continent.name.should == "asia"
49
+ describe "has_one" do
50
+ it "should create a new instance and assign_attributes to the associated class" do
51
+ @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India"}, :read_test => 'This should not be assigned',:write_test => "this shd be available"})
52
+ @address.country.class.should == Country
53
+ end
54
+ it "should create the nested class instance and assign_attributes to the associated nested class" do
55
+ @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India", :continent => {:name => "asia"}}, :read_test => 'This should not be assigned',:write_test => "this shd be available"})
56
+ @address.country.continent.class.should == Continent
57
+ end
58
+ it "should create a new instance and assign_attributes to the associated class" do
59
+ @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India", :continent => {:name => "asia", :desc => {:this => "is a test", :actual_desc => "is another test"}}}, :read_test => 'This should not be assigned',:write_test => "this shd be available"})
60
+ @address.country.continent.class.should == Continent
61
+ @address.country.continent.name.should == "asia"
62
+ @continent = @address.country.continent
63
+ @continent.name.should == "asia"
64
+ end
65
+ it "should assign values to the read only attributes" do
66
+ @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India"}, :read_test => 'This should be assigned',:write_test => "this shd be available"})
67
+ @address.read_test.should == "This should be assigned"
68
+ end
62
69
  end
63
- it "should assign values to the read only attributes" do
64
- @address = Address.new({:fname => "first value", :lname => "second value", :country => {:code => "In", :name => "India"}, :read_test => 'This should be assigned',:write_test => "this shd be available"})
65
- @address.read_test.should == "This should be assigned"
70
+ describe "has_many" do
71
+ it "should create a new instance and assign attributes for each value in array" do
72
+ @person = Person.new({ addresses: [{ fname: "first name 1", lname: "last name 1"}, { fname: "first name 2", lname: "last name 2"}]})
73
+ @person.addresses.length.should == 2
74
+ @person.addresses.first.class.should == Address
75
+ @person.addresses.first.fname.should == "first name 1"
76
+ @person.addresses.first.lname.should == "last name 1"
77
+ @person.addresses[1].class.should == Address
78
+ @person.addresses[1].fname.should == "first name 2"
79
+ @person.addresses[1].lname.should == "last name 2"
80
+ end
81
+
82
+ it "should create each class via factory_method if one is specified" do
83
+ @person = Person.new({ phones: [{ number: '423-5841'}, {number: '383-9139'}]})
84
+ @person.phones.length.should == 2
85
+ @person.phones[0].number.should == '423-5841'
86
+ @person.phones[0].extension.should == 'set_via_factory'
87
+ @person.phones[1].extension.should == 'set_via_factory'
88
+ end
66
89
  end
67
90
  end
68
-
69
-
70
91
  end
71
92
 
72
93
 
73
94
  class Person < PlainOldModel::Base
74
95
  attr_accessor :fname, :lname, :address
75
- #has_one :address
96
+ has_many :addresses
97
+ has_many :phones, factory_method: :create
76
98
  validates_presence_of :fname
77
99
  end
78
100
 
101
+ class Phone < PlainOldModel::Base
102
+ attr_accessor :number, :extension
103
+
104
+ def self.create(attributes)
105
+ attributes[:extension] = 'set_via_factory'
106
+ new(attributes)
107
+ end
108
+ end
109
+
79
110
  class Address < PlainOldModel::Base
80
111
  attr_accessor :fname, :lname
81
112
  attr_reader :read_test
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plain_old_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-02-11 00:00:00.000000000 Z
13
+ date: 2013-02-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
17
- requirement: &70282593825980 !ruby/object:Gem::Requirement
17
+ requirement: &70107737128780 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70282593825980
25
+ version_requirements: *70107737128780
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: activemodel
28
- requirement: &70282593825520 !ruby/object:Gem::Requirement
28
+ requirement: &70107737128360 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70282593825520
36
+ version_requirements: *70107737128360
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rake
39
- requirement: &70282593825100 !ruby/object:Gem::Requirement
39
+ requirement: &70107737127940 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *70282593825100
47
+ version_requirements: *70107737127940
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rspec
50
- requirement: &70282593824660 !ruby/object:Gem::Requirement
50
+ requirement: &70107737127440 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *70282593824660
58
+ version_requirements: *70107737127440
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: rspec-core
61
- requirement: &70282593824180 !ruby/object:Gem::Requirement
61
+ requirement: &70107737126940 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: '0'
67
67
  type: :development
68
68
  prerelease: false
69
- version_requirements: *70282593824180
69
+ version_requirements: *70107737126940
70
70
  description: ! "This gem is created to cater the projects which do not require a backend/database,\n
71
71
  \ but still need some of the niceties offered by the ActiveRecord"
72
72
  email: