Redmine插件开发-如何避免插件之间的表名和模型名重复

问题描述 投票:0回答:1

我正在为Redmine创建一个插件。但是似乎在迁移时,CREATE TABLE使用模型名称作为表名称。如果我已经有另一个具有相同表名的插件怎么办?

我可以做些什么来自动在表名前添加前缀而不更改模型名吗?

我的问题是模型Carro

是否可以使用rake脚本来指示它创建表,例如:CREATE_TABLE pluginName_modelName

我如何创建插件框架:

bundle exec ruby bin/rails generate redmine_plugin carros
      create  plugins/carros/app
      create  plugins/carros/app/controllers
      create  plugins/carros/app/helpers
      create  plugins/carros/app/models
      create  plugins/carros/app/views
      create  plugins/carros/db/migrate
      create  plugins/carros/lib/tasks
      create  plugins/carros/assets/images
      create  plugins/carros/assets/javascripts
      create  plugins/carros/assets/stylesheets
      create  plugins/carros/config/locales
      create  plugins/carros/test
      create  plugins/carros/test/fixtures
      create  plugins/carros/test/unit
      create  plugins/carros/test/functional
      create  plugins/carros/test/integration
      create  plugins/carros/README.rdoc
      create  plugins/carros/init.rb
      create  plugins/carros/config/routes.rb
      create  plugins/carros/config/locales/en.yml
      create  plugins/carros/test/test_helper.rb

我无法使用重复的表名的模型:

bundle exec ruby bin/rails generate redmine_plugin_model carros Carro modelo:string ano:integer cor:string km:integer
      create  plugins/carros/app/models/carro.rb
      create  plugins/carros/test/unit/carro_test.rb
      create  plugins/carros/db/migrate/001_create_carros.rb

迁移是:

cat plugins/carros/db/migrate/001_create_carros.rb
class CreateCarros < ActiveRecord::Migration
  def change
    create_table :carros do |t|
      t.string :modelo
      t.integer :ano
      t.string :cor
      t.integer :km
    end
  end
end

而且我想避免的错误,如果可能的话,不对表的前缀进行硬编码:

bundle exec rake redmine:plugins:migrate
Migrating carros (Carros plugin)...
== 1 CreateCarros: migrating ==================================================
-- create_table(:carros)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Table 'carros' already exists: CREATE TABLE `carros` (`id` int(11) auto_increment PRIMARY KEY, `modelo` varchar(255), `ano` int(11), `cor` varchar(255), `km` int(11)) ENGINE=InnoDB                                                                            
/usr/local/www/redmine/plugins/carros/db/migrate/001_create_carros.rb:3:in `change'
/usr/local/www/redmine/lib/redmine/plugin.rb:481:in `migrate_plugin'
/usr/local/www/redmine/lib/redmine/plugin.rb:453:in `migrate'
/usr/local/www/redmine/lib/redmine/plugin.rb:467:in `block in migrate'
/usr/local/www/redmine/lib/redmine/plugin.rb:466:in `each'
/usr/local/www/redmine/lib/redmine/plugin.rb:466:in `migrate'
/usr/local/www/redmine/lib/tasks/redmine.rake:135:in `block (3 levels) in <top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'

Caused by:
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'carros' already exists: CREATE TABLE `carros` (`id` int(11) auto_increment PRIMARY KEY, `modelo` varchar(255), `ano` int(11), `cor` varchar(255), `km` int(11)) ENGINE=InnoDB                                            
/usr/local/www/redmine/plugins/carros/db/migrate/001_create_carros.rb:3:in `change'
/usr/local/www/redmine/lib/redmine/plugin.rb:481:in `migrate_plugin'
/usr/local/www/redmine/lib/redmine/plugin.rb:453:in `migrate'
/usr/local/www/redmine/lib/redmine/plugin.rb:467:in `block in migrate'
/usr/local/www/redmine/lib/redmine/plugin.rb:466:in `each'
/usr/local/www/redmine/lib/redmine/plugin.rb:466:in `migrate'
/usr/local/www/redmine/lib/tasks/redmine.rake:135:in `block (3 levels) in <top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'

Caused by:
Mysql2::Error: Table 'carros' already exists
/usr/local/www/redmine/plugins/carros/db/migrate/001_create_carros.rb:3:in `change'
/usr/local/www/redmine/lib/redmine/plugin.rb:481:in `migrate_plugin'
/usr/local/www/redmine/lib/redmine/plugin.rb:453:in `migrate'
/usr/local/www/redmine/lib/redmine/plugin.rb:467:in `block in migrate'
/usr/local/www/redmine/lib/redmine/plugin.rb:466:in `each'
/usr/local/www/redmine/lib/redmine/plugin.rb:466:in `migrate'
/usr/local/www/redmine/lib/tasks/redmine.rake:135:in `block (3 levels) in <top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => redmine:plugins:migrate
(See full trace by running task with --trace)

我尝试没有成功的事情:

向模型添加名称空间(模块):

如果正确解开,ActiveModel :: Name ActiveModel具有生成模型名称的函数,该函数将由ActiveRecord :: create_table使用。

#ActiveModel::Name
    def model_name
          @_model_name ||= begin
            namespace = module_parents.detect do |n|
              n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming?
            end
            ActiveModel::Name.new(self, namespace)
          end
    end

所以我尝试将模块添加到我的模型名称:

module Tutorial
    class Carro < ActiveRecord::Base

    end
end

但是它仍然抱怨表名重复。因此,添加包装该类的模块不会产生任何效果:

bundle exec rake redmine:plugins:migrate NAME=carros
/usr/local/lib/ruby/gems/2.6/gems/activesupport-4.2.11.1/lib/active_support/core_ext/object/duplicable.rb:111: warning: BigDecimal.new is deprecated; use BigDecimal() method instead.
Migrating carros (Carros plugin)...
== 1 CreateCarros: migrating ==================================================
-- create_table(:carros)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Table 'carros' already exists: CREATE TABLE `carros` (`id` int(11) auto_increment PRIMARY KEY, `modelo` varchar(255), `ano` int(11), `cor` varchar(255), `km` int(11)) ENGINE=InnoDB
ruby-on-rails ruby-on-rails-4 redmine redmine-plugins
1个回答
0
投票

基本上,我更改了模型,将其包装在模块中:

这是我的新模特。它会覆盖ActiveRecord中的属性以设置表名称:

module Transporte
    class Carro < ActiveRecord::Base
        # https://github.com/rails/rails/blob/master/activerecord/test/models/developer.rb
        self.table_name = "trans_carros"
    end
end

文件系统必须反映从models/carro.rbmodels/transporte/carro.rb的更改。该模块在文件系统中表示为目录,以避免文件冲突。

我的迁移文件正在运行CREATE TABLE时正在调用模型的table_name属性。

class CreateCarros < ActiveRecord::Migration
  def change
    say("Creating table " << Transporte::Carro.table_name)
    create_table Transporte::Carro.table_name do |t|
      t.string :modelo
      t.integer :ano
      t.string :cor
      t.integer :km
    end
  end
end

假设我更改了表名,而没有将模型包装在模块中。查询数据库时,我的行为不正确:

$ rails c
irb> Carro.all

上面的SELECT从表carros中的记录,来自第一个安装了名为Carro的模型的插件。

但是,有一个避免冲突的模块,我有:

$ rails c
irb> Transporte::Carro.all

现在它可以正常工作,使用正确的模型并查询相关表。

© www.soinside.com 2019 - 2024. All rights reserved.