2016-05-19 6 views
1

Ich sende ein Array von Attributen in Parameter zu meinem Controller und ich muss Validierungsfehler behandeln, wenn es einen Fehler beim Erstellen des Datensatzes gibt.Wie erstellt man mehrere Datensätze und behandelt Validierungen mit create-Methode in Rails?

Da ich mehrere Gruppen auf einmal erstellen müssen.

PARAMETER

Parameters: {"group"=>[{"sort_by"=>"id", "template_ids"=>[182], "name"=>"Csdfwses", "count"=>1}, {"sort_by"=>"id", "template_ids"=>[181], "name"=>"rthydrt", "count"=>1}]} 

So create Methode ist mein Controller ist wie folgt:

def create 
    @groups = Group.create group_params 
    if @groups 
    render json: { success: true, message: "#{@groups.length} groups created" } 
    else 
    render_422 @groups, 'Could not save groups.' 
    end 
end 

i den Fall behandeln will, ob es ein Fehler ist aufgetreten, während jeder Datensatz erstellt, so dass nach dem Erstellen Es sollte die Fehlermeldung anzeigen.

Mit dem obigen Ansatz gibt es keine Möglichkeit error Methode hier zu verwenden. Wie zeigen Sie die Fehlermeldungen an?

Ich versuchte begin-rescue mit:

def create 
    begin 
    @groups = Group.create! group_params 
    if @groups 
    render json: { success: true, message: "#{@groups.length} groups created" } 
    else 
    render_422 @groups, 'Could not save groups.' 
    end 
    rescue ActiveRecord::RecordInvalid => invalid 
    render json: { success: false, message: "#{invalid.record.errors.messages}" }, status: 500 
    end 
end 

aber ich bin für den Reiniger Ansatz suchen, wenn es eine gibt?

Antwort

3

Sie möchten ein Array von Hashes an model.create übergeben, um mehrere Datensätze gleichzeitig zu erstellen.

def create 
    @groups = Group.create group_params 
    if @groups.all? { |group| group.persisted? } 
    render json: { success: true, message: "#{@groups.length} groups created" } 
    else 
    render_422 @groups, 'Could not save groups.' 
    end 
end 

Wenn Sie Validierungsfehler angezeigt werden soll, dann werden Sie in model.errors oder für eine schöne Auswahl von Fehlern suchen möchten Sie bei model.errors.full_messages aussehen kann.

def create 
    @groups = Group.create group_params 
    if @groups.all? { |group| group.persisted? } 
    render json: { success: true, message: "#{@groups.length} groups created" } 
    else 
    errors = @groups.map { |group| group.errors.full_messages.empty? nil : group.errors.full_messages }.compact.join("<br/>") # gross one-liner to show you where the errors live 
    render_422 @groups, "Could not save groups. Here are the errors: #{errors}" 
    end 
end 

Sie möchten die Fehler besser formatieren, aber dies ist ein einfaches Beispiel.

+0

Es ist eine ziemlich schlammig Frage, aber ich glaube, er sucht auf einmal mehrere Gruppen Aufzeichnungen zu schaffen - dies würde nur einen einzelnen Datensatz erstellen. – max

+0

Oh du hast Recht. Ich werde es beheben – Dbz

+0

Ja, ich möchte mehrere Gruppen gleichzeitig erstellen. Ich habe versucht, 'rettung ActiveRecord :: RecordInvalid => invalid' zu verwenden und die Meldungen wie folgt anzuzeigen 'render json: {erfolg: false, nachricht:" # {invalid.record.errors.messages} "}, status: 500' –

4

würden Sie normalerweise accepts_nested_attributes verwenden - aber dies erfordert eine Art hierarchischer Beziehung:

class Company < ActiveRecord::Base 
    has_many :employees 
    accepts_nested_records_for :employees 
    validates_associated :employees 
end 

class Employee < ActiveRecord::Base 
    belongs_to :company 
    validates_presence_of :name 
end 

c = Company.new(name: 'Acme', employee_attributes: [ 
    { name: 'Wile E. Coyotee' }, 
    { name: 'Bugs Bunny' }, 
    { name: nil } # invalid 
]) 

c.valid? # false 
c.save # false 

Wie würden Sie dies tun, ohne ein übergeordnetes Modell? Erstellen Sie ein Modell, das wie ein Elternverein fungiert:

# A fake parent model for groups. 
# This is not a ActiveRecord model 
# It's is not backed by a database table. 
class GroupCollection 
    include ActiveModel::Model 
    attr_accessor :groups 

    def initialize(*args, groups_attributes: [], **kw_args) 
    super 
    end 

    # mimics behavior of accepts_nested_attributes 
    # takes either an array or a key/val hash: 
    # { 1 => {'name' => 'foo'} } 
    def groups_attributes=(attrs) 
    # normalize key/val hash 
    attrs = attrs.values if attrs.is_a?(Hash) 
    self.groups = attrs.map {|h| Group.new(h) } 
    end 

    # mimics behavior of validates_associated 
    def valid? 
    errors.clear 
    # alternatively you can aggregate errors for 
    # the nested records on the parent object 
    if groups.reject { |g| g.valid? }.any? 
     errors.add(:groups, 'are invalid.') 
    end 
    errors.none? 
    end 

    def save 
    return false unless valid? 
    save_in_transaction 
    end 

    def save! 
    raise ActiveRecord::RecordInvalid and return unless valid? 
    save_in_transaction 
    end 

    private 
    def save_in_transaction 
     # use a transaction so changes are rolled back if a save fails. 
     Group.transaction do 
     groups.reject { |g| g.save! }.none? 
     end 
    end 
end 

class GroupsController 

    def create 
    @collection = GroupCollection.new(groups_params) 
    @groups = @collection.groups 

    if @collection.save 
     c = @groups.length 
     render json: { 
      success: true, # anti-pattern! - rely on the response code instead 
      message: "#{c} #{pluralize(c, 'group')} created" 
     }, status: :created 
    else 
     # you can get the error messages by iterating through @groups 
     # and calling `.errors.full_messages` on each 
     render_422 @groups, 'Could not save groups.' 
    end 
    end 

    def collection_params 
    params.permit(groups_attributes: [:name, :foo, :bar]) 
    end 
end 
Verwandte Themen