hobo_fields 1.3.0.RC
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +38 -0
- data/LICENSE.txt +22 -0
- data/README.txt +8 -0
- data/Rakefile +36 -0
- data/VERSION +1 -0
- data/bin/hobofields +19 -0
- data/hobo_fields.gemspec +31 -0
- data/lib/generators/hobo/migration/USAGE +47 -0
- data/lib/generators/hobo/migration/migration_generator.rb +162 -0
- data/lib/generators/hobo/migration/migrator.rb +445 -0
- data/lib/generators/hobo/migration/templates/migration.rb.erb +9 -0
- data/lib/generators/hobo/model/USAGE +19 -0
- data/lib/generators/hobo/model/model_generator.rb +11 -0
- data/lib/generators/hobo/model/templates/model_injection.rb.erb +18 -0
- data/lib/hobo_fields/extensions/active_record/attribute_methods.rb +48 -0
- data/lib/hobo_fields/extensions/active_record/fields_declaration.rb +21 -0
- data/lib/hobo_fields/field_declaration_dsl.rb +33 -0
- data/lib/hobo_fields/model/field_spec.rb +121 -0
- data/lib/hobo_fields/model/index_spec.rb +47 -0
- data/lib/hobo_fields/model.rb +226 -0
- data/lib/hobo_fields/railtie.rb +13 -0
- data/lib/hobo_fields/sanitize_html.rb +23 -0
- data/lib/hobo_fields/types/email_address.rb +26 -0
- data/lib/hobo_fields/types/enum_string.rb +101 -0
- data/lib/hobo_fields/types/html_string.rb +15 -0
- data/lib/hobo_fields/types/lifecycle_state.rb +16 -0
- data/lib/hobo_fields/types/markdown_string.rb +15 -0
- data/lib/hobo_fields/types/password_string.rb +15 -0
- data/lib/hobo_fields/types/raw_html_string.rb +13 -0
- data/lib/hobo_fields/types/raw_markdown_string.rb +13 -0
- data/lib/hobo_fields/types/serialized_object.rb +15 -0
- data/lib/hobo_fields/types/text.rb +16 -0
- data/lib/hobo_fields/types/textile_string.rb +22 -0
- data/lib/hobo_fields.rb +94 -0
- data/test/api.rdoctest +244 -0
- data/test/doc-only.rdoctest +96 -0
- data/test/generators.rdoctest +53 -0
- data/test/interactive_primary_key.rdoctest +54 -0
- data/test/migration_generator.rdoctest +639 -0
- data/test/migration_generator_comments.rdoctest +75 -0
- data/test/prepare_testapp.rb +8 -0
- data/test/rich_types.rdoctest +394 -0
- metadata +140 -0
data/CHANGES.txt
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
== HoboFields 0.7.4 ==
|
2
|
+
|
3
|
+
Fix to using the migration generator with STI
|
4
|
+
|
5
|
+
HoboFields::Text - fix to to_html
|
6
|
+
|
7
|
+
Ensure that the bundled rich types are only loaded on demand
|
8
|
+
|
9
|
+
HoboFields::TextileString -- adding require 'redcloth'
|
10
|
+
|
11
|
+
Fix for HoboFields::EnumString -- couldn't set values using
|
12
|
+
symbols
|
13
|
+
|
14
|
+
Adding to_html to PasswordString (returns '[password-hidden]')
|
15
|
+
|
16
|
+
EnumString -- now defines constants on the class for each value in
|
17
|
+
the enum
|
18
|
+
|
19
|
+
Also, won't define an is_foo? method if that already exists
|
20
|
+
|
21
|
+
Removing HoboFields::Percentage -- this is better handled as an
|
22
|
+
application specific type
|
23
|
+
|
24
|
+
For example, is a percentage an fixnum or a float? Is 101% valid
|
25
|
+
or invalid?
|
26
|
+
|
27
|
+
Fix to validates_virtual_field
|
28
|
+
|
29
|
+
*Breaking Change* EnumString: Change to automatically defined
|
30
|
+
class methods on EnumString classes
|
31
|
+
|
32
|
+
It used to be that if you did EnumString.for(:foo, :baa), your
|
33
|
+
class had methods foo, baa and the instance got methods foo?
|
34
|
+
and baa?. There was a big problem with name clashes with other
|
35
|
+
class methods. You now get no class methods, and the instance
|
36
|
+
methods are called is_foo? and is_baa?.
|
37
|
+
|
38
|
+
Rich field type fix: don't attempt to wrap booleans
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Tom Locke
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
ActiveRecord::ActiveRecordError # hack for https://rails.lighthouseapp.com/projects/8994/tickets/2577-when-using-activerecordassociations-outside-of-rails-a-nameerror-is-thrown
|
6
|
+
|
7
|
+
RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
|
8
|
+
RUBYDOCTEST = ENV['RUBYDOCTEST'] || "#{RUBY} -S rubydoctest"
|
9
|
+
|
10
|
+
$:.unshift File.expand_path('../../hobo_support/lib', __FILE__)
|
11
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
12
|
+
require 'hobo_support'
|
13
|
+
require 'hobo_fields'
|
14
|
+
|
15
|
+
GEM_ROOT = File.expand_path('../', __FILE__)
|
16
|
+
TESTAPP_PATH = File.join Dir.tmpdir, 'hobo_fields_testapp'
|
17
|
+
BIN = File.expand_path('../bin/hobofields', __FILE__)
|
18
|
+
require 'hobo_support/common_tasks'
|
19
|
+
include HoboSupport::CommonTasks
|
20
|
+
|
21
|
+
|
22
|
+
namespace "test" do
|
23
|
+
desc "Run the doctests"
|
24
|
+
task :doctest do |t|
|
25
|
+
files=Dir['test/*.rdoctest'].map {|f| File.expand_path(f)}.join(' ')
|
26
|
+
exit(1) if !system("#{RUBYDOCTEST} #{files}")
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Run the unit tests"
|
30
|
+
task :unit do |t|
|
31
|
+
Dir["test/test_*.rb"].each do |f|
|
32
|
+
exit(1) if !system("#{RUBY} #{f}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.3.0.RC
|
data/bin/hobofields
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
if ENV["HOBODEV"]
|
5
|
+
dev_root = File.expand_path ENV["HOBODEV"], FileUtils.pwd
|
6
|
+
$:.unshift "#{dev_root}/hobo_support/lib"
|
7
|
+
else
|
8
|
+
require 'rubygems'
|
9
|
+
end
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'hobo_support/command'
|
13
|
+
rescue LoadError
|
14
|
+
puts "The 'hobo_support' gem is not installed.
|
15
|
+
You probably need to set the HOBODEV environment variable to the local repository path."
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
HoboSupport::Command.run(:hobofields)
|
data/hobo_fields.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
name = File.basename( __FILE__, '.gemspec' )
|
2
|
+
version = File.read(File.expand_path('../VERSION', __FILE__)).strip
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
|
7
|
+
s.authors = ['Tom Locke']
|
8
|
+
s.email = 'tom@tomlocke.com'
|
9
|
+
s.homepage = 'http://hobocentral.net'
|
10
|
+
s.rubyforge_project = 'hobo'
|
11
|
+
s.summary = 'Rich field types and migration generator for Rails'
|
12
|
+
s.description = 'Rich field types and migration generator for Rails'
|
13
|
+
|
14
|
+
s.add_runtime_dependency('hobo_support', ["= #{version}"])
|
15
|
+
s.add_development_dependency('rubydoctest', [">= 0"])
|
16
|
+
s.add_development_dependency('redcloth', [">= 0"]) # for testing rich types
|
17
|
+
s.add_development_dependency('bluecloth', [">= 0"]) # for testing rich types
|
18
|
+
|
19
|
+
s.executables = ["hobofields"]
|
20
|
+
s.files = `git ls-files -x #{name}/* -z`.split("\0")
|
21
|
+
|
22
|
+
s.name = name
|
23
|
+
s.version = version
|
24
|
+
s.date = Date.today.to_s
|
25
|
+
|
26
|
+
s.required_rubygems_version = ">= 1.3.6"
|
27
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
28
|
+
s.require_paths = ["lib"]
|
29
|
+
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Description:
|
2
|
+
|
3
|
+
This generator compares your existing schema against the
|
4
|
+
schema declared inside your fields declarations in your
|
5
|
+
models.
|
6
|
+
|
7
|
+
If the generator finds differences, it will display the
|
8
|
+
migration it has created, and ask you if you wish to
|
9
|
+
[g]enerate migration, generate and [m]igrate now or [c]ancel?
|
10
|
+
Enter "g" to just generate the migration but do not run it.
|
11
|
+
Enter "m" to generate the migration and run it, or press "c"
|
12
|
+
to do nothing.
|
13
|
+
|
14
|
+
The generator will then prompt you for the migration name,
|
15
|
+
supplying a numbered default name.
|
16
|
+
|
17
|
+
The generator is conservative and will prompt you to resolve
|
18
|
+
any ambiguities.
|
19
|
+
|
20
|
+
Examples:
|
21
|
+
|
22
|
+
$ rails generate hobo:migration
|
23
|
+
|
24
|
+
---------- Up Migration ----------
|
25
|
+
create_table :foos do |t|
|
26
|
+
t.datetime :created_at
|
27
|
+
t.datetime :updated_at
|
28
|
+
end
|
29
|
+
----------------------------------
|
30
|
+
|
31
|
+
---------- Down Migration --------
|
32
|
+
drop_table :foos
|
33
|
+
----------------------------------
|
34
|
+
What now: [g]enerate migration, generate and [m]igrate now or [c]ancel? m
|
35
|
+
|
36
|
+
Migration filename:
|
37
|
+
(you can type spaces instead of '_' -- every little helps)
|
38
|
+
Filename [hobo_migration_2]: create_foo
|
39
|
+
exists db/migrate
|
40
|
+
create db/migrate/20091023183838_create_foo.rb
|
41
|
+
(in /work/foo)
|
42
|
+
== CreateFoo: migrating ======================================================
|
43
|
+
-- create_table(:yos)
|
44
|
+
-> 0.0856s
|
45
|
+
== CreateFoo: migrated (0.0858s) =============================================
|
46
|
+
|
47
|
+
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
require 'generators/hobo_support/thor_shell'
|
4
|
+
|
5
|
+
module Hobo
|
6
|
+
class MigrationGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
argument :name, :type => :string, :optional => true
|
10
|
+
|
11
|
+
include Rails::Generators::Migration
|
12
|
+
include Generators::HoboSupport::ThorShell
|
13
|
+
|
14
|
+
# the Rails::Generators::Migration.next_migration_number gives a NotImplementedError
|
15
|
+
# in Rails 3.0.0.beta4, so we need to implement the logic of ActiveRecord.
|
16
|
+
# For other ORMs we will wait for the rails implementation
|
17
|
+
# see http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/a507ce419076cda2
|
18
|
+
def self.next_migration_number(dirname)
|
19
|
+
ActiveRecord::Generators::Base.next_migration_number dirname
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.banner
|
23
|
+
"rails generate hobo:migration #{self.arguments.map(&:usage).join(' ')} [options]"
|
24
|
+
end
|
25
|
+
|
26
|
+
class_option :drop,
|
27
|
+
:aliases => '-d',
|
28
|
+
:type => :boolean,
|
29
|
+
:desc => "Don't prompt with 'drop or rename' - just drop everything"
|
30
|
+
|
31
|
+
class_option :default_name,
|
32
|
+
:aliases => '-n',
|
33
|
+
:type => :boolean,
|
34
|
+
:desc => "Don't prompt for a migration name - just pick one"
|
35
|
+
|
36
|
+
class_option :generate,
|
37
|
+
:aliases => '-g',
|
38
|
+
:type => :boolean,
|
39
|
+
:desc => "Don't prompt for action - generate the migration"
|
40
|
+
|
41
|
+
class_option :migrate,
|
42
|
+
:aliases => '-m',
|
43
|
+
:type => :boolean,
|
44
|
+
:desc => "Don't prompt for action - generate and migrate"
|
45
|
+
|
46
|
+
def migrate
|
47
|
+
return if migrations_pending?
|
48
|
+
|
49
|
+
generator = Generators::Hobo::Migration::Migrator.new(lambda{|c,d,k,p| extract_renames!(c,d,k,p)})
|
50
|
+
up, down = generator.generate
|
51
|
+
|
52
|
+
if up.blank?
|
53
|
+
say "Database and models match -- nothing to change"
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
say "\n---------- Up Migration ----------"
|
58
|
+
say up
|
59
|
+
say "----------------------------------"
|
60
|
+
|
61
|
+
say "\n---------- Down Migration --------"
|
62
|
+
say down
|
63
|
+
say "----------------------------------"
|
64
|
+
|
65
|
+
action = options[:generate] && 'g' ||
|
66
|
+
options[:migrate] && 'm' ||
|
67
|
+
choose("\nWhat now: [g]enerate migration, generate and [m]igrate now or [c]ancel?", /^(g|m|c)$/)
|
68
|
+
|
69
|
+
if action != 'c'
|
70
|
+
if name.blank? && !options[:default_name]
|
71
|
+
final_migration_name = choose("\nMigration filename: [<enter>=#{migration_name}|<custom_name>]:", /^[a-z0-9_ ]*$/, migration_name).strip.gsub(' ', '_')
|
72
|
+
end
|
73
|
+
final_migration_name = migration_name if final_migration_name.blank?
|
74
|
+
|
75
|
+
up.gsub!("\n", "\n ")
|
76
|
+
up.gsub!(/ +\n/, "\n")
|
77
|
+
down.gsub!("\n", "\n ")
|
78
|
+
down.gsub!(/ +\n/, "\n")
|
79
|
+
|
80
|
+
@up = up
|
81
|
+
@down = down
|
82
|
+
@migration_class_name = final_migration_name.camelize
|
83
|
+
|
84
|
+
migration_template 'migration.rb.erb', "db/migrate/#{final_migration_name.underscore}.rb"
|
85
|
+
rake('db:migrate') if action == 'm'
|
86
|
+
end
|
87
|
+
rescue HoboFields::Model::FieldSpec::UnknownSqlTypeError => e
|
88
|
+
say "Invalid field type: #{e}"
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def migrations_pending?
|
94
|
+
pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations
|
95
|
+
|
96
|
+
if pending_migrations.any?
|
97
|
+
say "You have #{pending_migrations.size} pending migration#{'s' if pending_migrations.size > 1}:"
|
98
|
+
pending_migrations.each do |pending_migration|
|
99
|
+
say ' %4d %s' % [pending_migration.version, pending_migration.name]
|
100
|
+
end
|
101
|
+
true
|
102
|
+
else
|
103
|
+
false
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def extract_renames!(to_create, to_drop, kind_str, name_prefix="")
|
108
|
+
to_rename = {}
|
109
|
+
|
110
|
+
unless options[:drop]
|
111
|
+
|
112
|
+
rename_to_choices = to_create
|
113
|
+
to_drop.dup.each do |t|
|
114
|
+
while true
|
115
|
+
if rename_to_choices.empty?
|
116
|
+
say "\nCONFIRM DROP! #{kind_str} #{name_prefix}#{t}"
|
117
|
+
resp = ask("Enter 'drop #{t}' to confirm or press enter to keep:")
|
118
|
+
if resp.strip == "drop " + t.to_s
|
119
|
+
break
|
120
|
+
elsif resp.strip.empty?
|
121
|
+
to_drop.delete(t)
|
122
|
+
break
|
123
|
+
else
|
124
|
+
next
|
125
|
+
end
|
126
|
+
else
|
127
|
+
say "\nDROP, RENAME or KEEP?: #{kind_str} #{name_prefix}#{t}"
|
128
|
+
say "Rename choices: #{to_create * ', '}"
|
129
|
+
resp = ask "Enter either 'drop #{t}' or one of the rename choices or press enter to keep:"
|
130
|
+
resp.strip!
|
131
|
+
|
132
|
+
if resp == "drop " + t
|
133
|
+
# Leave things as they are
|
134
|
+
break
|
135
|
+
else
|
136
|
+
resp.gsub!(' ', '_')
|
137
|
+
to_drop.delete(t)
|
138
|
+
if resp.in?(rename_to_choices)
|
139
|
+
to_rename[t] = resp
|
140
|
+
to_create.delete(resp)
|
141
|
+
rename_to_choices.delete(resp)
|
142
|
+
break
|
143
|
+
elsif resp.empty?
|
144
|
+
break
|
145
|
+
else
|
146
|
+
next
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
to_rename
|
154
|
+
end
|
155
|
+
|
156
|
+
def migration_name
|
157
|
+
name || Generators::Hobo::Migration::Migrator.default_migration_name
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|