learn_rails 0.0.0 → 0.0.1

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,7 @@
1
+ Given(/^PENDING/) do
2
+ pending
3
+ end
4
+
5
+ When(/^I type/) do
6
+ pending # either find the right aruba step definition or create one
7
+ end
@@ -0,0 +1,3 @@
1
+ Before do
2
+ @aruba_timeout_seconds = 5
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'coveralls'
2
+ Coveralls.wear_merged!
3
+
4
+ require "aruba/cucumber"
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'learn_rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "learn_rails"
8
+ spec.version = LearnRails::VERSION
9
+ spec.authors = ["Peter-Jan Celis"]
10
+ spec.email = ["pj@celis.org"]
11
+ spec.description = %q{Gem learn_rails shows you the ruby code behind rails magic.}
12
+ spec.summary = %q{Gem learn_rails shows you the ruby code behind rails magic.}
13
+ spec.homepage = "http://github.com/pjc/learn_rails"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", "~> 4.0.1"
22
+ spec.add_dependency "thor", "~> 0.18.1"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec", "~> 2.14.1"
27
+ spec.add_development_dependency "cucumber", "~> 1.3.9"
28
+ spec.add_development_dependency "aruba", "~> 0.5.3"
29
+ spec.add_development_dependency "debugger", "~> 1.6.2"
30
+ spec.add_development_dependency "coveralls", "~> 0.7.0"
31
+ end
data/lib/ext/hash.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def to_condition_string
3
+ self.symbolize_keys.to_s.delete("}").delete("{").gsub('=>', ' => ')
4
+ end
5
+ end
data/lib/learn_rails.rb CHANGED
@@ -1,3 +1,54 @@
1
- class LearnRails
2
- # Code to be added, just claiming RubyGems gem name
3
- end
1
+ require "learn_rails/version"
2
+ require "ext/hash"
3
+ require "learn_rails/associations"
4
+ require "learn_rails/associations/belongs_to"
5
+ require "learn_rails/associations/has_one"
6
+ require "learn_rails/associations/has_many"
7
+ require "learn_rails/accessors"
8
+ require "active_support/core_ext/string"
9
+
10
+ module LearnRails
11
+ def self.analyze(*magic)
12
+ if accessor? magic
13
+ remove_model_name_from_accessor magic
14
+ LearnRails::Accessors.code_for magic
15
+ elsif association? magic
16
+ ensure_model_name_for_association magic
17
+ LearnRails::Associations.code_for magic
18
+ else
19
+ error_message
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def self.accessor? magic
26
+ (magic[0..1] & ['attr_reader', 'attr_writer', 'attr_accessor']).any?
27
+ end
28
+
29
+ def self.remove_model_name_from_accessor magic
30
+ magic.shift unless ['attr_reader', 'attr_writer', 'attr_accessor'].include? magic[0]
31
+ magic
32
+ end
33
+
34
+ def self.association? magic
35
+ (magic[0..1] & ['belongs_to', 'has_one', 'has_many']).any?
36
+ end
37
+
38
+ def self.ensure_model_name_for_association magic
39
+ if ['has_one', 'has_many'].include? magic[0]
40
+ puts "What is the model name for this association?"
41
+ model_name = $stdin.gets.strip
42
+ magic.unshift model_name
43
+ elsif magic[0] == 'belongs_to'
44
+ magic.unshift 'token value for params[:model]'
45
+ end
46
+ end
47
+
48
+ def self.error_message
49
+ <<-error.gsub(/^\s+/, '')
50
+ No ruby code available.
51
+ See http://www.github.com/pjc/learn_rails for list of valid instructions.
52
+ error
53
+ end
54
+ end
@@ -0,0 +1,56 @@
1
+ module LearnRails
2
+ class Accessors
3
+ def self.code_for(accessor)
4
+ @accessor = accessor
5
+ @code = <<-code.gsub(/^\s+/, '')
6
+ code
7
+
8
+ attributes.each do |attribute|
9
+ @code << getter_method_for(attribute) if getter_method_needed?
10
+ @code << setter_method_for(attribute) if setter_method_needed?
11
+ end
12
+
13
+ @code
14
+ end
15
+
16
+ private
17
+
18
+ def self.attributes
19
+ @accessor.drop(1).map { |attr| attr.delete(',').delete(':') }.delete_if(&:empty?)
20
+ end
21
+
22
+ def self.getter_method_needed?
23
+ @getter ||= ['reader', 'accessor'].include? accessor_type
24
+ end
25
+
26
+ def self.setter_method_needed?
27
+ @setter ||= ['writer', 'accessor'].include? accessor_type
28
+ end
29
+
30
+ def self.accessor_type
31
+ @accessor[0].split('_')[1]
32
+ end
33
+
34
+ def self.getter_method_for attribute
35
+ <<-code.gsub(/^\s+/, '')
36
+ #{empty_comment_line_if_needed}
37
+ # def #{attribute}
38
+ # @#{attribute}
39
+ # end
40
+ code
41
+ end
42
+
43
+ def self.setter_method_for attribute
44
+ <<-code.gsub(/^\s+/, '')
45
+ #{empty_comment_line_if_needed}
46
+ # def #{attribute}=(value)
47
+ # @#{attribute} = value
48
+ # end
49
+ code
50
+ end
51
+
52
+ def self.empty_comment_line_if_needed
53
+ @code.present? ? '#' : nil
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ module LearnRails
2
+ class Associations
3
+ def self.code_for(association)
4
+ params = params association
5
+ "LearnRails::Associations::#{params[:association].camelize}".constantize.send(:code_for, params)
6
+ end
7
+
8
+ private
9
+
10
+ def self.params association
11
+ clean_up association
12
+ hashify_conditions_options association
13
+
14
+ params = {}
15
+ params[:model] = association.shift.downcase
16
+ params[:association] = association.shift
17
+ params[:associate] = association.shift
18
+
19
+ options_specified = Hash[*association].symbolize_keys!
20
+
21
+ params.merge!(options_specified)
22
+ end
23
+
24
+ def self.clean_up association
25
+ association.delete "=>"
26
+ association.map! { |e| e.delete(':').delete(',').delete('\"') }
27
+ end
28
+
29
+ def self.hashify_conditions_options association
30
+ return association unless association.include? "conditions"
31
+
32
+ start_options_index = association.index("conditions") + 1
33
+ end_options_index = association[start_options_index..-1].find_index { |e| e.match /}/ } + start_options_index
34
+
35
+ conditions = []
36
+ association[start_options_index..end_options_index].each do |option|
37
+ conditions << option.delete('{').delete('}') if option.length > 1
38
+ association.delete(option)
39
+ end
40
+
41
+ association.insert(start_options_index, Hash[*conditions])
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ module LearnRails
2
+ class Associations::BelongsTo < Associations
3
+ def self.code_for(params)
4
+ associate_model = (params[:class_name] || params[:associate]).camelize
5
+ foreign_id = params[:foreign_key] || params[:associate] + "_id"
6
+ primary_id = params[:primary_key] || "id"
7
+
8
+ <<-code.gsub(/^\s+/, '')
9
+ # def #{params[:associate]}(force_reload = false)
10
+ # @#{params[:associate]} = nil if force_reload
11
+ # @#{params[:associate]} ||= #{finder_method params, foreign_id, associate_model}
12
+ # end
13
+ #{ setter_method(params, foreign_id, primary_id) unless params[:readonly] }
14
+ #
15
+ # def build_#{params[:associate]}(attributes = {})
16
+ # self.#{params[:associate]} = #{associate_model}.new(attributes)
17
+ # end
18
+ #
19
+ # def create_#{params[:associate]}(attributes = {})
20
+ # self.#{params[:associate]} = #{associate_model}.create(attributes)
21
+ # end
22
+ #
23
+ # def create_#{params[:associate]}!(attributes = {})
24
+ # self.#{params[:associate]} = #{associate_model}.create!(attributes)
25
+ # end
26
+ code
27
+ end
28
+
29
+ private
30
+
31
+ def self.setter_method params, foreign_id, primary_id
32
+ <<-code.gsub(/^\s+/, '')
33
+ #
34
+ # def #{params[:associate]}=(#{params[:associate]})
35
+ # self.#{foreign_id} = #{params[:associate]}.#{primary_id}
36
+ # end
37
+ code
38
+ end
39
+
40
+ def self.finder_method params, foreign_id, associate_model
41
+ if params[:conditions]
42
+ "#{associate_model}.first(:conditions => {:id => self.#{foreign_id}, #{params[:conditions].to_condition_string}})"
43
+ else
44
+ "#{associate_model}.find_by_id(self.#{foreign_id})"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,13 @@
1
+ module LearnRails
2
+ class Associations::HasMany < Associations
3
+ def self.code_for(params)
4
+ associate_model = params[:associate].singularize.camelize
5
+
6
+ <<-code.gsub(/^\s+/, '')
7
+ # def #{params[:associate]}
8
+ # #{associate_model}.where(#{params[:model]}_id: self.id)
9
+ # end
10
+ code
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,52 @@
1
+ module LearnRails
2
+ class Associations::HasOne < Associations
3
+ def self.code_for(params)
4
+ associate_model = (params[:class_name] || params[:associate]).camelize
5
+ foreign_id = params[:foreign_key] || params[:model] + "_id"
6
+ primary_id = params[:primary_key] || "id"
7
+
8
+ <<-code.gsub(/^\s+/, '')
9
+ # def #{params[:associate]}(force_reload = false)
10
+ # @#{params[:associate]} = nil if force_reload
11
+ # @#{params[:associate]} ||= #{finder_method params, foreign_id, primary_id, associate_model}
12
+ # end
13
+ #{ setter_method(params, foreign_id, primary_id) unless params[:readonly] }
14
+ #
15
+ # def build_#{params[:associate]}(attributes = {})
16
+ # attributes[:#{foreign_id}] = self.#{primary_id}
17
+ # #{associate_model}.new(attributes)
18
+ # end
19
+ #
20
+ # def create_#{params[:associate]}(attributes = {})
21
+ # attributes[:#{foreign_id}] = self.#{primary_id}
22
+ # #{associate_model}.create(attributes)
23
+ # end
24
+ #
25
+ # def create_#{params[:associate]}!(attributes = {})
26
+ # attributes[:#{foreign_id}] = self.#{primary_id}
27
+ # #{associate_model}.create!(attributes)
28
+ # end
29
+ code
30
+ end
31
+
32
+ private
33
+
34
+ def self.setter_method params, foreign_id, primary_id
35
+ <<-code.gsub(/^\s+/, '')
36
+ #
37
+ # def #{params[:associate]}=(#{params[:associate]})
38
+ # #{params[:associate]}.#{foreign_id} = self.#{primary_id}
39
+ # #{params[:associate]}.save
40
+ # end
41
+ code
42
+ end
43
+
44
+ def self.finder_method params, foreign_id, primary_id, associate_model
45
+ if params[:conditions]
46
+ "#{associate_model}.first(:conditions => {:#{foreign_id} => self.#{primary_id}, #{params[:conditions].to_condition_string}})"
47
+ else
48
+ "#{associate_model}.find_by_#{foreign_id}(self.#{primary_id})"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ require 'thor'
2
+ require 'learn_rails'
3
+
4
+ module LearnRails
5
+ class CLI < Thor
6
+ desc "rails MAGIC", "Prints out the ruby code behind any rails magic line"
7
+ def rails(*magic)
8
+ puts LearnRails.analyze(*magic)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module LearnRails
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,142 @@
1
+ require 'spec_helper'
2
+
3
+ @accessors
4
+ describe LearnRails::Accessors do
5
+
6
+ after(@accessors) do
7
+ LearnRails::Accessors.instance_variable_set(:@getter, nil)
8
+ LearnRails::Accessors.instance_variable_set(:@setter, nil)
9
+ end
10
+
11
+ context "attr" do
12
+ context "reader" do
13
+ context "with one attribute" do
14
+ it "should return the correct code" do
15
+ LearnRails::Accessors.code_for(%w(attr_reader :name)).should eql attr_reader_code
16
+ end
17
+ end
18
+
19
+ context "with multiple attributes" do
20
+ it "should return the correct code" do
21
+ LearnRails::Accessors.code_for(%w(attr_reader :name, :another)).should eql attr_reader_two_attributes_code
22
+ end
23
+ end
24
+ end
25
+
26
+ context "writer" do
27
+ context "with one attribute" do
28
+ it "should return the correct code" do
29
+ LearnRails::Accessors.code_for(%w(attr_writer :name)).should eql attr_writer_code
30
+ end
31
+ end
32
+
33
+ context "with multiple attributes" do
34
+ it "should return the correct code" do
35
+ LearnRails::Accessors.code_for(%w(attr_writer :name, :another)).should eql attr_writer_two_attributes_code
36
+ end
37
+ end
38
+ end
39
+
40
+ context "accessor" do
41
+ context "with one attribute" do
42
+ it "should return the correct code" do
43
+ LearnRails::Accessors.code_for(%w(attr_accessor :name)).should eql attr_accessor_code
44
+ end
45
+ end
46
+
47
+ context "with multiple attributes" do
48
+ it "should return the correct code" do
49
+ LearnRails::Accessors.code_for(%w(attr_accessor :name, :another)).should eql attr_accessor_two_attributes_code
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ context "with comma" do
56
+ context "right after the last attribute" do
57
+ it "should return the correct code" do
58
+ LearnRails::Accessors.code_for(%w(attr_accessor :name,)).should eql attr_accessor_code
59
+ end
60
+ end
61
+
62
+ context "seperated by a space" do
63
+ it "should return the correct code" do
64
+ LearnRails::Accessors.code_for(%w(attr_accessor :name ,)).should eql attr_accessor_code
65
+ end
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ def attr_reader_code
72
+ <<-code.gsub(/^\s+/, '')
73
+ # def name
74
+ # @name
75
+ # end
76
+ code
77
+ end
78
+
79
+ def attr_writer_code
80
+ <<-code.gsub(/^\s+/, '')
81
+ # def name=(value)
82
+ # @name = value
83
+ # end
84
+ code
85
+ end
86
+
87
+ def attr_accessor_code
88
+ <<-code.gsub(/^\s+/, '')
89
+ # def name
90
+ # @name
91
+ # end
92
+ #
93
+ # def name=(value)
94
+ # @name = value
95
+ # end
96
+ code
97
+ end
98
+
99
+ def attr_reader_two_attributes_code
100
+ <<-code.gsub(/^\s+/, '')
101
+ # def name
102
+ # @name
103
+ # end
104
+ #
105
+ # def another
106
+ # @another
107
+ # end
108
+ code
109
+ end
110
+
111
+ def attr_writer_two_attributes_code
112
+ <<-code.gsub(/^\s+/, '')
113
+ # def name=(value)
114
+ # @name = value
115
+ # end
116
+ #
117
+ # def another=(value)
118
+ # @another = value
119
+ # end
120
+ code
121
+ end
122
+
123
+ def attr_accessor_two_attributes_code
124
+ <<-code.gsub(/^\s+/, '')
125
+ # def name
126
+ # @name
127
+ # end
128
+ #
129
+ # def name=(value)
130
+ # @name = value
131
+ # end
132
+ #
133
+ # def another
134
+ # @another
135
+ # end
136
+ #
137
+ # def another=(value)
138
+ # @another = value
139
+ # end
140
+ code
141
+ end
142
+ end