manhattan 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.
@@ -0,0 +1,143 @@
1
+ # Manhattan
2
+
3
+ Manhattan is a gem extracted from the practices we used at [Xenda](http://xenda.pe "Xenda") in the development of our projects.
4
+
5
+ It strives to be a simple status manager for models with minimal overhead and allowing the creation of a simple state machine. Most projects in our experience need for a model to hold a status at once and to perform some actions before or after obtaining that state. This gem simplifies that work without adding much overhead.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'manhattan'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install manhattan
20
+
21
+ ## Usage
22
+
23
+ Models that want to be handled by Manhattan should include the gem on their definition:
24
+
25
+ ```ruby
26
+ class ComicBook < ActiveRecord::Base
27
+ include Manhattan
28
+ end
29
+ ```
30
+
31
+ Manhattan will then wait for your to describe the list of states your class can hold:
32
+
33
+ ```ruby
34
+ class ComicBook < ActiveRecord::Base
35
+ include Manhattan
36
+
37
+ has_statuses :opened, :sold
38
+
39
+ end
40
+ ```
41
+
42
+ For it to do its work, it'll assume the model has a "status" column of type string on your database. This can be customized by appending the "column_name" key at the end of your states list:
43
+
44
+ ```ruby
45
+ class ComicBook < ActiveRecord::Base
46
+ include Manhattan
47
+
48
+ has_statuses :opened, :sold, column_name: :state
49
+
50
+ end
51
+ ```
52
+
53
+ Manhattan will even allow you to setup a default state for initialized records. Take notice that this shouldn't be used instead of setting a default value on a migration or directly on your column.
54
+
55
+ After this setup, Manhattan will give you some love in the form of code
56
+
57
+ #### Getting a list of status
58
+
59
+ ```ruby
60
+ ComicBook.statuses #=> ["opened", "sold"]
61
+ ComicBook.new.statuses #=> ["opened", "sold"]
62
+ ```
63
+
64
+ #### Setting a new status
65
+
66
+ ```ruby
67
+ comic_book = ComicBook.new
68
+ comic_book.mark_as_opened
69
+ comic_book.status #=> "opened"
70
+ ```
71
+
72
+ #### Querying about its status
73
+
74
+ ```ruby
75
+ # directly asking for status
76
+ comic_book.opened? #=> "true"
77
+ comic_book.sold? #=> "false"
78
+
79
+ # or even asking about its negative
80
+ comic_book.unopened? #=> "false"
81
+ comic_book.not_sold? #=> "true"
82
+ ```
83
+
84
+ Manhattan will create alias like "invalid" "unsold" and "not_valid" for each state. Use whichever feels natural for your code.
85
+
86
+ #### Performing actions before and after code changes
87
+
88
+ Manhattan will look for before_* and after_* methods for each state. If they exist, it will run them accordingly:
89
+
90
+ ```ruby
91
+ class ComicBook < ActiveRecord::Base
92
+ # .... all the above code
93
+
94
+ def before_opened
95
+ puts "This is a sad day... when this comic loses its value"
96
+ end
97
+
98
+ def after_opened
99
+ puts "WE CRY NOW AND SHIVER FOR IT'S NO LONGER COLLECTABLE"
100
+ end
101
+ ```
102
+
103
+ ```ruby
104
+ comic_book.mark_as_opened #=>
105
+ #"This is a sad day... when this comic loses its value"
106
+ #"WE CRY NOW AND SHIVER FOR IT'S NO LONGER COLLECTABLE"
107
+ ````
108
+
109
+ #### Model scopes
110
+
111
+ Each model class has associated scopes created for easy returning records from the DB for each state:
112
+
113
+ ```ruby
114
+ ComicBook.opened #=> select * from comic_books where status = 'opened'
115
+ ```
116
+
117
+ #### Adding a default state
118
+
119
+ If wanted, you can setup a default state for your model
120
+
121
+ ```ruby
122
+ class ComicBook < ActiveRecord::Base
123
+ include Manhattan
124
+
125
+ has_statuses :opened, :sold, default_value: :opened
126
+ end
127
+ ```
128
+
129
+ ```ruby
130
+ ComicBook.new.status #=> "opened"
131
+ ```
132
+
133
+ ## TODO
134
+
135
+ Fairly simple, but I18N is pending.
136
+
137
+ ## Contributing
138
+
139
+ 1. Fork it
140
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
141
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
142
+ 4. Push to the branch (`git push origin my-new-feature`)
143
+ 5. Create new Pull Request
@@ -3,6 +3,7 @@ require "manhattan/version"
3
3
  module Manhattan
4
4
 
5
5
  extend ActiveSupport::Concern
6
+ class AlreadyDefinedMethod < StandardError; end
6
7
 
7
8
  def status_column_value
8
9
  self.send(self.class.status_column_name)
@@ -39,6 +40,10 @@ module Manhattan
39
40
  def has_statuses(*statuses)
40
41
  options = statuses.pop if statuses.last.is_a? Hash
41
42
  options ||= {}
43
+
44
+ common_methods = statuses & self.methods
45
+ raise Manhattan::AlreadyDefinedMethod, "Already defined method #{common_methods}" unless common_methods.empty?
46
+
42
47
  @status_column_name = options[:column_name]
43
48
  @status_column_name ||= :status
44
49
 
@@ -81,9 +86,9 @@ module Manhattan
81
86
  def define_query_methods(status)
82
87
 
83
88
  status_sym = status.to_sym
84
- query = "#{status}?".to_sym
85
- negative_query = "not_#{query}".to_sym
86
- alternative_negatives = ["un#{query}".to_sym, "in#{query}".to_sym]
89
+ query = "is_#{status}?".to_sym
90
+ negative_query = "is_not_#{status}?".to_sym
91
+ alternative_negatives = ["is_un#{status}?".to_sym, "is_in#{status}?".to_sym]
87
92
 
88
93
  define_method query do
89
94
  status_column_value == status_value(status_sym)
@@ -1,3 +1,3 @@
1
1
  module Manhattan
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: manhattan
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.3
5
+ version: 0.0.4
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alvaro Pereyra
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 3.2.10
19
+ version: '3.2'
20
20
  none: false
21
21
  name: rails
22
22
  type: :runtime
@@ -25,23 +25,7 @@ dependencies:
25
25
  requirements:
26
26
  - - ~>
27
27
  - !ruby/object:Gem::Version
28
- version: 3.2.10
29
- none: false
30
- - !ruby/object:Gem::Dependency
31
- version_requirements: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ! '>='
34
- - !ruby/object:Gem::Version
35
- version: '0'
36
- none: false
37
- name: sqlite3
38
- type: :development
39
- prerelease: false
40
- requirement: !ruby/object:Gem::Requirement
41
- requirements:
42
- - - ! '>='
43
- - !ruby/object:Gem::Version
44
- version: '0'
28
+ version: '3.2'
45
29
  none: false
46
30
  description: Easy way to define states on your classes
47
31
  email:
@@ -55,7 +39,7 @@ files:
55
39
  - lib/tasks/manhattan_tasks.rake
56
40
  - MIT-LICENSE
57
41
  - Rakefile
58
- - README.rdoc
42
+ - README.md
59
43
  homepage: ''
60
44
  licenses: []
61
45
  post_install_message:
@@ -1,29 +0,0 @@
1
- # Manhattan
2
-
3
- TODO: Write a gem description
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'manhattan'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install manhattan
18
-
19
- ## Usage
20
-
21
- TODO: Write usage instructions here
22
-
23
- ## Contributing
24
-
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request