Chave Primária Composta
Ruby on Rails No Comments »Porque
O RubyonRails não suporta chaves primárias compostas. Este software livre é uma extensão para a camada de banco de dados Rails – ActiveRecords – para aceitar chaves primárias compostas tão transparentemente quanto possível.
Qualquer script de Rubi usando ActiveRecords pode usar Chaves Primárias Composto com esta biblioteca.
Instalando
sudo gem install composite_primary_keys
Rails: Adicione a seguinte linha na parte inferior de seu environment.rb
require 'composite_primary_keys'
Script Ruby: Adicione a seguinte linha no topo de seu script
require 'rubygems' require 'composite_primary_keys'
O Básico
Um modelo com chaves primárias compostas pareceria com …
class Membership < ActiveRecord::Base # set_primary_keys *keys - turns on composite key functionality set_primary_keys :user_id, :group_id belongs_to :user belongs_to :group has_many :statuses, :class => 'MembershipStatus', :foreign_key => [:user_id, :group_id] end
Um modelo associado com um modelo de chave composto seria definido como …
class MembershipStatus < ActiveRecord::Base belongs_to :membership, :foreign_key => [:user_id, :group_id] end
Isto é, associações podem incluir chaves compostas também. Bom.
Demonstração de Uso
Uma vez que você tem criados seus modelos para especificar chaves primárias compostas (como a classe Membership) e associações (como MembershipStatus#membership), você pode usar-las como qualquer modelo normal com associações.
Mas primeiro, verifique nossas chaves primárias.
MembershipStatus.primary_key # => "id" # Chave Normal Membership.primary_key # => [:user_id, :group_id] # Chave composta Membership.primary_key.to_s # => "user_id,group_id"
Agora nós queremos achar instâncias usando a mesma sintaxe que nós sempre usamos para ActiveRecords …
MembershipStatus.find(1) # single id returns single instance
=> <MembershipStatus:0x392a8c8 @attributes={"id"=>"1", "status"=>"Active"}>
Membership.find(1,1) # composite ids returns single instance
=> <Membership:0x39218b0 @attributes={"user_id"=>"1", "group_id"=>"1"}>
Usando Ruby on Rails? Você desejará seu seu helpers url_for para converter chaves compostas em strings e voltar novamente …
Membership.find(:first).to_param # => "1,1"
E então use a string ID dentro de seu controlador para achar o objeto novamente
params[:id] # => '1,1'
Membership.find(params[:id])
=> <Membership:0x3904288 @attributes={"user_id"=>"1", "group_id"=>"1"}>
Isto é, um ActiveRecord sustentando chaves compostas se comporta transparentemente ao longo de sua aplicação. Só como um ActiveRecord normal.
Outros Truques
Passe por uma lista de id composto para o achar método
Membership.find [1,1], [2,1]
=> [
<Membership:0x394ade8 @attributes={"user_id"=>"1", "group_id"=>"1"}>,
<Membership:0x394ada0 @attributes={"user_id"=>"2", "group_id"=>"1"}>
]
Perform #count operations
MembershipStatus.find(:first).memberships.count # => 1
Rotas com Rails
De Pete Sumskas:
Eu choquei-me com um problema que eu não vi mencionado nesta lista – e eu não vi quaisquer informações sobre ele na documentação de como eu devia fazer para trata-lo. O problema era que os URLs sendo gerado para ação do show (por exemplo) teve uma sintaxe como:
/controller/show/123000,Bu70
Para um PK de dois campos composto. A rota padrão não combinaria, então depois de descobrir como fazer a rota que eu adicionei:
Map.connect ':controller/:action/:id ', :iD => /w+(,w+)*/
ao meu arquivo route.rb.
Que Banco de Dados?
Um suíte de testes da unidade foi executado nos bancos de dados seguintes sustentado por ActiveRecord:
| Database |
Sucesso do Teste |
Retorno (since 0.8.0) |
| mysql | YES | ??? (Yes! or No…) |
| sqlite3 | YES (new 0.8.0) | ??? (Yes! or No…) |
| postgresql | YES (new 0.8.0) | ??? (Yes! or No…) |
| oracle | YES (new 0.8.2) | YES (Yes! or No…) |
| sqlserver | ??? (I can help) | ??? (Yes! or No…) |
| db2 | ??? (I can help) | ??? (Yes! or No…) |
| firebird | ??? (I can help) | ??? (Yes! or No…) |
| sybase | ??? (I can help) | ??? (Yes! or No…) |
| openbase | ??? (I can help) | ??? (Yes! or No…) |
| frontbase | ??? (I can help) | ??? (Yes! or No…) |