以多对多关系连接两个模型

时间:2015-07-06 22:31:42

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord

我有问题。 我希望在我的播放器中显示所有比赛#show显示玩家参与的地方。所以我做了很多对多的关系。

匹配模型:

class Match < ActiveRecord::Base
  has_many :match_schedules
  has_many :players, through: :match_schedules
end

玩家模型:

class Player < ActiveRecord::Base
  has_many :match_schedules
  has_many :matches, through: :match_schedules
  has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end

和我的match_schedule模型:

class MatchSchedule < ActiveRecord::Base
  belongs_to :player
  belongs_to :match
end

如果我在rails console中执行类似的操作:

p = Player.find 1
m = p.matches.new
m.playerA = “leo”
m.playerB = “cris”
p.save

它可以工作,我可以显示名称循环:

<% @player.matches.each do |match| %>
<%= match.playerA %>
<% end %>

问题是我真的不知道如何在浏览器中以新的形式将匹配连接到播放器。我已经有这样的事情了: Players_helper:

module PlayersHelper
  def player_hash(players)
    hash = Hash.new
    players.each do |player|
      hash["#{player.first_name}" + " " + "#{player.last_name}"] = player.first_name + player.last_name
    end
    hash
  end
end

和_form:

  <div class="form-inputs">
    <%= f.select :playerA, options_for_select(player_hash(@abc)) %>
    <%= f.select :playerB, options_for_select(player_hash(@abc)) %>
    <%= f.input :PlayerApoints %>
    <%= f.input :PlayerBpoints %>
  </div>

匹配new和create方法的控制器如下:

  def new
    @match = Match.new
    @abc = Player.all
  end
  def create
    @match = Match.new(match_params)
    respond_to do |format|
      if @match.save
        format.html { redirect_to @match, notice: 'Match was successfully created.' }
        format.json { render :show, status: :created, location: @match }
      else
        format.html { render :new }
        format.json { render json: @match.errors, status: :unprocessable_entity }
      end
    end
  end

我的schema.rb:

ActiveRecord::Schema.define(version: 20150706185030) do
create_table "match_schedules", force: :cascade do |t|
    t.integer  "match_id"
    t.integer  "player_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
create_table "matches", force: :cascade do |t|
    t.string   "playerA"
    t.string   "playerB"
    t.integer  "PlayerApoints"
    t.integer  "PlayerBpoints"
    t.datetime "created_at",    null: false
    t.datetime "updated_at",    null: false
  end
create_table "players", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.datetime "created_at",          null: false
    t.datetime "updated_at",          null: false
    t.string   "avatar_file_name"
    t.string   "avatar_content_type"
    t.integer  "avatar_file_size"
    t.datetime "avatar_updated_at"
  end
create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

1 个答案:

答案 0 :(得分:0)

你遗漏了你的match_params哈希,所以我必须做一些猜测,但有些东西: 在你的Match类中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FAFAFA">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:text="lacci"
        android:id="@+id/lacci_row"
        android:textSize="16sp"
        android:textColor="#000"
        android:layout_gravity="center_horizontal"
        android:gravity="left|center_vertical"/>

</LinearLayout>

在您的控制器中:

class Match < ActiveRecord::Base
  has_many :match_schedules
  has_many :players, through: :match_schedules
  accepts_nested_attributes_for :match_schedules
end

在您的match_params白名单中,您需要添加:

def new
  @match = Match.new
  @match.match_schedules.build
  @abc = Player.all
end

def create
    @match = Match.new(match_params)
    respond_to do |format|
      if @match.save
        format.html { redirect_to @match, notice: 'Match was successfully created.' }
        format.json { render :show, status: :created, location: @match }
      else
        format.html { render :new }
        format.json { render json: @match.errors, status: :unprocessable_entity }
      end
    end
  end

因为它是一个数组,你需要把它放在其他参数之后。

您还必须修改视图代码。基本上你想要返回..., :player_ids => []) ,这使你能够告诉match_shedules_attributes => {player_ids => [1,2]}表格与MatchSchedule相关联的每个玩家的ID。您可以使用match_id块内的fields_for执行此操作。见http://guides.rubyonrails.org/form_helpers.html

因此,在匹配控制器的form_for操作中,它还应该在MatchSchedule表中保存两个记录,一个记录每个玩家的ID和该匹配的ID。