Долгое время читатель 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="}
Пожалуйста, обратите внимание: я очень новые рельсы так голым со мной здесь. Кроме того, я просматривал все форумы, которые искали ответ на такой вопрос. Я нашел несколько похожих, но никто из них не работал, когда я их тестировал.
Наконец, взглянув на модели, вам может быть интересно, откуда поступают электронные письма/логины. Они построены внутри модели в нашей системе, но на самом деле не являются частью этого вопроса, поэтому я опустил код для них. Они работают, поэтому проблема не в этом.
В любом случае, спасибо за ваше время и, пожалуйста, дайте мне знать, если вам нужна дополнительная информация.
я могу увидеть, где вы собираетесь с фрагмента кода выше. Я немного изменил его (несколькими способами). Я могу заставить его выполнить без ошибок, но псевдоним никогда не заканчивается обновлением. Я думаю, что приведенный выше пример близок, но не совсем там. – creeves
Возможно вам нужно его сохранить? (team_mate.save) –
@ user.save фактически вызывается сразу после выполнения кода, так что это уже есть. Из-за изощренности, я пробовал это с командой.save, и это все еще не сработало. (Я знаю, что вы сказали «team_mate.save, но код, который я тестирую, немного отличается от того, что вы предложили, - та же концепция, но я сначала перехожу в team_mates, так как команда является вложенным атрибутом team_mates) – creeves