schofield 0.2.2 → 0.3.0

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.
data/.rvmrc ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ree-1.8.7-2011.03@schofield"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create use "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ return 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]]
45
+ # then
46
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47
+ # fi
48
+
49
+ # If you use bundler, this might be useful to you:
50
+ # if command -v bundle && [[ -s Gemfile ]]
51
+ # then
52
+ # bundle install
53
+ # fi
54
+
55
+ if [[ $- == *i* ]] # check for interactive shells
56
+ then
57
+ echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
58
+ else
59
+ echo "Using: $GEM_HOME" # don't use colors in interactive shells
60
+ fi
61
+
@@ -1,14 +1,14 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- diff-lcs (1.1.2)
4
+ diff-lcs (1.1.3)
5
5
  git (1.2.5)
6
- jeweler (1.5.1)
6
+ jeweler (1.5.2)
7
7
  bundler (~> 1.0.0)
8
8
  git (>= 1.2.5)
9
9
  rake
10
- rake (0.8.7)
11
- rcov (0.9.9)
10
+ rake (0.9.2.2)
11
+ rcov (0.9.11)
12
12
  rspec (2.1.0)
13
13
  rspec-core (~> 2.1.0)
14
14
  rspec-expectations (~> 2.1.0)
@@ -3,7 +3,7 @@
3
3
  Description goes here.
4
4
 
5
5
  == Contributing to schofield
6
-
6
+
7
7
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
8
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
9
  * Fork the project
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.0
@@ -1,31 +1,31 @@
1
1
  module Schofield
2
-
2
+
3
3
  module Generators
4
-
4
+
5
5
  class Association
6
-
6
+
7
7
  ONE_TO_ONE = '1-1'
8
8
  ONE_TO_MANY = '1-*'
9
-
10
-
11
-
9
+
10
+
11
+
12
12
  class << self; attr_accessor :all end
13
13
  @all = []
14
-
14
+
15
15
  def self.reference_parents
16
16
  all.each { |a| a.reference_parent }
17
17
  end
18
-
18
+
19
19
  def self.report
20
20
  all.each { |a| Responses.say a.report }
21
21
  end
22
-
23
-
24
-
22
+
23
+
24
+
25
25
  attr_reader :parent, :child, :parent_name, :child_name , :polymorphic_name
26
26
  attr_writer :nest
27
27
  attr_accessor :cardinality
28
-
28
+
29
29
  def initialize child, parent_name, one_to_one, polymorphic_name=nil
30
30
  @child = child
31
31
  @child_name = child.name
@@ -35,16 +35,16 @@ module Schofield
35
35
  @nest = polymorphic_name.present? && !one_to_one
36
36
  self.class.all << self
37
37
  end
38
-
38
+
39
39
  def nest?
40
40
  @nest
41
41
  end
42
-
42
+
43
43
  def reference_parent
44
44
  @parent = Levels.find(@parent_name)
45
45
  @parent.child_associations << self
46
46
  end
47
-
47
+
48
48
  def report
49
49
  <<-STRING.gsub(/^ {8}/, '')
50
50
  parent: #{@parent.name}
@@ -55,40 +55,40 @@ module Schofield
55
55
  ---
56
56
  STRING
57
57
  end
58
-
58
+
59
59
  def one_to_one?
60
60
  @cardinality == Association::ONE_TO_ONE
61
61
  end
62
-
62
+
63
63
  def one_to_many?
64
64
  @cardinality == Association::ONE_TO_MANY
65
65
  end
66
-
66
+
67
67
  def polymorphic?
68
68
  @polymorphic_name.present?
69
69
  end
70
-
70
+
71
71
  def non_polymorphic?
72
72
  !polymorphic?
73
73
  end
74
-
74
+
75
75
  def polymorphic_one_to_one?
76
76
  polymorphic? && one_to_one?
77
77
  end
78
-
78
+
79
79
  def polymorphic_one_to_many?
80
80
  polymorphic? && one_to_many?
81
81
  end
82
-
82
+
83
83
  def non_polymorphic_one_to_one?
84
84
  non_polymorphic? && one_to_one?
85
85
  end
86
-
86
+
87
87
  def non_polymorphic_one_to_many?
88
88
  non_polymorphic? && one_to_many?
89
89
  end
90
90
 
91
91
  end
92
-
92
+
93
93
  end
