2

Stackoverflow の長年の読者ですが、自分が質問をする立場にあることに気付いたことはありません (まだ回答されていません)。すべてが初めてだと思うので、ここに行きます...

システム情報:
Ruby バージョン = 1.8.7
Rails バージョン = 3.2.2

状況:
ユーザー登録システムが導入されているアプリケーションがあります。すべてのテーブルを正しく接続して入力するために、登録ビュー内で複雑な/ネストされたフォームを利用しています。実際、ネストされたフォームは完全に機能しており、すべてが正常に入力されています。本当に素晴らしいです。

問題は次のとおりです。フォームの投稿後、レコードが保存される前に、ネストされた属性の値の 1 つを設定する必要があります。

ここに簡単な例を示します。これは、私が話していることをもう少しよく理解できるようにするためです。ユーザーが私たちのサイトに登録します。ユーザーが登録すると、Users データ テーブルにレコードが作成されます。各ユーザーは team_mate (結合テーブル) としても分類され、(最初は) 独自のチームに割り当てられます。ただし、「チーム」(テーブル) には「エイリアス」フィールドもあり、ユーザーの最初の作成時に、ユーザーのファースト ネームを設定したいと考えています (ファースト ネームを 'フォームのエイリアスのフィールド)。

したがって、質問は次のようになると思います: フォームの投稿後、レコードがデータベースに保存される前に、ネストされた属性の値を手動で設定するにはどうすればよいですか?

テーブル スキーマの外観の (単純な) 例は次のとおりです。

ユーザー (id、first_name、last_name、created_at、updated_at)

Team_mates(id, user_id, team_id, created_at, updated_at) - テーブルに参加

チーム (id、エイリアス、created_at、updated_at)

モデル:

ユーザー.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"=>"lpisfsopf@psflsjdk.com"}}, "login_attributes"=>{"user_login"=>"lkjsdfooiusfd", "password_encrypted"=>"[FILTERED]"}}, "utf8"=>"✓", "commit"=>"Create User", "authenticity_token"=>"CQLQ93/0VlncSzMlmtLPHgaVrrvjuHFN+lN6CYCsiR8="}

モデルを見た後、電子メール/ログインがどこから来ているのか疑問に思うかもしれません. それらはシステムのモデル内に構築されていますが、実際にはこの質問の一部ではないため、それらのコードは省略しました. 彼らは働いているので、問題はその側にはありません。

4

1 に答える 1

0

http://archives.ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes を確認してください

新しいオブジェクトの作成と既存のオブジェクトの編集の両方をサポートするには、1 対多の関連付けにはハッシュの配列を使用するか、1 対 1 の関連付けには単一のハッシュを使用する必要があります。:id プロパティが存在しない場合は、作成するネストされたモデルを表すと見なされます。

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
于 2012-06-06T17:23:28.347 に答える