When generating a model/migration from cli added ability to specify whether particular property should also have an index #2555

Closed
wants to merge 5 commits into
from

Projects

None yet

7 participants

@german

When generating a model/migration from cli wouldn't that be nice if there would be an ability to specify whether particular property should also have an index like this:

rails g model person name:string:index profile:string

so developer could just run 'rake db:migrate' w/o looking into migration file?

The main change is adding the has_index property in the railties/lib/rails/generators/generated_attribute.rb:

module Rails
  module Generators
    class GeneratedAttribute
      attr_accessor :name, :type, :has_index

      def initialize(name, type, has_index = false)
        type = :string if type.blank?
        @name, @type, @has_index = name, type.to_sym, has_index.eql?("index")
      end

      ...

      def has_index?
        @has_index
      end
    end
  end
end

What do you think of it? Was it worth implementing?

UPD: added ability to specify :limit and :precision/:scale column options in migration like this: name:string[40] or name:string[40]:index or price:decimal[5.2] as proposed below (I chosen square brackets because parentheses break bash shell)

UPD changed a dot to a comma and square brackets to curly ones while specifying column type options

@german german added ability to specify from cli when generating a model/migration w…
…hether particular property should be an index like this 'rails g model person name:string:index profile:string'
3d2eed7
@vijaydev vijaydev and 2 others commented on an outdated diff Aug 17, 2011
railties/lib/rails/generators/named_base.rb
@@ -154,8 +154,8 @@ module Rails
# Convert attributes array into GeneratedAttribute objects.
def parse_attributes! #:nodoc:
self.attributes = (attributes || []).map do |key_value|
- name, type = key_value.split(':')
- Rails::Generators::GeneratedAttribute.new(name, type)
+ name, type, has_index = key_value.split(':')
@vijaydev
vijaydev Aug 17, 2011

Rails 3.2 (edge) has a change where the type can be omitted and it will default to string. So you need to support "name:index" in addition to "name:string:index".

@vijaydev
vijaydev Aug 17, 2011

Here is the relevant commit: 08983fe

@josevalim
josevalim Dec 23, 2011

What if we remove this code from here and move it to Rails::Generators::GeneratedAttribute.parse(key_value). That said, the responsibility ends up all in one place.

@german
german Dec 23, 2011

You mean move this code to Rails::Generators::GeneratedAttribute#parse(key_value):

   name, type, has_index = key_value.split(':')
   # if user provided "name:index" instead of "name:string:index" type should be set blank
   # so GeneratedAttribute's constructor could set it to :string
   if type.eql?("index")
     has_index = type
     type = nil
   end

So we could write Rails::Generators::GeneratedAttribute.parse(key_value) ? Sure, I think it's ok.

@german german added condition to check whether user omitted type of the attribute b…
…ut specified it should have index while generating model/migration from the cli, so 'rails g model person name:index age:integer' should work
12dcac7
@alexeymuranov

I like the idea. It would also be nice to be able to specify the length as name:string(40).

@german

@alexeymuranov yeah, I didn't thought of that. Will try to implement it.

@german

@alexeymuranov I think that's what you've talked about: name:string[40] or name:string[40]:index or price:decimal[5.2]. I choose square brackets because parentheses break bash shell

@alexeymuranov

Thanks!

@sikachu
Ruby on Rails member

Square brackets need to be escaped in zsh as well ...

@german

Thanks for the feedback @sikachu. So what do you think of which delimiter will do ideally? Comma maybe (like "name:string,20") or curly brackets (like "name:string{20}:index") or dot? Or should I delete the last commit at all?

@alexeymuranov

Sorry for starting this :). Maybe underscore? name:string_20:index
Or just name:string20:index

@dmathieu

Is this really useful ? I don't think a lot of people will use it, it's too hard to remember.
And when you want to create a really specific migration with specific indexes, you can still manually edit the file.

@alexeymuranov

About the parentheses: i thought that the parentheses syntax was natural, and this is how annotate_models writes its comments, but if parentheses do not work in bash, i do not know.
In my opinion, there is some use in all this: it is easier to edit several command lines before pasting them into the shell, than edit multiple migration files afterwards.