94
94
  end
@@ -1,87 +1,104 @@
1
1
  module Schofield
2
-
2
+
3
3
  module Generators
4
-
4
+
5
5
  class Attribute
6
-
6
+
7
7
  ATTACHMENT_IMAGE_NAMES = %w( image thumbnail enlargement photo avatar )
8
-
8
+
9
9
  attr_reader :model_name, :name, :max_number, :max_length, :attachment_name, :type
10
-
11
-
10
+
11
+
12
12
  def initialize column
13
-
13
+
14
14
  if (match_data = column.name.match(/(.+)_file_name$/))
15
15
  @attachment_name = match_data[1]
16
16
  @attachment = true
17
- @image = @attachment_name =~ /#{ATTACHMENT_IMAGE_NAMES.join('|')}/
17
+ @image = !!(@attachment_name =~ /#{ATTACHMENT_IMAGE_NAMES.join('|')}/)
18
18
  end
19
-
19
+
20
20
  if (match_data = column.name.match(/^(.+)_id$/))
21
- @reference = true
22
- @model_name = match_data[1]
21
+ model_name = match_data[1]
22
+ if Levels.exists?(model_name)
23
+ @model_name = model_name
24
+ @reference = true
25
+ end
23
26
  end
24
-
27
+
25
28
  @name = column.name
26
29
  @required = !column.null
27
30
  @type = column.type
28
31
  @max_length = column.type == :string ? column.limit : nil
29
32
  @max_number = column.type == :integer && !@reference ? 256**column.limit / 2 - 1 : nil
30
-
33
+
31
34
  end
32
-
35
+
33
36
  def reference?
34
37
  @reference == true
35
38
  end
36
-
39
+
37
40
  def attachment?
38
41
  @attachment == true
39
42
  end
40
-
43
+
41
44
  def image?
42
- @image == 0
45
+ @image
43
46
  end
44
-
47
+
45
48
  def required?
46
49
  @required && !@attachment
47
50
  end
48
-
51
+
52
+ def validate_presence?
53
+ required? && @name != 'position' && !boolean? && !fingerprint? && @name != 'slug'
54
+ end
55
+
49
56
  def required_attachment?
50
57
  @attachment && @required
51
58
  end
52
-
59
+
53
60
  def text?
54
61
  type == :text
55
62
  end
56
-
63
+
57
64
  def boolean?
58
65
  type == :boolean
59
66
  end
60
-
67
+
61
68
  def actual_name
62
69
  @attachment_name || @model_name || @name
63
70
  end
64
-
71
+
72
+ def fingerprint?
73
+ !!(@name =~ /_fingerprint$/)
74
+ end
75
+
76
+ def accessible_name
77
+ actual_name unless fingerprint? || @name == 'slug'
78
+ end
79
+
65
80
  def to_column
66
81
  "'#{actual_name.humanize}', lambda { |x| " +
67
82
  case
68
- when image? then "image_tag(x.#{@attachment_name}.url(:thumbnail), :alt => '', :class => 'thumbnail')"
83
+ when image? then "image_tag(x.#{@attachment_name}.url(:admin), :alt => '', :class => 'thumbnail')"
69
84
  when attachment? then "link_to('#{actual_name.humanize}', x.#{@attachment_name}.url)"
85
+ when boolean? then "x.#{actual_name} ? '✓' : ''"
70
86
  else "x.#{actual_name}"
71
87
  end + ' }'
72
88
  end
73
-
89
+
74
90
  def weight
75
91
  case
76
- when image? then 1
77
- when @name == 'name' then 2
78
- when @name == 'title' then 3
79
- when reference? then 4
80
- else 5
92
+ when image? then 1
93
+ when @name == 'name' then 2
94
+ when @name == 'title' then 3
95
+ when reference? then 4
96
+ when @name == 'published' then 6
97
+ else 5
81
98
  end
82
99
  end
83
-
100
+
84
101
  end
85
-
102
+
86
103
  end
87
104
  end
@@ -1,87 +1,87 @@
1
1
  module Schofield
2
-
2
+
3
3
  module Generators
4
-
4
+
5
5
  class Attributes
6
-
6
+
7
7
  include Enumerable
8
-
9
-
8
+
9
+
10
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
11
+ @attributes = []
12
+ @presence_validateds = []
13
+ @presence_validated_one_to_ones = []
14
+ @attachments = []
15
+ @required_attachments = []
16
+ @accessibles = []
17
+ @max_numbers = {}
18
+ @max_lengths = {}
19
+ @references_count = 0
19
20
  end
20
-
21
-
21
+
22
+
22
23
  def new_attribute column, one_to_one
23
-
24
+
24
25
  attribute = Attribute.new column
25
26
  @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
27
+
28
+ @references_count += 1 if attribute.reference?
29
+
30
+ if attribute.validate_presence?
31
+ if one_to_one then @presence_validated_one_to_ones << attribute
32
+ else @presence_validateds << attribute
32
33
  end
33
34
  end
34
-
35
+
35
36
  if attribute.attachment?
36
- @attachments << attribute.attachment_name
37
- @required_attachments << attribute.attachment_name if attribute.required_attachment?
37
+ @attachments << attribute
38
+ @required_attachments << attribute if attribute.required_attachment?
38
39
  end
39
-
40
+
40
41
  if attribute.max_number
41
42
  @max_numbers[attribute.max_number] ||= []
42
43
  @max_numbers[attribute.max_number] << attribute.name
43
44
  end
44
-
45
+
45
46
  if attribute.max_length
46
47
  @max_lengths[attribute.max_length] ||= []
47
48
  @max_lengths[attribute.max_length] << attribute.name
48
49
  end
49
50
 
51
+ accessible_name = attribute.accessible_name
52
+ @accessibles << accessible_name if accessible_name.present?
53
+
50
54
  attribute
51
55
  end
52
-
56
+
53
57
  def each
54
58
  @attributes.each { |a| yield a }
55
59
  end
56
-
60
+
57
61
  def join?
58
- @references == @attributes.select{ |a| a.name != 'position' }.count && @references == 2
62
+ @references_count == @attributes.select{ |a| a.name != 'position' }.count && @references_count == 2
59
63
  end
60
-
64
+
61
65
  def validations?
62
66
  validations.any?
63
67
  end
64
-
65
- def attr_protecteds?
66
- attr_protecteds.present?
68
+
69
+ def attr_accessors?
70
+ attr_accessors.present?
67
71
  end
68
-
69
- def acts_as_markdowns?
70
- acts_as_markdowns.present?
72
+
73
+ def attr_accessibles?
74
+ attr_accessibles.present?
71
75
  end
72
-
76
+
73
77
  def attachments?
74
78
  @attachments.any?
75
79
  end
76
-
80
+
77
81
  def validations
78
82
  @validations ||= get_validations
79
83
  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
-
84
+
85
85
  def to_s_string
86
86
  case
87
87
  when name? then 'name'
@@ -89,116 +89,117 @@ module Schofield
89
89
  when text? then 'text'
90
90
  end
91
91
  end
92
-
92
+
93
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")
94
+ @attachments.map { |attribute|
95
+ "\n has_attached_file :#{attribute.attachment_name}, {" + (attribute.image? ? image_attachment(name) : non_image_attachment(name)) + "\n }.merge(S3_ATTACHMENT_INFO)"
96
+ }.join("\n")
102
97
  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)
