2012-06-06 2 views
1

Долгое время читатель Stackoverflow, но так и не смог задать вопрос (на который еще не был дан ответ). Я предполагаю, что это первый раз за все, так вот она идет ...Rails - обновлять вложенные атрибуты перед сохранением в базе данных

System Info:
Рубин Version = 1.8.7
Rails версии 3.2.2 =

Ситуация:
У нас есть приложение с системой регистрации пользователей на месте. Чтобы правильно подключить и заполнить все наши таблицы, мы используем сложные/вложенные формы в окне регистрации. У меня действительно есть вложенные формы, которые работают отлично, все заполняется так, как должно, это действительно потрясающе.

В чем проблема: мне нужно установить одно из значений одного из вложенных атрибутов ПОСЛЕ публикации формы, но до того, как записи сохранены.

Вот краткий пример, чтобы вы могли видеть, что я говорю о немного лучше: Пользователь регистрируется на нашем сайте. Когда они регистрируют запись, создается в таблице данных «Пользователи». Каждый пользователь также классифицируется как team_mate (join table) и присваивается своей собственной отдельной команде (сначала). Но в «команде» (таблице) также есть поле «псевдоним», в котором при первоначальном создании пользователя мы хотели бы указать имя пользователя (без необходимости вводить их имя в " псевдоним "на форме).

Итак, я задал вопрос: Как мне вручную установить значение вложенного атрибута после сообщения формы и до того, как записи будут сохранены в базе данных?

A (упрощенно) Пример схемы таблицы выглядит следующим образом:

Users (идентификатор, first_name, last_name, created_at, updated_at)

Team_mates (ID, user_id, team_id, created_at, updated_at) - присоединяйтесь таблице

Команда (идентификатор, псевдоним, created_at, updated_at)

Модели:

User.rb

class User < ActiveRecord::Base 
    has_many :team_mates, :dependent => :destroy 
    has_many :teams, :through => :team_mates, :foreign_key => :team_id 
    accepts_nested_attributes_for :team_mates, :allow_destroy => true 

    before_save :set_defaults 

    private 
    def set_defaults 
     #want to set :users => :team_mates_attributes => :team_attributes => :alias to @user.first_name here 

     # Would prefer to handle this here instead of in the controller. 
    end 
    end 

Team.rb

class Team < ActiveRecord::Base 
    has_many :team_mates, :dependent => :destroy 
    has_many :users, :through => :team_mates, :foreign_key => :user_id 

end 

Team_mate.rb

class TeamMate < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :team 

    accepts_nested_attributes_for :team, :allow_destroy => true 
end 

Контроллер

Users_controller.rb

class UsersController < ApplicationController 

def new 
    @user = User.new 
    @user.emails.build(:is_default_email => 1) 
    @user.build_login 

    @user.team_mates.build.build_team(:alias => 'Clinton444', :created_at => Time.new, :updated_at => Time.new) 

    respond_to do |format| 
    format.html 
    format.json { render :json => @match } 
    end 
end 

def create 
    @user = User.new(params[:user]) 

    @user.attributes = ({ "user" => { "team_mates" => { "team" => { "alias" => @user.first_name } } } }) #--this doesn't work... 

    @user.attributes = ({ :user => { :team_mates => { :team => { :alias => @user.first_name } } } }) #--neither does this... 


    respond_to do |format| 
    if @user.save 
     format.html { redirect_to(@user, :notice => 'User was successfully created.') } 
     format.json { render :json => @user, :status => :created, :location => @user } 
    else 
     format.html { render :action => "new" } 
     format.json { render :json => @user.errors, :status => :unprocessable_entity } 
    end 
    end 
end 

Посмотреть

new.html.Haml

= form_for(@user, :html => {:class => 'form-horizontal'}) do |f| 
- if @user.errors.any? 
    .alert 
    %h2 
     = pluralize(@user.errors.count, "error") 
     prohibited this post from being saved: 
    %ul 
     - @user.errors.full_messages.each do |msg| 
     %li 
      = msg 
