famili 0.0.6 → 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.
@@ -0,0 +1,36 @@
1
+ module Famili
2
+ class Child < BasicObject
3
+ def initialize(mother, attributes)
4
+ @mother = mother
5
+ @attributes = attributes
6
+ end
7
+
8
+ def method_missing(name, *arguments)
9
+ if @mother.respond_to?(name)
10
+ @mother.send(name, *arguments)
11
+ else
12
+ evaluate_value(name.to_sym, *arguments)
13
+ end
14
+ end
15
+
16
+ def born
17
+ @unresolved_keys = @attributes.keys
18
+ @model = @mother.class.model_class.new
19
+ evaluate_value(@unresolved_keys.first) until @unresolved_keys.empty?
20
+ @model
21
+ end
22
+
23
+ private
24
+
25
+ def evaluate_value(name, *arguments)
26
+ if @unresolved_keys.include?(name)
27
+ @unresolved_keys.delete(name)
28
+ attribute_value = @attributes[name]
29
+ attribute_value = instance_exec(&attribute_value) if attribute_value.is_a?(::Proc)
30
+ @model.send("#{name}=", attribute_value)
31
+ else
32
+ @model.send(name, *arguments)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,42 @@
1
+ require "famili/child"
2
+
3
+ module Famili
4
+ class Father
5
+ def initialize(mother, attributes)
6
+ @mother = mother
7
+ @attributes = attributes
8
+ end
9
+
10
+ def build_hash(opts = {})
11
+ build(opts).attributes.symbolize_keys
12
+ end
13
+
14
+ def build(opts = {})
15
+ attributes = merge(opts)
16
+ model = Famili::Child.new(@mother, attributes).born
17
+ @mother.before_save(model)
18
+ model
19
+ end
20
+
21
+ def create(opts = {})
22
+ model = build(opts)
23
+ model.save!
24
+ @mother.after_create(model)
25
+ model
26
+ end
27
+
28
+ def method_missing(name, *args)
29
+ if scope_attributes = @mother.class.scopes[name]
30
+ Famili::Father.new(@mother, merge(scope_attributes))
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def merge(attributes)
39
+ @attributes.merge(attributes)
40
+ end
41
+ end
42
+ end
data/lib/famili/mother.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require 'date'
2
- module Famili
2
+ require 'famili/father'
3
3
 
4
+ module Famili
4
5
  class Mother
5
-
6
6
  def before_save(model)
7
7
  end
8
8
 
@@ -20,9 +20,9 @@ module Famili
20
20
  class << self
21
21
  alias :class_name :name
22
22
 
23
- def objects_sequence_number
23
+ def objects_sequence_number
24
24
  @sequence_number ||=0
25
- @sequence_number += 1
25
+ @sequence_number += 1
26
26
  end
27
27
 
28
28
  def parent_class=(klass)
@@ -39,94 +39,67 @@ module Famili
39
39
 
40
40
  def name(&block)
41
41
  return class_name unless block_given?
42
- field(:name,&block)
42
+ field(:name, &block)
43
43
  end
44
44
 
45
- def method_missing(method,&block)
46
- return field(method,&block) if block_given?
45
+ def method_missing(method, &block)
46
+ return field(method, &block) if block_given?
47
47
  super
48
48
  end
49
49
 
50
- def attribures
51
- @attribures||=parent_class && parent_class.attribures.clone
52
- @attribures||=[]
53
- @attribures.uniq!
54
- @attribures
50
+ def attributes
51
+ @attributes||=parent_class && parent_class.attributes.clone || {}
52
+ @attributes
55
53
  end
56
54
 
57
- def field(method,&block)
58
- attribures<< method
59
- #puts "define_method #{method} #{self}"
60
- define_method(method,&block) if block_given?
55
+ def field(method, &block)
56
+ attributes[method] = block
61
57
  end
62
58
 
63
- def create(opts={})
64
- mother,model = _build(opts)
65
- model.save!
66
- mother.after_create(model)
67
- model
59
+ def father
60
+ @father ||= Famili::Father.new(self.new, attributes)
68
61
  end
69
62
 
70
- def build(opts={})
71
- _,model = _build(opts)
72
- model
63
+ def create(opts = {})
64
+ father.create(opts)
73
65
  end
74
66
 
