napa 0.4.3 → 0.5.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.
- checksums.yaml +4 -4
- data/.dockerignore +6 -0
- data/CHANGELOG.md +5 -0
- data/Dockerfile +29 -0
- data/contrib/start.rb +19 -0
- data/docs/quickstart.md +23 -44
- data/lib/napa/cli/generate.rb +8 -0
- data/lib/napa/cli/generated_attribute.rb +170 -0
- data/lib/napa/cli/migration.rb +5 -151
- data/lib/napa/cli/model.rb +126 -0
- data/lib/napa/cli/templates/migration/{%migration_filename%.rb.tt → migration.rb.tt} +0 -0
- data/lib/napa/cli/templates/model/app/models/model.rb.tt +9 -0
- data/lib/napa/cli/templates/{create_table_migration/%migration_filename%.rb.tt → model/db/migrate/migration.rb.tt} +0 -0
- data/lib/napa/cli/templates/model/spec/factories/factory.rb.tt +14 -0
- data/lib/napa/cli/templates/model/spec/models/model_spec.rb.tt +14 -0
- data/lib/napa/cli/templates/new/Gemfile.tt +1 -0
- data/lib/napa/middleware/authentication.rb +5 -1
- data/lib/napa/rspec_extensions/response_helpers.rb +4 -0
- data/lib/napa/setup.rb +5 -1
- data/lib/napa/version.rb +1 -1
- data/lib/tasks/db.rake +6 -0
- data/napa.gemspec +18 -18
- data/spec/cli/generate/api_spec.rb +0 -14
- data/spec/cli/model_spec.rb +297 -0
- data/spec/middleware/authentication_spec.rb +19 -0
- metadata +52 -43
- data/lib/napa/cli/templates/api/app/models/%name_underscore%.rb.tt +0 -2
- data/lib/napa/cli/templates/api/spec/models/%name_underscore%_spec.rb.tt +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91335a0b0cd0c3a0efd87528894698508f26f51f
|
4
|
+
data.tar.gz: 04c64e2dd763c45a38a89d8a84e0f5bdaf80dbad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f25478d3900145201937e2b3f79c2f3cc7fd8d4c0ce8c2a0656137773d557eb2f34dd3e976bf5a6f5698c395c6b4a762e917a5388585891a7f24a549e10461d
|
7
|
+
data.tar.gz: d257e109aed088d50f701873bdf1d56cfff66f2f9df2fb4f2b2d4b6bcd07f0aecd26c9cd1b906b5c2c15e46575e834f11a8dfbf2f729133e7284cc67508957d9
|
data/.dockerignore
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
master
|
2
2
|
===
|
3
|
+
* [Support for Rails style Model Generation](https://github.com/bellycard/napa/pull/207)
|
4
|
+
* [Resolves issue #205 by adding hashie-forbidden_attributes gem to generated Gemfile](https://github.com/bellycard/napa/pull/206)
|
5
|
+
* [use RAILS_ENV if RACK_ENV not found](https://github.com/bellycard/napa/pull/200)
|
6
|
+
* [Support for creating and dropping databases on non-standard ports](https://github.com/bellycard/napa/pull/166)
|
7
|
+
* Added an rspec response helper `expect_error_code` for easier testing of API methods which are supposed to send back a JSON representation of an error
|
3
8
|
|
4
9
|
0.4.3
|
5
10
|
===
|
data/Dockerfile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
FROM ruby:2.0.0-p643
|
2
|
+
|
3
|
+
# Install deps
|
4
|
+
RUN apt-get update \
|
5
|
+
&& apt-get install -y libreadline-dev nano vim \
|
6
|
+
&& apt-get purge -y --auto-remove
|
7
|
+
|
8
|
+
# Ensure Gemfile.lock is up to date
|
9
|
+
RUN bundle config --global frozen 1
|
10
|
+
|
11
|
+
# Install latest released Napa to get baseline dependencies
|
12
|
+
RUN gem install napa
|
13
|
+
|
14
|
+
# Add a simple Procfile parser
|
15
|
+
ADD contrib/start.rb /start
|
16
|
+
|
17
|
+
# Create directory for app
|
18
|
+
RUN mkdir -p /usr/src/app
|
19
|
+
WORKDIR /usr/src/app
|
20
|
+
|
21
|
+
# Copy Gemfile and Gemfile.lock and run bundle install
|
22
|
+
ONBUILD COPY Gemfile /usr/src/app/
|
23
|
+
ONBUILD COPY Gemfile.lock /usr/src/app/
|
24
|
+
ONBUILD RUN bundle install
|
25
|
+
|
26
|
+
# Copy rest of app
|
27
|
+
ONBUILD COPY . /usr/src/app
|
28
|
+
|
29
|
+
CMD ["/start", "web"]
|
data/contrib/start.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
# attempt to parse Procfile
|
6
|
+
begin
|
7
|
+
proc = YAML.load_file('Procfile')
|
8
|
+
command = proc[ARGV[0]]
|
9
|
+
|
10
|
+
if command
|
11
|
+
exec(command)
|
12
|
+
else
|
13
|
+
puts "Could not find #{ARGV[0]} in Procfile"
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
rescue
|
17
|
+
puts 'Failed to parse Procfile'
|
18
|
+
exit 2
|
19
|
+
end
|
data/docs/quickstart.md
CHANGED
@@ -69,63 +69,52 @@ Once your databases are setup, you can run `rspec` to verify everything is worki
|
|
69
69
|
rspec spec
|
70
70
|
```
|
71
71
|
|
72
|
-
##
|
72
|
+
## Model Generator
|
73
73
|
|
74
|
-
Now that we have our service scaffolded up, let's generate
|
74
|
+
Now that we have our service scaffolded up, let's generate the data model for our service.
|
75
75
|
|
76
|
-
Napa includes
|
76
|
+
Napa includes a Model generator that will create an ActiveRecord model, the associated database migration, a factory stub for testing, and an initial rspec test. To invoke this, run:
|
77
77
|
|
78
78
|
```
|
79
|
-
napa generate
|
79
|
+
napa generate model Person name:string job_title:string email:string
|
80
80
|
```
|
81
81
|
|
82
|
-
**Note:** the generator will pluralize the name of your resource for the API, so use the singular version in the generator.
|
83
|
-
|
84
82
|
You will see the following output:
|
85
83
|
|
86
84
|
```
|
87
|
-
Generating
|
88
|
-
create
|
85
|
+
Generating model...
|
86
|
+
create db/migrate/20140411163743_create_people.rb
|
89
87
|
create app/models/person.rb
|
90
|
-
create
|
88
|
+
create spec/factories/people.rb
|
89
|
+
create spec/models/person_spec.rb
|
91
90
|
Done!
|
92
91
|
```
|
93
92
|
|
94
|
-
|
95
|
-
|
96
|
-
From the output above, we can see that the generated create a `Person` model, so we should create a migration to actually build the table for that in our database. So, let's run:
|
93
|
+
Now we're ready to create and setup our databases by running:
|
97
94
|
|
98
95
|
```
|
99
|
-
|
96
|
+
rake db:migrate
|
97
|
+
RACK_ENV=test rake db:migrate
|
100
98
|
```
|
101
99
|
|
102
|
-
|
100
|
+
## API Generator
|
101
|
+
|
102
|
+
Next, let's generate an API to expose this information. Napa also includes an API generator which will create a Grape API, Model and Representer by running:
|
103
103
|
|
104
104
|
```
|
105
|
-
|
106
|
-
create db/migrate
|
107
|
-
create db/migrate/20140411163743_create_person.rb
|
108
|
-
Done!
|
105
|
+
napa generate api person
|
109
106
|
```
|
110
107
|
|
111
|
-
|
112
|
-
|
113
|
-
```ruby
|
114
|
-
class CreatePerson < ActiveRecord::Migration
|
115
|
-
def change
|
116
|
-
create_table :people do |t|
|
117
|
-
t.string :name
|
118
|
-
t.string :job_title
|
119
|
-
t.string :email
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
```
|
108
|
+
**Note:** the generator will pluralize the name of your resource for the API, so use the singular version in the generator.
|
124
109
|
|
125
|
-
|
110
|
+
You will see the following output:
|
126
111
|
|
127
112
|
```
|
128
|
-
|
113
|
+
Generating api...
|
114
|
+
create app/apis/people_api.rb
|
115
|
+
create app/representers/person_representer.rb
|
116
|
+
create spec/apis/people_api_spec.rb
|
117
|
+
Done!
|
129
118
|
```
|
130
119
|
|
131
120
|
## Declare these attributes in the API and Representer
|
@@ -201,17 +190,7 @@ To create a person we will send a `POST` request to our API.
|
|
201
190
|
curl -X POST -d name="Darby Frey" -d job_title="Software Engineer" -d email="darbyfrey@gmail.com" http://localhost:9393/people
|
202
191
|
```
|
203
192
|
|
204
|
-
**SIDENOTE:**
|
205
|
-
|
206
|
-
```json
|
207
|
-
{
|
208
|
-
"error": {
|
209
|
-
"code": "not_configured",
|
210
|
-
"message": "password not configured"
|
211
|
-
}
|
212
|
-
}
|
213
|
-
```
|
214
|
-
|
193
|
+
**SIDENOTE:** Napa ships with authentication support via the `Napa::Middleware::Authentication` middleware. This middleware is disabled by default, but can be enabled by uncommenting the `use Napa::Middleware::Authentication` line in `config.ru` and restarting shotgun. Also, see the Napa::Middleware::Authentication docs for more details.
|
215
194
|
|
216
195
|
All response from Napa include the `data` key. In this case the newly created person object is returned nested within the `data` key.
|
217
196
|
|
data/lib/napa/cli/generate.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "napa/cli/generate/api"
|
2
2
|
require "napa/cli/generate/readme"
|
3
3
|
require "napa/cli/migration"
|
4
|
+
require "napa/cli/model"
|
4
5
|
|
5
6
|
module Napa
|
6
7
|
module CLI
|
@@ -13,6 +14,13 @@ module Napa
|
|
13
14
|
'Create a Database Migration'
|
14
15
|
)
|
15
16
|
|
17
|
+
register(
|
18
|
+
Model,
|
19
|
+
'model',
|
20
|
+
'model <NAME> [field[:type][:index] field[:type][:index]] [options]',
|
21
|
+
'Create a Model, including its database migration and test scaffolding'
|
22
|
+
)
|
23
|
+
|
16
24
|
end
|
17
25
|
end
|
18
26
|
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module Napa
|
2
|
+
module CLI
|
3
|
+
# directly ported with slight modification from
|
4
|
+
# https://github.com/rails/rails/blob/76883f92374c6395f13c16628e1d87d40b6d2399/railties/lib/rails/generators/generated_attribute.rb
|
5
|
+
class GeneratedAttribute # :nodoc:
|
6
|
+
INDEX_OPTIONS = %w(index uniq)
|
7
|
+
UNIQ_INDEX_OPTIONS = %w(uniq)
|
8
|
+
|
9
|
+
attr_accessor :name, :type
|
10
|
+
attr_reader :attr_options
|
11
|
+
attr_writer :index_name
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def parse(column_definition)
|
15
|
+
name, type, has_index = column_definition.split(':')
|
16
|
+
|
17
|
+
# if user provided "name:index" instead of "name:string:index"
|
18
|
+
# type should be set blank so GeneratedAttribute's constructor
|
19
|
+
# could set it to :string
|
20
|
+
has_index, type = type, nil if INDEX_OPTIONS.include?(type)
|
21
|
+
|
22
|
+
type, attr_options = *parse_type_and_options(type)
|
23
|
+
type = type.to_sym if type
|
24
|
+
|
25
|
+
if type && reference?(type)
|
26
|
+
references_index = UNIQ_INDEX_OPTIONS.include?(has_index) ? { unique: true } : true
|
27
|
+
attr_options[:index] = references_index
|
28
|
+
end
|
29
|
+
|
30
|
+
new(name, type, has_index, attr_options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def reference?(type)
|
34
|
+
[:references, :belongs_to].include? type
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# parse possible attribute options like :limit for string/text/binary/integer, :precision/:scale for decimals or :polymorphic for references/belongs_to
|
40
|
+
# when declaring options curly brackets should be used
|
41
|
+
def parse_type_and_options(type)
|
42
|
+
case type
|
43
|
+
when /(string|text|binary|integer)\{(\d+)\}/
|
44
|
+
return $1, limit: $2.to_i
|
45
|
+
when /decimal\{(\d+)[,.-](\d+)\}/
|
46
|
+
return :decimal, precision: $1.to_i, scale: $2.to_i
|
47
|
+
when /(references|belongs_to)\{polymorphic\}/
|
48
|
+
return $1, polymorphic: true
|
49
|
+
else
|
50
|
+
return type, {}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize(name, type=nil, index_type=false, attr_options={})
|
56
|
+
@name = name
|
57
|
+
@type = type || :string
|
58
|
+
@has_index = INDEX_OPTIONS.include?(index_type)
|
59
|
+
@has_uniq_index = UNIQ_INDEX_OPTIONS.include?(index_type)
|
60
|
+
@attr_options = attr_options
|
61
|
+
end
|
62
|
+
|
63
|
+
def field_type
|
64
|
+
@field_type ||= case type
|
65
|
+
when :integer then :number_field
|
66
|
+
when :float, :decimal then :text_field
|
67
|
+
when :time then :time_select
|
68
|
+
when :datetime, :timestamp then :datetime_select
|
69
|
+
when :date then :date_select
|
70
|
+
when :text then :text_area
|
71
|
+
when :boolean then :check_box
|
72
|
+
else
|
73
|
+
:text_field
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def default
|
78
|
+
@default ||= case type
|
79
|
+
when :integer then 1
|
80
|
+
when :float then 1.5
|
81
|
+
when :decimal then "9.99"
|
82
|
+
when :datetime, :timestamp, :time then Time.now.to_s(:db)
|
83
|
+
when :date then Date.today.to_s(:db)
|
84
|
+
when :string then name == "type" ? "" : "MyString"
|
85
|
+
when :text then "MyText"
|
86
|
+
when :boolean then false
|
87
|
+
when :references, :belongs_to then nil
|
88
|
+
else
|
89
|
+
""
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def factory_stub
|
94
|
+
case type
|
95
|
+
when :integer then "1"
|
96
|
+
when :float then "1.5"
|
97
|
+
when :decimal then "9.99"
|
98
|
+
when :datetime, :timestamp, :time then "{ Time.now }"
|
99
|
+
when :date then "{ Date.today }"
|
100
|
+
when :string then '"MyString"'
|
101
|
+
when :text then '"MyText"'
|
102
|
+
when :boolean then "false"
|
103
|
+
when :digest then '"password"'
|
104
|
+
else
|
105
|
+
'"Unknown"'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def plural_name
|
110
|
+
name.sub(/_id$/, '').pluralize
|
111
|
+
end
|
112
|
+
|
113
|
+
def singular_name
|
114
|
+
name.sub(/_id$/, '').singularize
|
115
|
+
end
|
116
|
+
|
117
|
+
def human_name
|
118
|
+
name.humanize
|
119
|
+
end
|
120
|
+
|
121
|
+
def index_name
|
122
|
+
@index_name ||= if polymorphic?
|
123
|
+
%w(id type).map { |t| "#{name}_#{t}" }
|
124
|
+
else
|
125
|
+
column_name
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def column_name
|
130
|
+
@column_name ||= reference? ? "#{name}_id" : name
|
131
|
+
end
|
132
|
+
|
133
|
+
def foreign_key?
|
134
|
+
!!(name =~ /_id$/)
|
135
|
+
end
|
136
|
+
|
137
|
+
def reference?
|
138
|
+
self.class.reference?(type)
|
139
|
+
end
|
140
|
+
|
141
|
+
def polymorphic?
|
142
|
+
self.attr_options.has_key?(:polymorphic)
|
143
|
+
end
|
144
|
+
|
145
|
+
def required?
|
146
|
+
self.attr_options[:required]
|
147
|
+
end
|
148
|
+
|
149
|
+
def has_index?
|
150
|
+
@has_index
|
151
|
+
end
|
152
|
+
|
153
|
+
def has_uniq_index?
|
154
|
+
@has_uniq_index
|
155
|
+
end
|
156
|
+
|
157
|
+
def password_digest?
|
158
|
+
name == 'password' && type == :digest
|
159
|
+
end
|
160
|
+
|
161
|
+
def inject_options
|
162
|
+
"".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } }
|
163
|
+
end
|
164
|
+
|
165
|
+
def inject_index_options
|
166
|
+
has_uniq_index? ? ", unique: true" : ""
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/lib/napa/cli/migration.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'active_support/all'
|
3
|
+
require 'napa/cli/generated_attribute'
|
3
4
|
|
4
5
|
module Napa
|
5
6
|
module CLI
|
@@ -31,7 +32,7 @@ module Napa
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def set_local_assigns!
|
34
|
-
@migration_template = "migration"
|
35
|
+
@migration_template = "migration/migration.rb.tt"
|
35
36
|
filename = migration_name.underscore
|
36
37
|
case filename
|
37
38
|
when /^(add|remove)_.*_(?:to|from)_(.*)/
|
@@ -46,14 +47,14 @@ module Napa
|
|
46
47
|
end
|
47
48
|
when /^create_(.+)/
|
48
49
|
@table_name = $1.pluralize
|
49
|
-
@migration_template = "
|
50
|
+
@migration_template = "model/db/migrate/migration.rb.tt"
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
54
|
def migration
|
54
|
-
self.class.source_root "#{File.dirname(__FILE__)}/templates
|
55
|
+
self.class.source_root "#{File.dirname(__FILE__)}/templates/"
|
55
56
|
say 'Generating migration...'
|
56
|
-
|
57
|
+
template @migration_template, "#{output_directory}/#{migration_filename}.rb"
|
57
58
|
say 'Done!', :green
|
58
59
|
end
|
59
60
|
|
@@ -76,152 +77,5 @@ module Napa
|
|
76
77
|
end.to_sym
|
77
78
|
end
|
78
79
|
end
|
79
|
-
|
80
|
-
# directly ported from
|
81
|
-
# https://github.com/rails/rails/blob/76883f92374c6395f13c16628e1d87d40b6d2399/railties/lib/rails/generators/generated_attribute.rb
|
82
|
-
class GeneratedAttribute # :nodoc:
|
83
|
-
INDEX_OPTIONS = %w(index uniq)
|
84
|
-
UNIQ_INDEX_OPTIONS = %w(uniq)
|
85
|
-
|
86
|
-
attr_accessor :name, :type
|
87
|
-
attr_reader :attr_options
|
88
|
-
attr_writer :index_name
|
89
|
-
|
90
|
-
class << self
|
91
|
-
def parse(column_definition)
|
92
|
-
name, type, has_index = column_definition.split(':')
|
93
|
-
|
94
|
-
# if user provided "name:index" instead of "name:string:index"
|
95
|
-
# type should be set blank so GeneratedAttribute's constructor
|
96
|
-
# could set it to :string
|
97
|
-
has_index, type = type, nil if INDEX_OPTIONS.include?(type)
|
98
|
-
|
99
|
-
type, attr_options = *parse_type_and_options(type)
|
100
|
-
type = type.to_sym if type
|
101
|
-
|
102
|
-
if type && reference?(type)
|
103
|
-
references_index = UNIQ_INDEX_OPTIONS.include?(has_index) ? { unique: true } : true
|
104
|
-
attr_options[:index] = references_index
|
105
|
-
end
|
106
|
-
|
107
|
-
new(name, type, has_index, attr_options)
|
108
|
-
end
|
109
|
-
|
110
|
-
def reference?(type)
|
111
|
-
[:references, :belongs_to].include? type
|
112
|
-
end
|
113
|
-
|
114
|
-
private
|
115
|
-
|
116
|
-
# parse possible attribute options like :limit for string/text/binary/integer, :precision/:scale for decimals or :polymorphic for references/belongs_to
|
117
|
-
# when declaring options curly brackets should be used
|
118
|
-
def parse_type_and_options(type)
|
119
|
-
case type
|
120
|
-
when /(string|text|binary|integer)\{(\d+)\}/
|
121
|
-
return $1, limit: $2.to_i
|
122
|
-
when /decimal\{(\d+)[,.-](\d+)\}/
|
123
|
-
return :decimal, precision: $1.to_i, scale: $2.to_i
|
124
|
-
when /(references|belongs_to)\{polymorphic\}/
|
125
|
-
return $1, polymorphic: true
|
126
|
-
else
|
127
|
-
return type, {}
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
def initialize(name, type=nil, index_type=false, attr_options={})
|
133
|
-
@name = name
|
134
|
-
@type = type || :string
|
135
|
-
@has_index = INDEX_OPTIONS.include?(index_type)
|
136
|
-
@has_uniq_index = UNIQ_INDEX_OPTIONS.include?(index_type)
|
137
|
-
@attr_options = attr_options
|
138
|
-
end
|
139
|
-
|
140
|
-
def field_type
|
141
|
-
@field_type ||= case type
|
142
|
-
when :integer then :number_field
|
143
|
-
when :float, :decimal then :text_field
|
144
|
-
when :time then :time_select
|
145
|
-
when :datetime, :timestamp then :datetime_select
|
146
|
-
when :date then :date_select
|
147
|
-
when :text then :text_area
|
148
|
-
when :boolean then :check_box
|
149
|
-
else
|
150
|
-
:text_field
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def default
|
155
|
-
@default ||= case type
|
156
|
-
when :integer then 1
|
157
|
-
when :float then 1.5
|
158
|
-
when :decimal then "9.99"
|
159
|
-
when :datetime, :timestamp, :time then Time.now.to_s(:db)
|
160
|
-
when :date then Date.today.to_s(:db)
|
161
|
-
when :string then name == "type" ? "" : "MyString"
|
162
|
-
when :text then "MyText"
|
163
|
-
when :boolean then false
|
164
|
-
when :references, :belongs_to then nil
|
165
|
-
else
|
166
|
-
""
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def plural_name
|
171
|
-
name.sub(/_id$/, '').pluralize
|
172
|
-
end
|
173
|
-
|
174
|
-
def singular_name
|
175
|
-
name.sub(/_id$/, '').singularize
|
176
|
-
end
|
177
|
-
|
178
|
-
def human_name
|
179
|
-
name.humanize
|
180
|
-
end
|
181
|
-
|
182
|
-
def index_name
|
183
|
-
@index_name ||= if polymorphic?
|
184
|
-
%w(id type).map { |t| "#{name}_#{t}" }
|
185
|
-
else
|
186
|
-
column_name
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def column_name
|
191
|
-
@column_name ||= reference? ? "#{name}_id" : name
|
192
|
-
end
|
193
|
-
|
194
|
-
def foreign_key?
|
195
|
-
!!(name =~ /_id$/)
|
196
|
-
end
|
197
|
-
|
198
|
-
def reference?
|
199
|
-
self.class.reference?(type)
|
200
|
-
end
|
201
|
-
|
202
|
-
def polymorphic?
|
203
|
-
self.attr_options.has_key?(:polymorphic)
|
204
|
-
end
|
205
|
-
|
206
|
-
def has_index?
|
207
|
-
@has_index
|
208
|
-
end
|
209
|
-
|
210
|
-
def has_uniq_index?
|
211
|
-
@has_uniq_index
|
212
|
-
end
|
213
|
-
|
214
|
-
def password_digest?
|
215
|
-
name == 'password' && type == :digest
|
216
|
-
end
|
217
|
-
|
218
|
-
def inject_options
|
219
|
-
"".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } }
|
220
|
-
end
|
221
|
-
|
222
|
-
def inject_index_options
|
223
|
-
has_uniq_index? ? ", unique: true" : ""
|
224
|
-
end
|
225
|
-
end
|
226
80
|
end
|
227
81
|
end
|