bucket_maker 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZWUxYWViNjAzYTQ0MmY5NWVmNTc3YTY2ODM3ZTNjZDQwOTNkNzQ1Yg==
4
+ NzI3ZDVhYjZhNGQwMDc0YTljOTk1MzBmODE1MDYzNmUwOGRkNWQ1Zg==
5
5
  data.tar.gz: !binary |-
6
- YWUzZmMyNzkxYmI2OTc0ZjI2Mjg1MDFiZjE1NGRiMmYyODBhYjFkZg==
6
+ Yjk3N2ExMWNkZjI5MDkzZDIwZGExMDVlZmM0MDE2YTMxOWM0NmJhNQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODMxZGE3ZDM3ZDllMmYwOGViYzZiOTIzZTQwMzk0NTQ5N2Y4YTk2YjJiMmRi
10
- OWVlMTdiYTBjOGJkMGMyYWE3MjZmM2I1YTFkNDY3ZWQ2ZmIyNzZmZGFkYmY1
11
- MjUyZjBhZTBkMzAxYjI0MGQwNmE2M2QzNWRmNjMxNWMxYmI1ODQ=
9
+ MTUwMWQ3ODA5OTYyODNkZDYzOWY0ZmYxMGJlNDQzYjg3N2EzYjcyMmUxOGFk
10
+ OTZhNTU3ZTg2MmY2MWMwNTY1OTQ1MDcyOWFkMmUxNDU1NWQ4MzNiNGE3MzZi
11
+ NzllOGQ4ODYyMmQ2OTI0OGNlNjFiMTIxMjQzZTczN2U4ZWJmNTE=
12
12
  data.tar.gz: !binary |-
13
- MGZhOGExYjc5NjgyNjY0YjU2ZGQyMjM0NjllY2EwOGVmN2RkZTNlMGU4NGIy
14
- NDhjYmI2ZGUyZGVlNTQzYzcyOTI4ZDEwNjQ2OTM4NjBhZWIzYTgzYjM3MDQx
15
- MzRlNDZiMzRhNWJmOGUxOTRhMWJkMTQzYTk2OTQzYmJiOGRlZmQ=
13
+ NTM0Y2QzODkwOTRkNDhlN2FmMGI1ODY0NGMwYjJjZWIzYjY2NjkxOGFmNmRm
14
+ ZDg3NGE2Nzk0ZGM3Y2FkYjA5MTUwMzU1OGYxYjRmOTQ5Zjg1OTE1MTliNDZj
15
+ MjVhZWZkMDVhNjYxYmJmNDYwMTMxMmQyMzM1MmRhMWYyMzk0NGE=
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ spec/reports
16
16
  test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
