Kleine Tricks in Ruby on Rails

Hier eine kleine Sammlung von Dingen, die mir geholfen haben beim Lösen der Probleme die sich einem N00b so stellen.

Exportieren von Datensätzen ins YAML Format

Rails Fixtures sind Testdatensätze, die im relativ übersichtlichen YAML-Format gespeichert werden. Möchte man bestehende Datenbankinhalte als Testdatensätze verwenden, so können Sie direkt in YAML exportiert werden.

Ich halte mich an den Beitrag von NetManiac. Den Code habe ich nur soweit ergänzt, als dass ich das Exportieren der magischen Felder „id“, „created_at“ und „updated_at“ verhindere und den Dateinamen ändere, damit keine bestehenden Fixturen überschrieben werden.

Aufgerufen mit rake extract_fixtures['mymodel'] speichert es mymodel.dumped.yml im richtigen Verzeichnis.

Datei: libs/tasks/extract_fixtures.rake:

desc 'Create YAML test fixtures from data in an existing database.
Defaults to development database. Set RAILS_ENV to override. Use args
table and limit to dump one table and limit number of records'

task :extract_fixtures, :table, :limit, :needs => :environment do |t, args|
  args.with_defaults(:table => nil, :limit => nil)
  limit = args.limit.nil? ? "" : "LIMIT #{args.limit}"
  sql = "SELECT * FROM %s #{limit}"
  skip_tables = ["schema_info" ]
  if args.table.nil?
    tables = ActiveRecord::Base.connection.tables - skip_tables
  else
    tables = [ "#{args.table}"]
  end

  ActiveRecord::Base.establish_connection
  tables.each do |table_name|
    i = "000"
    File.open("#{RAILS_ROOT}/test/fixtures/#{table_name}.dumped.yml" , 'w' ) do |file|
      data = ActiveRecord::Base.connection.select_all(sql % table_name)
      file.write data.inject({}) { |hash, record|
        record.delete_if{|key, value| ['id', 'created_at', 'updated_at'].include?(key)}
        hash["#{table_name}_#{i.succ!}"] = record
        hash
      }.to_yaml
    end
  end
end

ActiveRecord Attribute beim Auslesen mit Defaultwerten überschreiben

Wenn ein Attribut immer beim Auslesen mit eineb bestimmten Wert belegt werden soll wenn noch nichts vorhanden ist, so geht dies mittels folgendem Codefragment:

def my_attribute
  read_attribute(:my_attribute) or another_attribute.capitalize+" "+yet_another_attribute
end

has_and_belongs_to_many mit Checkboxen in Fieldsets

Eine Rolle hat viele Permissions und umgekehrt. Um solche Assoziationen abzubilden, kann man collection_select verwenden, das aber leider nur ein hässliches Listfeld ausgibt. Eine ambitioniertere Variante arbeitet mit Checkboxen.

HABTM mit Checkboxen

HABTM mit Checkboxen

Zuerst wird in Permission.get_indexed_by_controller ein Hash of Hashes gemacht, der als ersten Schlüssel die Überschriften hat (controller) als zweiten Schlüssel die Feldbeschriftungen mit dem Zustand als Inhalt. Folgendes Partial gibt ein Formular aus und versieht sie mit „(Un-)Check all“ Links:

<%= link_to_function 'Check all', "$$('input.permission').each(function(checkbox) { checkbox.checked = true; })" %> |
<%= link_to_function 'Uncheck all', "$$('input.permission').each(function(checkbox) { checkbox.checked = false; })" %>
<% @permissions_indexed_by_controller=Permission.get_indexed_by_controller %>
<br />
<%- for controller in @permissions_indexed_by_controller.keys -%>
  <% field_set_tag controller do %>
    <%- for permission in @permissions_indexed_by_controller[controller] -%>
      <%= check_box_tag 'role[permission_ids][]', permission.id, @role.permissions.include?(permission),{ :id => "role_permission_ids_"+ permission.id.to_s, :class => "permission"} -%><%= permission.description %>
    <%- end -%>
  <% end %>
<%- end -%>

Wichtig ist, dass im entsprechenden Controller in der update Funktion ein leeres Array erzeugt wird wenn nichts übergeben wird, sonst ändert sich nichts wenn man alle Häckchen rausnimmt:

params[:role][:permission_ids] ||= []

Erzeugen eines Hash of Hashes in Ruby

Die Hash/Array implementierung in PHP ist immernoch ungeschlagen. Will man in Ruby ein Hash of Hashes machen und einen Wert mittels << hinzufügen wenn noch kein leerer Hash besteht, so tut es blöd. Insbesondere wenn man Records in einem Hash abspeichen will, hilft folgendes Idiom:

      (ret[map_key] ||= []) << record

Ein Gedanke zu “Kleine Tricks in Ruby on Rails

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.