75
- def build_hash(opts={})
76
- _,model = _build(opts)
77
- model.attributes.dup.symbolize_keys!
67
+ def build(opts = {})
68
+ father.build(opts)
78
69
  end
79
70
 
80
- if RUBY_VERSION.sub(/(\d+\.\d+).*/, "\\1").to_f < 1.9
81
- def hash(opts={})
82
- warn "[DEPRECATION] `hash` is deprecated and not supported for Ruby 1.9. Please use `build_hash` instead."
83
- build_hash(opts)
84
- end
71
+ def build_hash(opts = {})
72
+ father.build_hash(opts)
85
73
  end
86
74
 
87
-
88
- def _build(opts)
89
- mother = new
90
- model = model_class.new
91
- opts.symbolize_keys!
92
- passed_attrs = opts.keys || []
93
-
94
- mother.instance_eval do
95
- singleton = class <<self;self;end;
96
- passed_attrs.each do |attr|
97
- value = opts[attr]
98
- if value.class == Proc
99
- singleton.send(:define_method,attr,&value)
100
- else
101
- singleton.send(:define_method,attr) do
102
- opts[attr]
103
- end
104
- end
105
- end
75
+ def scope(name)
76
+ saved_attributes = @attributes
77
+ @attributes = {}
78
+ yield
79
+ scopes[name] = @attributes
80
+ singleton_class.send(:define_method, name) do
81
+ father.send(name)
82
+ end
83
+ ensure
84
+ @attributes = saved_attributes
106
85
  end
107
86
 
108
- fields = ( passed_attrs + attribures).uniq
109
- fields.each do |attr|
110
- attr = attr.to_sym
111
- value = opts.key?(attr) ? opts[attr] : mother.send(attr)
112
- model.send(:"#{attr}=",value)
87
+ def scopes
88
+ @scopes ||= parent_class && parent_class.scopes.dup || {}
113
89
  end
114
- mother.before_save(model)
115
- [mother,model]
116
- end
117
90
 
118
- private
119
-
120
- def model_class(klass=nil)
121
- if klass
122
- @model_class = klass
123
- return
124
- end
91
+ def model_class(klass=nil)
92
+ if klass
93
+ @model_class = klass
94
+ return
95
+ end
125
96
 
126
- @model_class||= class_name.to_s.split('::')[1..-1].inject(Object) do |mod,const|
127
- mod.const_get(const)
97
+ @model_class ||= if class_name =~ /(.*)Famili$/ || class_name =~ /Famili::(.*)/
98
+ $1.split('::').inject(Object) do |mod, const|
99
+ mod.const_get(const)
100
+ end
101
+ end
128
102
  end
129
103
  end
130
104
  end
131
105
  end
132
- end
@@ -0,0 +1,5 @@
1
+ module Famili
2
+ module Version
3
+ STRING = '0.1.2'
4
+ end
5
+ end
data/lib/famili.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
2
  module Famili
3
- VERSION='0.0.6'
4
3
  autoload :Mother,'famili/mother'
5
4
  end
metadata CHANGED
@@ -1,74 +1,54 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: famili
3
- version: !ruby/object:Gem::Version
4
- hash: 19
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 0
9
- - 6
10
- version: 0.0.6
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - niquola
9
+ - mirasrael
14
10
  autorequire:
15
- bindir: bin
11
+ bindir: exe
16
12
  cert_chain: []
17
-
18
- date: 2010-11-17 00:00:00 +03:00
19
- default_executable:
13
+ date: 2011-10-27 00:00:00.000000000Z
20
14
  dependencies: []
21
-
22
- description:
23
- email: niquola@gmail.com
15
+ description: Yet another object mother pattern implementation.
16
+ email:
24
17
  executables: []
25
-
26
18
  extensions: []
27
-
28
- extra_rdoc_files:
29
- - README.rdoc
30
- files:
31
- - README.rdoc
32
- - Rakefile
33
- - lib/famili/mother.rb
19
+ extra_rdoc_files: []
20
+ files:
34
21
  - lib/famili.rb
35
- - spec/famili_spec.rb
36
- - spec/database.yml
37
- - spec/db/schema.rb
38
- - spec/spec_helper.rb
39
- has_rdoc: true
22
+ - lib/famili/child.rb
23
+ - lib/famili/father.rb
24
+ - lib/famili/mother.rb
25
+ - lib/famili/version.rb
40
26
  homepage: http://github.com/niquola/famili