+ *.log
data/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
  [![Code Climate](https://codeclimate.com/github/dinks/bucket_maker.png)](https://codeclimate.com/github/dinks/bucket_maker)
5
5
  [![Build Status](https://travis-ci.org/dinks/bucket_maker.png?branch=master)](https://travis-ci.org/dinks/bucket_maker)
6
6
  [![Coverage Status](https://coveralls.io/repos/dinks/bucket_maker/badge.png)](https://coveralls.io/r/dinks/bucket_maker)
7
+ [![Dependency Status](https://gemnasium.com/dinks/bucket_maker.png)](https://gemnasium.com/dinks/bucket_maker)
7
8
 
8
9
  A Gem to categorize Objects into buckets. Typical use case is an A/B test for Users
9
10
 
@@ -4,27 +4,40 @@ class BucketMakerController < ApplicationController
4
4
  before_filter :ensure_valid_series_bucket_group, only: [:show, :switch]
5
5
  before_filter :ensure_valid_series_bucket, only: [:randomize]
6
6
 
7
+ # Show if the group for the current_user is the same as stored
8
+ #
7
9
  def show
8
10
  render text: @current_user.in_bucket?(@series_name, @bucket_name, @group_name)
9
11
  end
10
12
 
13
+ # Switch the current user to group_name
14
+ #
11
15
  def switch
12
16
  render text: @current_user.force_to_bucket!(@series_name, @bucket_name, @group_name)
13
17
  end
14
18
 
19
+ # Randomize the current_user for series_name and bucket_name
20
+ #
15
21
  def randomize
16
22
  render text: @current_user.bucketize_for_series_and_bucket!(@series_name, @bucket_name)
17
23
  end
18
24
 
19
25
  private
26
+
27
+ # Ensure we have valid attributes
28
+ #
20
29
  def ensure_valid_series_bucket_group
21
30
  not_found unless BucketMaker.buckets_configuration.has_group_in_bucket_in_series?(@series_name, @bucket_name, @group_name)
22
31
  end
23
32
 
33
+ # Ensure we have valid attributes
34
+ #
24
35
  def ensure_valid_series_bucket
25
36
  not_found unless BucketMaker.buckets_configuration.has_bucket_in_series?(@series_name, @bucket_name)
26
37
  end
27
38
 
39
+ # Head not found for invalid requests
40
+ #
28
41
  def not_found
29
42
  head :not_found
30
43
  false
data/config/routes.rb CHANGED
@@ -2,12 +2,15 @@ Rails.application.routes.draw do
2
2
  if BucketMaker.configured? && BucketMaker.load_routes?
3
3
 
4
4
  # Show if the user is in group
5
+ #
5
6
  get "/#{BucketMaker.configuration.path_prefix}:series_name/:bucket_name/:group_name", to: 'bucket_maker#show', as: :show_bucket, format: :json
6
7
 
7
8
  # Randomize group
9
+ #
8
10
  post "/#{BucketMaker.configuration.path_prefix}:series_name/:bucket_name", to: 'bucket_maker#randomize', as: :randomize_bucket, format: :json
9
11
 
10
12
  # Force Switch group
13
+ #
11
14
  post "/#{BucketMaker.configuration.path_prefix}:series_name/:bucket_name/:group_name", to: 'bucket_maker#switch', as: :switch_bucket, format: :json
12
15
 
13
16
  end
@@ -1,4 +1,6 @@
1
1
  module BucketMaker
2
+ # Class which holds all the Bucket information
3
+ #
2
4
  class Bucket
3
5
  attr_accessor :name,
4
6
  :summary,
@@ -11,6 +13,11 @@ module BucketMaker
11
13
  BUCKET_USER_AFTER = 'created_after'
12
14
  BUCKET_DISTRIBUTION = 'distributions'
13
15
 
16
+ # Initializer
17
+ #
18
+ # @param name [string] Name of the Bucket
19
+ # @param options [Hash] Options for the Bucket like BUCKET_DESCRIPTION, BUCKET_USER_AFTER, BUCKET_DISTRIBUTION
20
+ #
14
21
  def initialize(name, options={})
15
22
  @name = name.to_sym
16
23
  @summary = options[BUCKET_DESCRIPTION]
@@ -27,20 +34,28 @@ module BucketMaker
27
34
  result[dist_name.to_sym] = dist_options
28
35
  result
29
36
  end if options[BUCKET_DISTRIBUTION]
30
-
31
37
  end
32
38
 
39
+ # Randomize and get the group for this bucket
40
+ #
41
+ # @return [String] Group Name after randomization
42
+ #
33
43
  def random_group
34
44
  # Is set after first randomization
35
45
  unless @distributions_percent
46
+ # Get the total value of the distributions
47
+ #
36
48
  @denominator = @distributions.inject(0) do |result, (_, dist_value)|
37
49
  result + dist_value
38
50
  end
51
+ # Populate the variable with Distribution Percentages
52
+ #
39
53
  @distributions_percent = @distributions.inject({}) do |result, (dist_name, dist_value)|
40
54
  result[dist_name.to_sym] = (dist_value * 100.0)/@denominator
41
55
  result
42
56
  end
43
-
57
+ # Change the Distribution Percentages with Ranges for easy checks
58
+ #
44
59
  @distributions_percent.inject(0) do |starter, (dist_name, percent_value)|
45
60
  ender = starter + percent_value
46
61
  @distributions_percent[dist_name.to_sym] = (starter .. ender)
@@ -48,18 +63,32 @@ module BucketMaker
48
63
  end
49
64
  end
50
65
 
66
+ # Randomize within the 0..max_range
67
+ #
51
68
  randomized = rand(@denominator * 100)
69
+ # Find where the randomized number falls in the calculated range
70
+ #
52
71
  @distributions_percent.find do |_, percent_range|
53
72
  percent_range.include?(randomized)
54
73
  end.first
55
74
  end
56
75
 
76
+ # Check if the Bucketable conforms to the pre-conditions
77
+ #
78
+ # @param bucketable [Object] an object which responds to :created_at
79
+ # @return [Boolean] is it bucketable?
80
+ #
57
81
  def is_bucketable?(bucketable)
58
- bucketable.created_at >= @created_after
82
+ bucketable.created_at >= @created_after rescue false
59
83
  end
60
84
 
85
+ # Check if there is a group in this bucket
86
+ #
87
+ # @param group_name [String] Name of the group
88
+ # @return [Boolean] does the group exist?
89
+ #
61
90
  def has_group?(group_name)
62
- @distributions[group_name.to_sym] != nil
91
+ @distributions[group_name.to_sym] != nil if group_name
63
92
  end
64
93
  end
65
94
  end
@@ -3,6 +3,8 @@ require 'active_support/core_ext'
3
3
  require 'bucket_maker/series_maker'
4
4
 
5
5
  module BucketMaker
6
+ # Configuration Holder for the BucketMaker
7
+ #
6
8
  class Configuration
7
9
  attr_accessor :redis_options,
8
10
  :path_prefix,
@@ -13,23 +15,35 @@ module BucketMaker
13
15
  attr_reader :buckets_configuration,
14
16
  :connection
15
17
 
18
+ # Initializer
19
+ # Sets up the default variable values
20
+ #
16
21
  def initialize
22
+ # For Redis
17
23
  @redis_options = {
18
24
  host: 'localhost',
19
25
  port: 6379,
20
26
  db: 1
21
27
  }
22
-
23
28
  @redis_expiration_time = 12.months
24
29
 
30
+ # For paths
31
+ # If nil, the routes wont be loaded
25
32
  @path_prefix = '2bOrNot2B/'
26
33
 
34
+ # Configuration for the buckets
35
+ #
27
36
  @buckets_config_file = nil
28
37
  @buckets_configuration = nil
29
38
 
39
+ # Lazy Load is used to group only if in_bucket? is called
40
+ # if false, then the group is done at creation time of the objec as well
41
+ #
30
42
  @lazy_load = true
31
43
  end
32
44
 
45
+ # Reconfigure the Configuration
46
+ #
33
47
  def reconfigure!
34
48
  if @buckets_config_file
35
49
  @buckets_configuration = BucketMaker::SeriesMaker.instance
@@ -37,10 +51,17 @@ module BucketMaker
37
51
  end
38
52
  end
39
53
 
54
+ # Check if the configuration is done
55
+ #
56
+ # @return [Boolean]
40
57
  def configured?
41
58
  @buckets_configuration && @buckets_configuration.configured?
42
59
  end
43
60
 
61
+ # Check if its ok to load routes
62
+ #
63
+ # @return [Boolean]
64
+ #
44
65
  def load_routes?
45
66
  @path_prefix != nil
46
67
  end
@@ -48,6 +69,8 @@ module BucketMaker
48
69
  end
49
70
 
50
71
  class << self
72
+ # Forward some of the calls to the configuration object
73
+ #
51
74
  extend Forwardable
52
75
 
53
76
  attr_accessor :configuration
@@ -55,6 +78,8 @@ module BucketMaker
55
78
  def_delegators :@configuration, :configured?, :reconfigure!, :buckets_configuration, :load_routes?
56
79
  end
57
80
 
81
+ # Configure after yielding to the block
82
+ #
58
83
  def self.configure
59
84
  if block_given?
60
85
  self.configuration ||= Configuration.new
@@ -1,4 +1,6 @@
1
1
  module BucketMaker
2
+ # Engine for the BucketMaker
3
+ #
2
4
  class Engine < Rails::Engine
3
5
  initializer 'Require concerns path' do |app|
4
6
  concerns_path = 'app/controllers/concerns'
@@ -7,6 +9,8 @@ module BucketMaker
7
9
  app.paths.add(concerns_path)
8
10
  end
9
11
 
12
+ # Always add the concern
13
+ #
10
14
  require 'concerns/bucket_maker_concern'
11
15
  end
12
16
  end
@@ -2,7 +2,18 @@ require 'bucket_maker/series_maker'
2
2
 
3
3
  module BucketMaker
4
4
  module Models
5
+ # Module which holds the base methods for Bucketable objects
6
+ #
5
7
  module Bucketable
8
+
9
+ # Used to test if this object has been grouped under a certain group
10
+ #
11
+ # @param series_name [String] Name of the Series
12
+ # @param bucket_name [String] Name of the Bucket
13
+ # @param group_name [String] Name of the Group
14
+ # @param force [Boolean] To force the object into the group_name
15
+ # @return [Boolean] if the given group_name is the same after randomization of groups
16
+ #
6
17
  def in_bucket?(series_name, bucket_name, group_name, force=false)
7
18
  # Get the singleton Series Maker
8
19
  series_maker = BucketMaker::SeriesMaker.instance
@@ -39,15 +50,32 @@ module BucketMaker
39
50
  end
40
51
  end
41
52
 
53
+ # Used to test if this object has not been grouped under a certain group
54
+ #
55
+ # @param series_name [String] Name of the Series
56
+ # @param bucket_name [String] Name of the Bucket
57
+ # @param group_name [String] Name of the Group
58
+ # @return [Boolean] if the given group_name is the not the same after randomization of groups
59
+ #
42
60
  def not_in_bucket?(series_name, bucket_name, group_name)
43
61
  !in_bucket?(series_name, bucket_name, group_name)
44
62
  end
45
63
 
64
+ # Force object into the group_name under bucket under series
65
+ #
66
+ # @param series_name [String] Name of the Series
67
+ # @param bucket_name [String] Name of the Bucket
68
+ # @param group_name [String] Name of the Group
69
+ # @return [Boolean] Always true because forcing is ok by us
70
+ #
46
71
  def force_to_bucket!(series_name, bucket_name, group_name)
47
72
  # Forcefully place inside the bucket
48
73
  in_bucket?(series_name, bucket_name, group_name, true)
49
74
  end
50
75
 
76
+ # Iteratively group object into buckets
77
+ #
78
+ # @return [Boolean] true if all the operations are successfull
51
79
  def bucketize!
52
80
  # Take each series and bucket
53
81
  BucketMaker::SeriesMaker.instance.for_each_series_with_bucketable do |series_maker, series_name, bucket_name|
@@ -61,6 +89,11 @@ module BucketMaker
61
89
  end
62
90
  end
63
91
 
92
+ # Group object for series_name and bucket_name
93
+ #
94
+ # @param series_name [String] Name of the Series
95
+ # @param bucket_name [String] Name of the Bucket
96
+ # @return [Boolean] true if the operation is successfull
64
97
  def bucketize_for_series_and_bucket!(series_name, bucket_name)
65
98
  # Get the singleton Series Maker
66
99
  series_maker = BucketMaker::SeriesMaker.instance
@@ -77,10 +110,20 @@ module BucketMaker
77
110
  end
78
111
  end
79
112
 
113
+ # Get the value from persistent store for a key
114
+ #
115
+ # @param series_key [String] Series Key
116
+ # @return [String] should return the group_name
117
+ #
80
118
  def group_for_key(series_key)
81
119
  raise NotImplementedError, "Implement group_for_key"
82
120
  end
83
121
 
122
+ # Set the value to a persistent store for a series and group
123
+ #
124
+ # @param series_key [String] Series Key
125
+ # @param group_name [String] Name of the Group
126
+ #
84
127
  def set_group_for_key(series_key, group_name)
85
128
  raise NotImplementedError, "Implement set_group_for_key"
86
129
  end
@@ -1,4 +1,6 @@
1
1
  module BucketMaker
2
+ # Class which holds all the Series based information
3
+ #
2
4
  class Series
3
5
  attr_reader :name,
4
6
  :description,
@@ -9,6 +11,11 @@ module BucketMaker
9
11
  SERIES_USER_AFTER = 'created_after'
10
12
  SERIES_BUCKETS = 'buckets'
11
13
 
14
+ # Initializer
15
+ #
16
+ # @param name [String] Name of the Series
17
+ # @param options [Hash] Options for the Series like SERIES_DESCRIPTION, SERIES_USER_AFTER, SERIES_BUCKETS
18
+ #
12
19
  def initialize(name, options={})
13
20
  @name = name.to_sym
14
21
  @description = options[SERIES_DESCRIPTION] || ''
@@ -23,26 +30,49 @@ module BucketMaker
23
30
  end if options[SERIES_BUCKETS]
24
31
  end
25
32
 
33
+ # Iterator going through each bucket
34
+ #
26
35
  def each_bucket
27
36
  @buckets.each do |bucket_name, bucket|
28
37
  yield bucket_name, bucket
29
38
  end if block_given?
30
39
  end
31
40
 
41
+ # Get the Bucket object when given the bucket_name
42
+ #
43
+ # @param bucket_name [String] Name of the Bucket
44
+ # @return [BucketMaker::Bucket] Bucket object
45
+ #
32
46
  def bucket_with_name(bucket_name)
33
- @buckets[bucket_name.to_sym]
47
+ @buckets[bucket_name.to_sym] if bucket_name
34
48
  end
35
49
 
50
+ # Check if the Bucketable object conforms to the conditions
51
+ #
52
+ # @param bucketable [Object] an object which responds to :created_at
53
+ # @return [Boolean] is it bucketable?
54
+ #
36
55
  def is_bucketable?(bucketable)
37
- bucketable.created_at >= @created_after
56
+ bucketable.created_at >= @created_after rescue false
38
57
  end
39
58
 
59
+ # Check if the Series has the bucket
60
+ #
61
+ # @param bucket_name [String] Name of the Bucket
62
+ # @return [Boolean] does the bucket exist?
63
+ #
40
64
  def has_bucket?(bucket_name)
41
- @buckets[bucket_name.to_sym] != nil
65
+ @buckets[bucket_name.to_sym] != nil rescue false
42
66
  end
43
67
 
68
+ # Check if the bucket has the group
69
+ #
70
+ # @param bucket_name [String] Name of the Bucket
71
+ # @param group_name [String] Name of the Group
72
+ # @return [Boolean] does the group exist inside the bucket?
73
+ #
44
74
  def has_group_in_bucket?(bucket_name, group_name)
45
- has_bucket?(bucket_name) && @buckets[bucket_name.to_sym].has_group?(group_name)
75
+ has_bucket?(bucket_name) && @buckets[bucket_name.to_sym].has_group?(group_name) rescue false
46
76
  end
47
77
  end
48
78
  end
@@ -4,6 +4,8 @@ require 'bucket_maker/series'
4
4
  require 'bucket_maker/bucket'
5
5
 
6
6
  module BucketMaker
7
+ # Singleton which holds all information regarding the series, buckets and groups
8
+ #
7
9
  class SeriesMaker
8
10
  include Singleton
9
11
 
@@ -13,6 +15,10 @@ module BucketMaker
13
15
 
14
16
  BUCKET_ROOT = 'series'
15
17
 
18
+ # Set the class variables with configuration details
19
+ #
20
+ # @param config [String] Path of the config file WRT the rails app
21
+ #
16
22
  def make!(config)
17
23
  @series = []
18
24
 
@@ -28,10 +34,17 @@ module BucketMaker
28
34
  end
29
35
  end
30
36
 
37
+ # Check if the SeriesMaker is configured
38
+ #
39
+ # @return [Boolean] Signifies if the Object is configured
40
+ #
31
41
  def configured?
32
42
  @configuration != nil
33
43
  end
34
44
 
45
+ # Iterator for each series to be run on a Bucketable instance
46
+ # Expects a block parameter to be passed
47
+ #
35
48
  def for_each_series_with_bucketable
36
49
  @series.collect do |series_name, series|
37
50
  series.each_bucket do |bucket_name, bucket|
@@ -40,37 +53,81 @@ module BucketMaker
40
53
  end.inject(true) {|result, value| result && value } if block_given?
41
54
  end
42
55
 
56
+ # Get the Series object when given the series_name
57
+ #
58
+ # @param series_name [String] Series Name to search
59
+ # @return [BucketMaker::Series]
60
+ #
43
61
  def series_with_name(series_name)
44
- @series[series_name.to_sym]
62
+ @series[series_name.to_sym] if series_name
45
63
  end
46
64
 
65
+ # Check if the series exist
66
+ #
67
+ # @param series_name [String] Series Name to search
68
+ # @return [Boolean] is it there?
69
+ #
47
70
  def has_series?(series_name)
48
- @series[series_name.to_sym] != nil
71
+ @series[series_name.to_sym] != nil rescue false
49
72
  end
50
73
 
74
+ # Check if the bucket exist in the series
75
+ #
76
+ # @param series_name [String] Series Name to search
77
+ # @param bucket_name [String] Bucket Name to search
78
+ # @return [Boolean] is it there?
79
+ #
51
80
  def has_bucket_in_series?(series_name, bucket_name)
52
- has_series?(series_name) && series_with_name(series_name).has_bucket?(bucket_name)
81
+ has_series?(series_name) && series_with_name(series_name).has_bucket?(bucket_name) rescue false
53
82
  end
54
83
 
84
+ # Check if the group exists in the bucket in the series
85
+ #
86
+ # @param series_name [String] Series Name to search
87
+ # @param bucket_name [String] Bucket Name to search
88
+ # @param group_name [String] Group Name to search
89
+ # @return [Boolean] is it there?
90
+ #
55
91
  def has_group_in_bucket_in_series?(series_name, bucket_name, group_name)
56
92
  has_bucket_in_series?(series_name, bucket_name) &&
57
- series_with_name(series_name).bucket_with_name(bucket_name).has_group?(group_name)
93
+ series_with_name(series_name).bucket_with_name(bucket_name).has_group?(group_name) rescue false
58
94
  end
59
95
 
96
+ # Get the key for the combination
97
+ #
98
+ # @param bucketable [Object] any object which responds to :id
99
+ # @param series_name [String] Series Name
100
+ # @param bucket_name [String] Bucket Name
101
+ # @return [String] The key for future use
102
+ #
60
103
  def key_for_series(bucketable, series_name, bucket_name)
61
- "bucket_maker:#{bucketable.class.to_s.underscore}_#{bucketable.id}:#{series_name.to_s}:#{bucket_name.to_s}" if bucketable && bucketable.id
104
+ "bucket_maker:#{bucketable.class.to_s.underscore}_#{bucketable.id}:#{series_name.to_s}:#{bucket_name.to_s}" if bucketable && bucketable.id rescue nil
62
105
  end
63
106
 
107
+ # Get a random group for the bucket in a series
108
+ #
109
+ # @param series_name [String] Series Name
110
+ # @param bucket_name [String] Bucket Name
111
+ # @return [String] Random Group Name according to the distribution
112
+ #
64
113
  def bucketize(series_name, bucket_name)
65
- series_with_name(series_name).bucket_with_name(bucket_name).random_group
114
+ series_with_name(series_name).bucket_with_name(bucket_name).random_group rescue nil
66
115
  end
67
116
 
117
+ # Check if a Bucketable Object conform to the pre-conditions
118
+ #
119
+ # @param bucketable [Object] any object which has methods :has_attribute?, :created_at and :id
120
+ # @param series_name [String] Series Name
121
+ # @param bucket_name [String] Bucket Name
122
+ # @param group_name [String] Group Name
123
+ # @return [Boolean] is it bucketable?
124
+ #
68
125
  def bucketable?(bucketable, series_name, bucket_name, group_name)
69
126
  if bucketable.has_attribute?(:created_at) &&
70
127
  has_group_in_bucket_in_series?(series_name, bucket_name, group_name)
71
128
 
72
129
  series_with_name(series_name).bucket_with_name(bucket_name).is_bucketable?(bucketable) ||
73
- series_with_name(series_name).is_bucketable?(bucketable)
130
+ series_with_name(series_name).is_bucketable?(bucketable) rescue false
74
131
 
75
132
  else
76
133
  false
@@ -1,3 +1,5 @@
1
1
  module BucketMaker
2
- VERSION = "0.0.1"
2
+ # Get the version number
3
+ #
4
+ VERSION = "0.0.2"
3
5
  end
@@ -2,6 +2,8 @@ require 'rails/generators/active_record'
2
2
 
3
3
  module ActiveRecord
4
4
  module Generators
5
+ # Generator to create Active Record specific classes
6
+ #
5
7
  class BucketMakerGenerator < ActiveRecord::Generators::Base
6
8
 
7
9
  ACTIVE_RECORDABLE = 'bucket'
@@ -9,6 +11,10 @@ module ActiveRecord
9
11
  source_root File.expand_path("../../templates", __FILE__)
10
12
  argument :store_in, type: :string, default: 'redis'
11
13
 
14
+ # Generate the model
15
+ #
16
+ # If store_in is active_record then the ACTIVE_RECORDABLE is also created which holds association
17
+ #
12
18
  def generate_model
13
19
  invoke "active_record:model", [name], :migration => false unless model_exists? && behavior == :invoke
14
20
  if store_in == 'active_record'
@@ -16,6 +22,10 @@ module ActiveRecord
16
22
  end
17
23
  end
18
24
 
25
+ # Inject the content to the models
26
+ #
27
+ # If store_in is actice_record then the ACTIVE_RECORDABLE is also inserted with association
28
+ #
19
29
  def inject_bucket_maker_content
20
30
  contents = <<-CONTENT.strip_heredoc
21
31
  # Module Inclusion for BucketMaker
@@ -40,6 +50,8 @@ module ActiveRecord
40
50
  inject_for_active_recordable if store_in == 'active_record' && active_recordable_exists?
41
51
  end
42
52
 
53
+ # Content for association if store_in is active_record
54
+ #
43
55
  def inject_for_active_recordable
44
56
  ar_contents = <<-CONTENT.strip_heredoc
45
57
  # Association with the bucket
@@ -51,6 +63,10 @@ module ActiveRecord
51
63
  inject_into_class(active_recordable_path, ACTIVE_RECORDABLE.camelize, ar_contents)
52
64
  end
53
65
 
66
+ # Migration copier
67
+ #
68
+ # If store_in is actice_record then the migration runs
69
+ #
54
70
  def copy_bucket_maker_migration
55
71
  if behavior == :invoke && store_in == 'active_record' && active_recordable_exists?
56
72
  migration_template "active_recordable_migration.rb", "db/migrate/create_#{ACTIVE_RECORDABLE.pluralize}"
@@ -59,22 +75,32 @@ module ActiveRecord
59
75
 
60
76
  private
61
77
 
78
+ # Check if the MODEL exists
79
+ #
62
80
  def model_exists?
63
81
  File.exists?(File.join(destination_root, model_path))
64
82
  end
65
83
 
84
+ # Check if the association exists
85
+ #
66
86
  def active_recordable_exists?
67
87
  File.exists?(File.join(destination_root, active_recordable_path))
68
88
  end
69
89
 
90
+ # Get the association path
91
+ #
70
92
  def active_recordable_path
71
93
  @ar_path ||= File.join("app", "models", "#{ACTIVE_RECORDABLE}.rb")
72
94
  end
73
95
 
96
+ # Get the MODEL path
97
+ #
74
98
  def model_path
75
99
  @model_path ||= File.join("app", "models", "#{file_path}.rb")
76
100
  end
77
101
 
102
+ # Get the module name to the included for store_in values
103
+ #
78
104
  def module_name_for_include
79
105
  case store_in
80
106
  when 'redis'
@@ -2,6 +2,8 @@ require 'rails/generators/named_base'
2
2
 
3
3
  module BucketMaker
4
4
  module Generators
5
+ # Base Generator to set the namespace
6
+ #
5
7
  class BucketMakerGenerator < Rails::Generators::NamedBase
6
8
 
7
9
  namespace 'bucket_maker'
@@ -2,11 +2,15 @@ require 'rails/generators/base'
2
2
 
3
3
  module BucketMaker
4
4
  module Generators
5
+ # Installs the initializer
6
+ #
5
7
  class InstallGenerator < Rails::Generators::Base
6
8
  source_root File.expand_path("../../templates", __FILE__)
7
9
 
8
10
  desc "Creates a BucketMaker initializer"
9
11
 
12
+ # Copies the initializer bucket_maker from the templates and pastes
13
+ #
10
14
  def copy_initializer
11
15
  template "bucket_maker.rb", "config/initializers/bucket_maker.rb"
12
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bucket_maker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dinesh Vasudevan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-25 00:00:00.000000000 Z
11
+ date: 2013-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -337,3 +337,4 @@ test_files:
337
337
  - spec/unit/bucketable_spec.rb
338
338
  - spec/unit/series_maker_spec.rb
339
339
  - spec/unit/series_spec.rb
340
+ has_rdoc: