learn_rails 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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