98
+
99
+ def attr_accessors
100
+ @attr_accessors ||= (@attachments.any? ? 'attr_accessor :' + @attachments.map { |attribute|
101
+ %w( _content_type _file_size ).map{ |suffix| "#{attribute.attachment_name}#{suffix}" } + (attribute.image? ? ["#{attribute.attachment_name}_dimensions"] : [])
113
102
  }.flatten.join(', :') : '')
114
103
  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
104
+
105
+ def attr_accessibles
106
+ @attr_accessibles ||= @accessibles.any? ? 'attr_accessible :' + @accessibles.join(', :') : ''
136
107
  end
137
-
138
- def validate_presence
139
- if (names = @requireds.map { |a| a.gsub(/_id$/, '') }).any?
140
- @validations << "validates #{join_names(names)}, :presence => true"
108
+
109
+
110
+
111
+ private
112
+
113
+ def names_matching regex
114
+ self.select { |a| a.name.match(regex) }.map(&:name)
141
115
  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"
116
+
117
+ def join_names names
118
+ ":#{names.join(', :')}"
147
119
  end
148
- if (booleans = select { |a| a.boolean? && !a.required? }).any?
149
- @validations << "validates #{join_names(booleans.map(&:name))}, :boolean => true, :allow_nil => true"
120
+
121
+ def get_validations
122
+ @validations = []
123
+ validate_presence
124
+ validate_presence_unless_nested
125
+ validate_length
126
+ validate_numericality
127
+ validate_email_address
128
+ validate_phone_number
129
+ validate_url
130
+ validate_attachments
131
+ @validations
150
132
  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"