41
27
  licenses: []
42
-
43
28
  post_install_message:
44
- rdoc_options: []
45
-
46
- require_paths:
29
+ rdoc_options:
30
+ - --charset=UTF-8
31
+ require_paths:
47
32
  - lib
48
- required_ruby_version: !ruby/object:Gem::Requirement
33
+ required_ruby_version: !ruby/object:Gem::Requirement
49
34
  none: false
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- hash: 3
54
- segments:
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ segments:
55
40
  - 0
56
- version: "0"
57
- required_rubygems_version: !ruby/object:Gem::Requirement
41
+ hash: 3424676133283759480
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
43
  none: false
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- hash: 3
63
- segments:
64
- - 0
65
- version: "0"
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
66
48
  requirements: []
67
-
68
49
  rubyforge_project:
69
- rubygems_version: 1.3.7
50
+ rubygems_version: 1.8.10
70
51
  signing_key:
71
52
  specification_version: 3
72
- summary: Rails plugin for postgres
53
+ summary: famili-0.1.2
73
54
  test_files: []
74
-
data/README.rdoc DELETED
@@ -1,148 +0,0 @@
1
- == Famili
2
-
3
- Yet Another ObjectMother pattern implementation for rails testing
4
-
5
- == Why
6
-
7
- We meet some problems with factory-girl:
8
-
9
- * We require quite complex logic for creation of test models
10
- * We require use factories with running rails application for integration tests
11
- * So why don't make factory just another class in rails lib, and get extensibility of factories/mothers and rails lazy loading and dependency management?
12
-
13
- == Example
14
-
15
- To define factory/mother for model User just create class in your lib directory:
16
-
17
- #lib/famili/user.rb`
18
-
19
- module Famili
20
- class User < Mother
21
- fist_name { 'nicola' }
22
- last_name { 'nicola' }
23
- email { "#{last_name}@mail.lv" }
24
-
25
- def before_save(user)
26
- #...
27
- end
28
-
29
- def after_create(user)
30
- #...
31
- end
32
- end
33
- end
34
-
35
- #lib/famili/article
36
-
37
- module Famili
38
- class Article < Mother
39
- #creating association
40
- user { Famili::User.create }
41
- title { "article by #{user.last_name}" }
42
- end
43
- end
44
-
45
-
46
- And u can use it anywhere in tests or controllers:
47
-
48
- Famili::User.create(:fist_name=>'Override') # create model
49
- Famili::User.build(:fist_name=>'Override') # build model not saving
50
- Famili::User.hash(:fist_name=>'Override') #get attributes hash
51
-
52
- Famili::Article.create #create article with user
53
-
54
- == Inheritance
55
-
56
- U can inherite mothers just like plain ruby classes,
57
- Just think each declaration field_name {...} as method definition
58
-
59
- module Famili
60
- class User < Mother
61
- name { "nicola" }
62
- end
63
-
64
- class Person < User
65
- email { "#{name}@emial.com" }
66
- end
67
- end
68
-
69
- == Mother methods
70
-
71
- Mother have some usable methods, which can be used
72
-
73
- module Famili
74
- class User < Mother
75
- last_name { 'nicola' }
76
- login { "#{last_name}_#{unique}" }
77
- number { sequence_number }
78
- end
79
- end
80
-
81
- * sequence_number - incremented with each instance
82
- * unique - just unique string
83
- * we a planing add more
84
-
85
- == Nutshell
86
-
87
- each declaration
88
-
89
- field_name { block }
90
-
91
- just create method
92
-
93
- def field_name
94
- end
95
-
96
- and register attribuite to copy in model
97
-
98
- field :field_name
99
-
100
- == Install
101
-
102
- in config/environment.rb:
103
-
104
- config.gem 'famili'
105
-
106
- and then
107
-
108
- sudo rake gems:install
109
-
110
- == FEATURES
111
-
112
-
113
- == CHANGE LOG:
114
-
115
- * 0.0.1 - created
116
- * 0.0.2 - add inheritance, and mother methods [unique,sequence_number]
117
- * 0.0.3 - fix Mother.create call model.save!; Mother.hash return symbolized hash
118
- * 0.0.5 - add raise NoMethodError if property declared without block (becose it is error-prone), fix Famili::Mother.class#name method
119
- * 0.0.6 - rename Mother#hash to Mother#build_hash (to avoid conflicts with Object#hash in Ruby 1.9). Old name keeped as alias when using with oldest versions of Ruby for backward compatibility.
120
-
121
- == TODO
122
-
123
- * generators
124
-
125
- == LICENSE:
126
-
127
- (The MIT License)
128
-
129
- Copyright (c) 2010 niquola
130
-
131
- Permission is hereby granted, free of charge, to any person obtaining
132
- a copy of this software and associated documentation files (the
133
- 'Software'), to deal in the Software without restriction, including
134
- without limitation the rights to use, copy, modify, merge, publish,
135
- distribute, sublicense, and/or sell copies of the Software, and to
136
- permit persons to whom the Software is furnished to do so, subject to
137
- the following conditions:
138
-
139
- The above copyright notice and this permission notice shall be
140
- included in all copies or substantial portions of the Software.
141
-
142
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
143
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
144
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
145
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
146
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
147
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
148
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile DELETED
@@ -1,58 +0,0 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
4
- require 'rake/gempackagetask'
5
- require 'rubygems'
6
- require 'spec/rake/spectask'
7
-
8
-
9
- desc 'Default: run unit tests.'
10
- task :default => :test
11
-
12
- desc 'Test the pg_gnostic plugin.'
13
- #Rake::TestTask.new(:test) do |t|
14
- #t.libs << 'lib'
15
- #t.libs << 'spec'
16
- #t.pattern = 'spec/**/*_spec.rb'
17
- #t.verbose = true
18
- #end
19
-
20
- Spec::Rake::SpecTask.new(:test) do |t|
21
- t.libs << 'lib'
22
- t.warning = true
23
- t.rcov = true
24
- end
25
-
26
-
27
- desc 'Generate documentation for the pg_gnostic plugin.'
28
- Rake::RDocTask.new(:rdoc) do |rdoc|
29
- rdoc.rdoc_dir = 'rdoc'
30
- rdoc.title = 'Famili'
31
- rdoc.options << '--line-numbers' << '--inline-source'
32
- rdoc.rdoc_files.include('README.rdoc')
33
- rdoc.rdoc_files.include('lib/**/*.rb')
34
- end
35
-
36
-
37
- PKG_FILES = FileList[ '[a-zA-Z]*', 'generators/**/*', 'lib/**/*', 'spec/**/*' ]
38
-
39
- require 'lib/famili'
40
- spec = Gem::Specification.new do |s|
41
- s.name = "famili"
42
- s.version = Famili::VERSION
43
- s.author = "niquola"
44
- s.email = "niquola@gmail.com"
45
- s.homepage = "http://github.com/niquola/famili"
46
- s.platform = Gem::Platform::RUBY
47
- s.summary = "Rails plugin for postgres"
48
- s.files = PKG_FILES.to_a
49
- s.require_path = "lib"
50
- s.has_rdoc = false
51
- s.extra_rdoc_files = ["README.rdoc"]
52
- end
53
-
54
- desc 'Turn this plugin into a gem.'
55
- Rake::GemPackageTask.new(spec) do |pkg|
56
- pkg.gem_spec = spec
57
- end
58
-
data/spec/database.yml DELETED
@@ -1,6 +0,0 @@
1
- adapter: postgresql
2
- host: localhost
3
- database: famili
4
- username: postgres
5
- password: postgres
6
- encoding: utf8
data/spec/db/schema.rb DELETED
@@ -1,23 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 0) do
2
- create_table :users do |t|
3
- t.string :last_name, :limit => 25
4
- t.string :first_name, :limit => 25
5
- t.string :middle_name, :limit => 25
6
- t.string :name, :limit => 25
7
- t.string :login, :limit => 100
8
- t.string :email, :limit => 100
9
- t.string :number, :limit => 100
10
- t.string :crypted_password, :limit => 40
11
- t.string :salt, :limit => 40
12
- t.datetime :last_login_datetime
13
- t.datetime :deleted_at
14
- t.timestamps
15
- end
16
-
17
- create_table :articles do |t|
18
- t.integer :user_id
19
- t.string :title, :limit => 25
20
- t.text :content
21
- t.timestamps
22
- end
23
- end
data/spec/famili_spec.rb DELETED
@@ -1,94 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Famili do
4
- before :all do
5
- TestDbUtils.ensure_schema
6
- end
7
-
8
- after :all do
9
- TestDbUtils.drop_database
10
- end
11
-
12
- class User < ActiveRecord::Base
13
- has_many :articles
14
- validates_presence_of :login
15
- end
16
-
17
- class Article < ActiveRecord::Base
18
- belongs_to :user
19
- end
20
-
21
- module Famili
22
- class User < Mother
23
- last_name { 'nicola' }
24
- login { "#{last_name}_#{unique}" }
25
- number { sequence_number }
26
-
27
-
28
- def before_save(user)
29
- user.first_name = 'first_name'
30
- end
31
-
32
- def after_create(model)
33
- end
34
- end
35
-
36
- class Article < Mother
37
- user { Famili::User.create }
38
- title { "article by #{user.last_name}" }
39
- end
40
- end
41
-
42
- it "should use save! model" do
43
- lambda { Famili::User.create(:login=>nil) }.should raise_error
44
- end
45
-
46
- it "should create model" do
47
- nicola = Famili::User.create
48
- nicola.class.should == User
49
- nicola.last_name.should == 'nicola'
50
- nicola.first_name.should == 'first_name'
51
-
52
- ivan = Famili::User.create(:name=>'ivan')
53
- ivan.name.should == 'ivan'
54
- end
55
-
56
- it "mother should have #hash method returning symbolized hash" do
57
- hash = Famili::User.hash
58
- hash.keys.each {|key| key.should be_kind_of(Symbol) }
59
- end
60
-
61
-
62
- it "should create model with asscociation" do
63
- article = Famili::Article.create
64
- article.user.should_not be_nil
65
- article.user.class.should == ::User
66
- article.title.should == "article by nicola"
67
- end
68
-
69
- it "mother should have unique,sequence_number methods" do
70
- Famili::User.new.should respond_to(:unique)
71
- Famili::User.new.should respond_to(:sequence_number)
72
- u1 = Famili::User.create
73
- u2 = Famili::User.create
74
- seq_number = Famili::User.new.sequence_number
75
- next_seq_number = Famili::User.new.sequence_number
76
- next_seq_number.should == (seq_number + 1)
77
- end
78
-
79
- it "mother should generate unique numbers" do
80
- logins = []
81
- 10000.times do
82
- logins << Famili::User.hash[:login]
83
- end
84
- logins.include?(Famili::User.hash[:login]).should_not be_true
85
- end
86
-
87
- it "should not add attribuite name" do
88
- Famili::User.name
89
- Famili::User.attribures.should_not include(:name)
90
- lambda {
91
- Famili::User.unexisting
92
- }.should raise_error(NoMethodError)
93
- end
94
- end
data/spec/spec_helper.rb DELETED
@@ -1,60 +0,0 @@
1
- require 'rubygems'
2
- gem 'activerecord','=2.3.8'
3
- require 'active_record'
4
-
5
-
6
- def path(path)
7
- File.join(File.dirname(__FILE__),path)
8
- end
9
-
10
- $:.unshift(path('../lib'))
11
- require 'famili'
12
-
13
- class TestDbUtils
14
- class<< self
15
- def config
16
- @config ||= YAML::load(IO.read(path('/database.yml'))).symbolize_keys
17
- end
18
-
19
- #create test database
20
- def ensure_test_database
21
- connect_to_test_db
22
- rescue
23
- create_database
24
- end
25
-
26
- def load_schema
27
- ensure_test_database
28
- load(path('db/schema.rb'))
29
- end
30
-
31
- def ensure_schema
32
- load_schema
33
- rescue
34
- puts "tests database exists: skip schema loading"
35
- end
36
-
37
- def create_database
38
- connect_to_postgres_db
39
- ActiveRecord::Base.connection.create_database(config[:database], config)
40
- connect_to_test_db
41
- rescue
42
- $stderr.puts $!, *($!.backtrace)
43
- $stderr.puts "Couldn't create database for #{config.inspect}"
44
- end
45
-
46
- def connect_to_test_db
47
- ActiveRecord::Base.establish_connection(config)
48
- ActiveRecord::Base.connection
49
- end
50
-
51
- def connect_to_postgres_db
52
- ActiveRecord::Base.establish_connection(config.merge(:database => 'postgres', :schema_search_path => 'public'))
53
- end
54
-
55
- def drop_database
56
- connect_to_postgres_db
57
- ActiveRecord::Base.connection.drop_database config[:database]
58
- end
59
- end
60
- end