schofield 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.bundle/config +2 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +28 -0
  4. data/{LICENSE → LICENSE.txt} +1 -1
  5. data/README.rdoc +11 -9
  6. data/Rakefile +28 -24
  7. data/VERSION +1 -1
  8. data/lib/generators/schofield/association.rb +94 -0
  9. data/lib/generators/schofield/attribute.rb +76 -0
  10. data/lib/generators/schofield/attributes.rb +204 -0
  11. data/lib/generators/schofield/level.rb +287 -0
  12. data/lib/generators/schofield/levels.rb +74 -0
  13. data/lib/generators/schofield/responses.rb +46 -0
  14. data/lib/generators/schofield/routes.rb +46 -0
  15. data/lib/generators/schofield/schofield_generator.rb +124 -0
  16. data/lib/generators/templates/controller.erb +25 -0
  17. data/lib/generators/templates/form.erb +31 -0
  18. data/lib/generators/templates/index.erb +5 -0
  19. data/lib/generators/templates/join_controller.erb +15 -0
  20. data/lib/generators/templates/model.erb +109 -0
  21. data/lib/generators/templates/show.erb +21 -0
  22. data/schofield.gemspec +48 -46
  23. data/spec/spec_helper.rb +7 -4
  24. metadata +82 -47
  25. data/.gitignore +0 -21
  26. data/generators/schofield_controller/schofield_controller_generator.rb +0 -157
  27. data/generators/schofield_controller/templates/controller_spec.rb +0 -25
  28. data/generators/schofield_controller/templates/helper_spec.rb +0 -11
  29. data/generators/schofield_controller/templates/index_partial.rb +0 -26
  30. data/generators/schofield_controller/templates/nested/controller.rb +0 -106
  31. data/generators/schofield_controller/templates/nested/edit.rb +0 -5
  32. data/generators/schofield_controller/templates/nested/index.rb +0 -3
  33. data/generators/schofield_controller/templates/nested/new.rb +0 -1
  34. data/generators/schofield_controller/templates/nested/show.rb +0 -12
  35. data/generators/schofield_controller/templates/unnested/controller.rb +0 -94
  36. data/generators/schofield_controller/templates/unnested/edit.rb +0 -5
  37. data/generators/schofield_controller/templates/unnested/index.rb +0 -3
  38. data/generators/schofield_controller/templates/unnested/new.rb +0 -1
  39. data/generators/schofield_controller/templates/unnested/show.rb +0 -12
  40. data/generators/schofield_controller/templates/view_spec.rb +0 -12
  41. data/generators/schofield_form/schofield_form_generator.rb +0 -22
  42. data/generators/schofield_form/templates/view__form.html.haml +0 -11
  43. data/lib/schofield.rb +0 -111
  44. data/lib/schofield/tasks.rb +0 -3
  45. data/lib/schofield/tasks/schofield.rake +0 -7
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.1.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.1"
12
+ gem "rcov", ">= 0"
13
+ end
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.5.1)
7
+ bundler (~> 1.0.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.8.7)
11
+ rcov (0.9.9)
12
+ rspec (2.1.0)
13
+ rspec-core (~> 2.1.0)
14
+ rspec-expectations (~> 2.1.0)
15
+ rspec-mocks (~> 2.1.0)
16
+ rspec-core (2.1.0)
17
+ rspec-expectations (2.1.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.1.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ bundler (~> 1.0.0)
26
+ jeweler (~> 1.5.1)
27
+ rcov
28
+ rspec (~> 2.1.0)
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Marc Tauber
1
+ Copyright (c) 2010 Marc Tauber
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -2,16 +2,18 @@
2
2
 
3
3
  Description goes here.
4
4
 
5
- == Note on Patches/Pull Requests
5
+ == Contributing to schofield
6
6
 
7
- * Fork the project.
8
- * Make your feature addition or bug fix.
9
- * Add tests for it. This is important so I don't break it in a
10
- future version unintentionally.
11
- * Commit, do not mess with rakefile, version, or history.
12
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
- * Send me a pull request. Bonus points for topic branches.
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
14
 
15
15
  == Copyright
16
16
 
17
- Copyright (c) 2009 Marc Tauber. See LICENSE for details.
17
+ Copyright (c) 2010 Marc Tauber. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile CHANGED
@@ -1,38 +1,42 @@
1
1
  require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
2
10
  require 'rake'
3
11
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "schofield"
8
- gem.summary = %Q{Creates views and controller from defined routes and respective models}
9
- gem.description = %Q{Create views and controllers from routes defined in admin namespace. Very, very basic and very specific to my needs.'}
10
- gem.email = "marc@marctauber.com"
11
- gem.homepage = "http://github.com/sauberia/schofield"
12
- gem.authors = ["Marc Tauber"]
13
- gem.add_development_dependency "rspec", ">= 1.2.9"
14
- gem.add_development_dependency "formtastic", ">= 0.9.8"
15
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
- end
17
- Jeweler::GemcutterTasks.new
18
- rescue LoadError
19
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "schofield"
16
+ gem.homepage = "http://github.com/sauberia/schofield"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{one-line summary of your gem}
19
+ gem.description = %Q{longer description of your gem}
20
+ gem.email = "marc@marctauber.com"
21
+ gem.authors = ["Marc Tauber"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
20
26
  end
27
+ Jeweler::RubygemsDotOrgTasks.new
21
28
 
22
- require 'spec/rake/spectask'
23
- Spec::Rake::SpecTask.new(:spec) do |spec|
24
- spec.libs << 'lib' << 'spec'
25
- spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
26
33
  end
27
34
 
28
- Spec::Rake::SpecTask.new(:rcov) do |spec|
29
- spec.libs << 'lib' << 'spec'
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
30
36
  spec.pattern = 'spec/**/*_spec.rb'
31
37
  spec.rcov = true
32
38
  end
33
39
 
34
- task :spec => :check_dependencies
35
-
36
40
  task :default => :spec
37
41
 
38
42
  require 'rake/rdoctask'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.5
1
+ 0.2.0
@@ -0,0 +1,94 @@
1
+ module Schofield
2
+
3
+ module Generators
4
+
5
+ class Association
6
+
7
+ ONE_TO_ONE = '1-1'
8
+ ONE_TO_MANY = '1-*'
9
+
10
+
11
+
12
+ class << self; attr_accessor :all end
13
+ @all = []
14
+
15
+ def self.reference_parents
16
+ all.each { |a| a.reference_parent }
17
+ end
18
+
19
+ def self.report
20
+ all.each { |a| Responses.say a.report }
21
+ end
22
+
23
+
24
+
25
+ attr_reader :parent, :child, :parent_name, :child_name , :polymorphic_name
26
+ attr_writer :nest
27
+ attr_accessor :cardinality
28
+
29
+ def initialize child, parent_name, one_to_one, polymorphic_name=nil
30
+ @child = child
31
+ @child_name = child.name
32
+ @parent_name = parent_name
33
+ @polymorphic_name = polymorphic_name
34
+ @cardinality = one_to_one ? ONE_TO_ONE : ONE_TO_MANY
35
+ @nest = polymorphic_name.present? && !one_to_one
36
+ self.class.all << self
37
+ end
38
+
39
+ def nest?
40
+ @nest
41
+ end
42
+
43
+ def reference_parent
44
+ @parent = Levels.find(@parent_name)
45
+ @parent.child_associations << self
46
+ end
47
+
48
+ def report
49
+ <<-STRING.gsub(/^ {8}/, '')
50
+ parent: #{@parent.name}
51
+ child: #{@child.name}
52
+ nest: #{@nest ? 'yes' : 'no'}
53
+ cardinality: #{@cardinality}
54
+ polymorphic_name: #{@polymorphic_name}
55
+ ---
56
+ STRING
57
+ end
58
+
59
+ def one_to_one?
60
+ @cardinality == Association::ONE_TO_ONE
61
+ end
62
+
63
+ def one_to_many?
64
+ @cardinality == Association::ONE_TO_MANY
65
+ end
66
+
67
+ def polymorphic?
68
+ @polymorphic_name.present?
69
+ end
70
+
71
+ def non_polymorphic?
72
+ !polymorphic?
73
+ end
74
+
75
+ def polymorphic_one_to_one?
76
+ polymorphic? && one_to_one?
77
+ end
78
+
79
+ def polymorphic_one_to_many?
80
+ polymorphic? && one_to_many?
81
+ end
82
+
83
+ def non_polymorphic_one_to_one?
84
+ non_polymorphic? && one_to_one?
85
+ end
86
+
87
+ def non_polymorphic_one_to_many?
88
+ non_polymorphic? && one_to_many?
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,76 @@
1
+ module Schofield
2
+
3
+ module Generators
4
+
5
+ class Attribute
6
+
7
+ ATTACHMENT_IMAGE_NAMES = %w( image thumbnail enlargement photo avatar )
8
+
9
+ attr_reader :model_name, :name, :max_number, :max_length, :attachment_name, :type
10
+
11
+
12
+ def initialize column
13
+
14
+ if (match_data = column.name.match(/(.+)_file_name$/))
15
+ @attachment_name = match_data[1]
16
+ @attachment = true
17
+ @image = @attachment_name =~ /#{ATTACHMENT_IMAGE_NAMES.join('|')}/
18
+ end
19
+
20
+ if (match_data = column.name.match(/^(.+)_id$/))
21
+ @reference = true
22
+ @model_name = match_data[1]
23
+ end
24
+
25
+ @name = column.name
26
+ @required = !column.null
27
+ @type = column.type
28
+ @max_length = column.type == :string ? column.limit : nil
29
+ @max_number = column.type == :integer && !@reference ? 256**column.limit / 2 - 1 : nil
30
+
31
+ end
32
+
33
+ def reference?
34
+ @reference == true
35
+ end
36
+
37
+ def attachment?
38
+ @attachment == true
39
+ end
40
+
41
+ def image?
42
+ @image == 0
43
+ end
44
+
45
+ def required?
46
+ @required && !@attachment
47
+ end
48
+
49
+ def required_attachment?
50
+ @attachment && @required
51
+ end
52
+
53
+ def text?
54
+ type == :text
55
+ end
56
+
57
+ def boolean?
58
+ type == :boolean
59
+ end
60
+
61
+ def actual_name
62
+ @attachment_name || @model_name || @name
63
+ end
64
+
65
+ def to_column
66
+ case
67
+ when image? then "'#{actual_name.humanize} ', lambda { |x| image_tag(x.#{@attachment_name}.url(:thumbnail), :alt => '', :class => 'thumbnail') }"
68
+ when attachment? then "link_to('#{actual_name.humanize}', x.#{@attachment_name}.url)"
69
+ else "'#{actual_name.humanize}', lambda { |x| x.#{actual_name} }"
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,204 @@
1
+ module Schofield
2
+
3
+ module Generators
4
+
5
+ class Attributes
6
+
7
+ include Enumerable
8
+
9
+
10
+ def initialize
11
+ @attributes = []
12
+ @requireds = []
13
+ @required_one_to_ones = []
14
+ @attachments = []
15
+ @required_attachments = []
16
+ @max_numbers = {}
17
+ @max_lengths = {}
18
+ @references = 0
19
+ end
20
+
21
+
22
+ def new_attribute column, one_to_one
23
+
24
+ attribute = Attribute.new column
25
+ @attributes << attribute
26
+
27
+ @references += 1 if attribute.reference?
28
+
29
+ if attribute.required? && attribute.name != 'position' && !attribute.boolean?
30
+ if one_to_one then @required_one_to_ones << attribute.name
31
+ else @requireds << attribute.name
32
+ end
33
+ end
34
+
35
+ if attribute.attachment?
36
+ @attachments << attribute.attachment_name
37
+ @required_attachments << attribute.attachment_name if attribute.required_attachment?
38
+ end
39
+
40
+ if attribute.max_number
41
+ @max_numbers[attribute.max_number] ||= []
42
+ @max_numbers[attribute.max_number] << attribute.name
43
+ end
44
+
45
+ if attribute.max_length
46
+ @max_lengths[attribute.max_length] ||= []
47
+ @max_lengths[attribute.max_length] << attribute.name
48
+ end
49
+
50
+ attribute
51
+ end
52
+
53
+ def each
54
+ @attributes.each { |a| yield a }
55
+ end
56
+
57
+ def join?
58
+ @references == @attributes.select{ |a| a.name != 'position' }.count && @references == 2
59
+ end
60
+
61
+ def validations?
62
+ validations.any?
63
+ end
64
+
65
+ def attr_protecteds?
66
+ attr_protecteds.present?
67
+ end
68
+
69
+ def acts_as_markdowns?
70
+ acts_as_markdowns.present?
71
+ end
72
+
73
+ def attachments?
74
+ @attachments.any?
75
+ end
76
+
77
+ def validations
78
+ @validations ||= get_validations
79
+ end
80
+
81
+ def acts_as_markdowns
82
+ @acts_as_markdowns ||= (names = @attributes.select(&:text?).map(&:name)).any? ? "acts_as_markdown #{join_names(names)}" : ''
83
+ end
84
+
85
+ def to_s_string
86
+ case
87
+ when name? then 'name'
88
+ when title? then 'title'
89
+ when text? then 'text'
90
+ end
91
+ end
92
+
93
+ def attached_files
94
+ @attachments.map { |attachment_name|
95
+ string = "\n has_attached_file :#{attachment_name}, "
96
+ indentation = ' ' * (string.length - 1)
97
+ string += ":path => ':class/:id.:extension',\n"
98
+ string += indentation + ":storage => :s3,\n"
99
+ string += indentation + ":s3_credentials => \"\#{Rails.root}/config/s3.yml\",\n"
100
+ string += indentation + ":url => ':s3_domain_url'"
101
+ }.join("\n")
102
+ end
103
+
104
+
105
+
106
+ private
107
+
108
+ def attr_protecteds
109
+ @attr_protecteds ||= (@attachments.any? ? 'attr_protected :' + @attachments.map { |attachment_name|
110
+ self.select { |attribute|
111
+ (match_data = attribute.name.match(/^#{attachment_name}_(.+)$/)).present? && %w(file_name content_type file_size updated_at).include?(match_data[1])
112
+ }.map(&:name)
113
+ }.flatten.join(', :') : '')
114
+ end
115
+
116
+ def names_matching regex
117
+ self.select { |a| a.name.match(regex) }.map(&:name)
118
+ end
119
+
120
+ def join_names names
121
+ ":#{names.join(', :')}"
122
+ end
123
+
124
+ def get_validations
125
+ @validations = []
126
+ validate_presence
127
+ validate_presence_unless_nested
128
+ validate_length
129
+ validate_numericality
130
+ validate_email_address
131
+ validate_phone_number
132
+ validate_url
133
+ validate_boolean
134
+ validate_attachment_presence
135
+ @validations
136
+ end
137
+
138
+ def validate_presence
139
+ if (names = @requireds.map { |a| a.gsub(/_id$/, '') }).any?
140
+ @validations << "validates #{join_names(names)}, :presence => true"
141
+ end
142
+ end
143
+
144
+ def validate_boolean
145
+ if (booleans = select { |a| a.boolean? && a.required? }).any?
146
+ @validations << "validates #{join_names(booleans.map(&:name))}, :boolean => true"
147
+ end
148
+ if (booleans = select { |a| a.boolean? && !a.required? }).any?
149
+ @validations << "validates #{join_names(booleans.map(&:name))}, :boolean => true, :allow_nil => true"
150
+ end
151
+ end
152
+
153
+ def validate_presence_unless_nested
154
+ if (names = @required_one_to_ones.map { |a| a.gsub(/_id$/, '') }).any?
155
+ @validations << "validates #{join_names(names)}, :presence => true, :unless => :nested"
156
+ end
157
+ end
158
+
159
+ def validate_length
160
+ @max_lengths.each do |length, names|
161
+ @validations << "validates #{join_names(names)}, :length => { :maximum => #{length} }, :allow_nil => true"
162
+ end
163
+ end
164
+
165
+ def validate_numericality
166
+ @max_numbers.each do |number, names|
167
+ @validations << "validates #{join_names(names)}, :numericality => { :less_than_or_equal_to => #{number} }, :allow_nil => true"
168
+ end
169
+ end
170
+
171
+ def validate_email_address
172
+ if (names = names_matching(/email_address$/)).any?
173
+ @validations << "validates #{join_names(names)}, :email => true, :allow_nil => true"
174
+ end
175
+ end
176
+
177
+ def validate_phone_number
178
+ if (names = names_matching(/phone_number$/)).any?
179
+ @validations << "validates #{join_names(names)}, :phone_number => true, :allow_nil => true"
180
+ end
181
+ end
182
+
183
+ def validate_url
184
+ if (names = names_matching(/url$/)).any?
185
+ @validations << "validates #{join_names(names)}, :url => true, :allow_nil => true"
186
+ end
187
+ end
188
+
189
+ def validate_attachment_presence
190
+ @validations << "validates_attachment_presence #{join_names(@required_attachments)}" if @required_attachments.any?
191
+ end
192
+
193
+ private
194
+
195
+ def method_missing(method, *args, &block)
196
+ if match_data = method.to_s.match(/^(.+)\?$/)
197
+ self.find { |a| a.name == match_data[1] }.present?
198
+ end
199
+ end
200
+
201
+ end
202
+
203
+ end
204
+ end