开发者

how to save data to two models from one form

I have a scenario where I would like to save data to two models from one form.

Basically I have a player which belongs to many teams. So in the new action of players_controller I'd like to have a multiple select box that contains all the teams. then the user can select 2 or 3 of them..click save and they will be saved.

player belonging to many teams is done by a table called playerizations it contains a player_id and team_id columns

so if I want to get all the teams a player belongs to. I just say player.teams

all this relationship is working fine. I would just like to know how to save to playerizations table when new player is created

What I have (it is basically scaffolding model):

  def new
    @player = Player.new
 @teams = Team.all
    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @p开发者_如何学JAVAlayer }
    end

view:

<% form_for(@player) do |f| %>
  <%= f.error_messages %>
...
....
All Teams<br/>
<%= select_tag 'selected_teams[]', options_for_select(@teams.map {|t| [t.team_name, t.id]}), :multiple => true%>
      end

Can I get some hints please? I took a look at railscast regarding this but not much help.


You're describing a has-and-belongs-to-many ("HABTM") relationship but you have not defined it according to Rails convention, so Rails isn't sure how it should update your models.

Player model should say:

has_and_belongs_to_many :teams

Team model should say:

has_and_belongs_to_many :players

This has the happy side effect that not only does "player.teams" give a list of a player's associated teams, but also "team.players" gives the list of the players in a given team.

Your join table must be called "players_teams", because the Rails convention is to use the name of the two models in plural form and joined together in ascending alphabetical order. Renaming your "playerizations" table should be sufficient since it sounds like the table columns are correct.

Your select menu code is almost there; you need something like:

select_tag(
  :player_team_ids,
  options_for_select( @teams.map { | t | [ t.team_name, t.id ] } ),
  {
    :multiple => true,
    :name     => 'player[team_ids][]'
  }
)

It's the "name" assignment that contains the 'magic' to get your team IDs array assigned. The first parameter to "select_tag" is just the form field's name of "player[team_ids][]" with the square brackets turned into underscores or stripped off if at the end of the string, thus generating a recognisable and unique ID for use in the output HTML.

You can then save your player model or update its attributes with standard calls to save() or update_attributes() - no need for additional code per se however Rails falters on validations. If you are editing an existing player's details, then a call to "update_attributes" will result in the teams association being updated first. Then the player is updated; if its validations fail, the team changes will have been saved anyway. It's quite simple to patch around; wrap your call to update_attributes() in a transaction and roll back if update_attributes returns 'false' indicating failure.

success = Player.transaction do
  player.update_attributes( params[ :player ] ) ) or raise ActiveRecord::Rollback
end

The value of 'success' will end up being 'true' for success or 'nil' for failure. This works because the Rollback exception is caught by the transaction block and does not propagate. Setting 'success' to the evaluated result of the block rather than trying to use local variables means that the code is both Ruby 1.8 and Ruby 1.9-friendly.

This is only necessary when updating existing records with HABTM relationships. It is not required when creating new records.

All of the above code is untested and may contain typing errors, so please use with due care and attention.

For more on HABTM:

  • http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

For more on transactions:

  • http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