%fieldset 
.control-group 
    = f.label :first_name, :class => "control-label" 
    .controls 
    =f.text_field :first_name, :class => "span8" 

.control-group 
    = f.label :last_name, :class => "control-label" 
    .controls 
    =f.text_field :last_name, :class => "span8" 

= f.fields_for :emails do |e| 
    =e.hidden_field :is_default_email, :class => "span8" 

    .control-group 
    = e.label :email, :class => "control-label" 
    .controls 
     =e.text_field :email, :class => "span8" 

= f.fields_for :team_mates do |tm| 
    = tm.fields_for :team do |t| 
    =t.hidden_field :alias, :class => "span8" 
    =t.hidden_field :created_at, :class => "span8" 
    =t.hidden_field :updated_at, :class => "span8" 

= f.fields_for :login do |e| 
    .control-group 
    = e.label :user_login, :class => "control-label" 
    .controls 
     =e.text_field :user_login, :class => "span8" 

    .control-group 
    = e.label :password_encrypted, :class => "control-label" 
    .controls 
     =e.text_field :password_encrypted, :class => "span8" 

.control-group 
    .controls 
    =f.submit :class => 'btn btn-primary btn-medium' 

И, наконец, вывод сервера

Rails по форме поста

Parameters: {"user"=>{"team_mates_attributes"=>{"0"=>{"team_attributes"=>{"created_at"=>"Wed Jun 06 09:52:19 -0600 2012", "alias"=>"asfs444", "updated_at"=>"Wed Jun 06 09:52:19 -0600 2012"}}}, "first_name"=>"lkjlkjlsdfslkjeowir", "last_name"=>"ouisodifuoixv", "emails_attributes"=>{"0"=>{"is_default_email"=>"1", "email"=>"[email protected]"}}, "login_attributes"=>{"user_login"=>"lkjsdfooiusfd", "password_encrypted"=>"[FILTERED]"}}, "utf8"=>"✓", "commit"=>"Create User", "authenticity_token"=>"CQLQ93/0VlncSzMlmtLPHgaVrrvjuHFN+lN6CYCsiR8="} 

Пожалуйста, обратите внимание: я очень новые рельсы так голым со мной здесь. Кроме того, я просматривал все форумы, которые искали ответ на такой вопрос. Я нашел несколько похожих, но никто из них не работал, когда я их тестировал.

Наконец, взглянув на модели, вам может быть интересно, откуда поступают электронные письма/логины. Они построены внутри модели в нашей системе, но на самом деле не являются частью этого вопроса, поэтому я опустил код для них. Они работают, поэтому проблема не в этом.

В любом случае, спасибо за ваше время и, пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

ответ

0

Проверить http://archives.ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

Чтобы поддержать и создание новых объектов и редактирование существующих, мы должны использовать массив хэшей один-к-многим ассоциации или один хэш для одно- к-одному. Если нет: id свойство существует, то предполагается, что он представляет собой вложенную модель для create.

Не 100% уверен, что .. Я не использовал \ протестировали его и раньше, но это должно дать вам представление о том

@user.teams.each do |team| 
    team.team_mates do |team_mate| 
    # To edit existing 
    team_mate.team_attributes = [ { :id => team.id, :alias => @user.first_name } ] 

    # To create new 
    team_mate.team_attributes = [ { :alias => @user.first_name } ] 

    team_mate.save 
    end 
end 
+0

я могу увидеть, где вы собираетесь с фрагмента кода выше. Я немного изменил его (несколькими способами). Я могу заставить его выполнить без ошибок, но псевдоним никогда не заканчивается обновлением. Я думаю, что приведенный выше пример близок, но не совсем там. – creeves

+0

Возможно вам нужно его сохранить? (team_mate.save) –

+0

@ user.save фактически вызывается сразу после выполнения кода, так что это уже есть. Из-за изощренности, я пробовал это с командой.save, и это все еще не сработало. (Я знаю, что вы сказали «team_mate.save, но код, который я тестирую, немного отличается от того, что вы предложили, - та же концепция, но я сначала перехожу в team_mates, так как команда является вложенным атрибутом team_mates) – creeves

Смежные вопросы