133
+
134
+ def validate_presence
135
+ if (names = @presence_validateds.map(&:actual_name)).any?
136
+ @validations << "validates #{join_names(names)}, :presence => true"
137
+ end
156
138
  end
157
- end
158
139
 
159
- def validate_length
160
- @max_lengths.each do |length, names|
161
- @validations << "validates #{join_names(names)}, :length => { :maximum => #{length} }, :allow_nil => true"
140
+ def validate_presence_unless_nested
141
+ if (names = @presence_validated_one_to_ones.map(&:actual_name)).any?
142
+ @validations << "validates #{join_names(names)}, :presence => true, :unless => :nested"
143
+ end
162
144
  end
163
- end
164
145
 
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"
146
+ def validate_length
147
+ @max_lengths.each do |length, names|
148
+ @validations << "validates #{join_names(names)}, :length => { :maximum => #{length} }, :allow_nil => true"
149
+ end
168
150
  end
169
- end
170
151
 
171
- def validate_email_address
172
- if (names = names_matching(/email_address$/)).any?
173
- @validations << "validates #{join_names(names)}, :email => true, :allow_nil => true"
152
+ def validate_numericality
153
+ @max_numbers.each do |number, names|
154
+ @validations << "validates #{join_names(names)}, :numericality => { :less_than_or_equal_to => #{number} }, :allow_nil => true"
155
+ end
156
+ end
157
+
158
+ def validate_email_address
159
+ if (names = names_matching(/email_address$/)).any?
160
+ @validations << "validates #{join_names(names)}, :email => true, :allow_nil => true"
161
+ end
174
162
  end
175
- end
176
163
 
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"
164
+ def validate_phone_number
165
+ if (names = names_matching(/phone_number$/)).any?
166
+ @validations << "validates #{join_names(names)}, :phone_number => true, :allow_nil => true"
167
+ end
180
168
  end
181
- end
182
169
 
183
- def validate_url
184
- if (names = names_matching(/url$/)).any?
185
- @validations << "validates #{join_names(names)}, :url => true, :allow_nil => true"
170
+ def validate_url
171
+ if (names = names_matching(/url$/)).any?
172
+ @validations << "validates #{join_names(names)}, :url => true, :allow_nil => true"
173
+ end
186
174
  end
187
- end
188
175
 
189
- def validate_attachment_presence
190
- @validations << "validates_attachment_presence #{join_names(@required_attachments)}" if @required_attachments.any?
191
- end
192
-
193
- private
176
+ def validate_attachments
177
+ @attachments.each do |attribute|
178
+ name = attribute.attachment_name
179
+ @validations << "validates_attachment_presence :#{name}" if attribute.required_attachment?
180
+ @validations << "validates_attachment_content_type :#{name}, Rails.configuration.bodmin.image_content_type" if attribute.image?
181
+ @validations << "validates_attachment_size :#{name}, :less_than => 10.megabytes"
182
+ @validations << "validates_attachment_dimensions :#{name}, :width => 1..Infinity, :height => 1..Infinity" if attribute.image?
183
+ end
184
+ end
185
+
186
+ def image_attachment name
187
+ "\n :styles => { :admin => '96x78#' }," +
188
+ "\n :path => 'images/:class_with_thumbnails/:id/:fingerprint.:extension'," +
189
+ "\n :convert_options => { :admin => \"-colorspace RGB -strip \#{Rails.configuration.bodmin.image_quality}\" }"
190
+ end
191
+
192
+ def non_image_attachment name
193
+ "\n :path => 'downloads/:class/:id/:fingerprint.:extension'"
194
+ end
194
195
 
195
196
  def method_missing(method, *args, &block)
196
197
  if match_data = method.to_s.match(/^(.+)\?$/)
197
198
  self.find { |a| a.name == match_data[1] }.present?
198
199
  end
199
200
  end
200
-
201
+
201
202
  end
202
-
203
+
203
204
  end
204
205
  end