@german

@dmathieu well, I don't know about :limit/:precision/:scale options but at least :index option might be useful, I often add indices by myself after generating a migration and I thought it could be automated somehow.

@Bodacious

Just noticed this pull request
+1 - great idea

@alexeymuranov

@german, just a thought: use parenthesis () for :limit, and those who need them from the command line, like me, will escape them!

@german

@alexeymuranov I think I'll better create a thread in rails-core google group, so this pull request could attract more attention and gather some more opinions
/ cc @spastorino

@german german closed this Nov 24, 2011
@german german reopened this Dec 15, 2011
@josevalim josevalim and 1 other commented on an outdated diff Dec 23, 2011
railties/lib/rails/generators/generated_attribute.rb
type = :string if type.blank?
- @name, @type = name, type.to_sym
+ @name, @type, @attr_options, @has_index = name, *parse_type_and_options(type), has_index.eql?("index")
@josevalim
josevalim Dec 23, 2011

We don't need to do everything in one line. :)

@german
german Dec 23, 2011

yes, I know)

@josevalim josevalim commented on the diff Dec 23, 2011
...rators/active_record/migration/migration_generator.rb
@@ -3,7 +3,7 @@
module ActiveRecord
module Generators
class MigrationGenerator < Base
- argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type field:type:index"
@josevalim
josevalim Dec 23, 2011

Let's change the banner to: "field field:type field:type:index". What do you think?

@german
german Dec 23, 2011

Ok, cool. Actually I'm in doubt whether 'name:string[40]' functionality is needed as it was proposed ealier #2555 (comment) ? what do you think?

@josevalim
josevalim Dec 24, 2011

I think it would be too hard to put all this information in the banner. We should document it in the USAGE though. Now that we use {} for extra information, we could even change the banner to: field[:type][:index] field[:type][:index] and put the remaining information in the USAGE.

@josevalim
Ruby on Rails member

I like [] because this is what rake uses.

@josevalim
Ruby on Rails member

Btw, decimal[5.2] meaning precision.scale is not good. I would suggest using decimal[5,2] or removing it.

@josevalim josevalim commented on an outdated diff Dec 23, 2011
railties/lib/rails/generators/generated_attribute.rb
@@ -48,6 +48,27 @@ def human_name
def reference?
self.type.in?([:references, :belongs_to])
end
+
+ def has_index?
+ @has_index
+ end
+
+ # parse possible attribute options like :limit for string/text/binary/integer or :precision/:scale for decimals
+ # when declaring options square brackets should be used since bash interpreter fails when parentheses are used
+ def parse_type_and_options(type)
@josevalim
josevalim Dec 23, 2011

As I said, this could be the class method parse and the object would be then initialized with all four args (name, type, index and options).

@german german changed square brackets to curly ones in column type definition, also…
… added ability to specify (uniq|unique) in index definition, so now it's possible to write 'discount:decimal{5,2}:uniq' or 'user_uuid:uniq' while generating new model/migration
51eded9
@german

I've

  • changed square brackets to the curly ones in column type definition (so zsh and bash are ok)
  • changed a dot to a comma
  • added ability to specify (uniq|unique) in column definition (instead of index)

so now it's possible to write 'discount:decimal{5,2}:unique' or 'user_uuid:uniq' while generating new model/migration.

What do you think of this? I'll investigate on this further tomorrow. Thanks.

@josevalim
Ruby on Rails member

I have merged this to a local branch. I will push it to master soon.

@josevalim josevalim added a commit that closed this pull request Dec 24, 2011
@josevalim josevalim Merge branch 'gzip-index' which contains two features:
1) Adding gzip to pages cache, closes #4124

2) Allow scaffold/model/migration generators to accept a "index" and "uniq"
modifiers, as in: "tracking_id:integer:uniq" in order to generate (unique)
indexes. Some types also accept custom options, for instance, you can
specify the precision and scale for decimals as "price:decimal{7,2}".
This feature closes #2555.
0152fe9
@josevalim josevalim closed this in 0152fe9 Dec 24, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment