【发布时间】:2019-01-22 17:59:40
【问题描述】:
我正在创建一个应用程序,让用户可以跟踪他们的棋盘游戏。有一个主库,用于将棋盘游戏添加到用户的个人库中。我的代码中的某些内容或多或少使这两个库成为同义词。每次我删除并重新迁移我的数据库时,它都会自动将主库中的所有游戏添加到用户库中。
但这不是我想要解决的问题,它只是沿着相同的路线。当我点击 axios.delete 函数从人员库中删除棋盘游戏时,它也会触发从主库中删除棋盘游戏。由于我目前设置了后端,因此我的用户 has_many board_games 和 board_games has_many users。我认为我的 axios.delete 在通用 board_game 控制器而不是 user_board_games 中使用了我的破坏功能(即使那是我发送它的地方),所以我认为我需要创建一个特定于 user_board_games 的控制器。但是我对 has_many through 的研究只给了我最基本的设置。
这是组件:
import React, { Component } from 'react';
import axios from 'axios';
import { connect } from 'react-redux';
import { Button, Card, Container, Dropdown, Grid } from 'semantic-ui-react'
class Games extends Component {
state = { games:[], user_games: [], showGames: false, sort: "A-Z" }
const userId = this.props.user.id
axios.get('/api/board_games')
.then(res => {
console.log(res.data)
this.setState({games: res.data});
})
axios.get(`/api/users/${userId}/board_games`)
.then(res => {
console.log(res.data);
this.setState({user_games: res.data});
} )
}
toggleGames = () => {
this.setState({ showGames: !this.state.showGames })
}
removeGame = (id) => {
const userId = this.props.user.id
axios.delete(`/api/users/${userId}/board_games/${id}`)
.then(res => {
console.log(res);
})
}
addGame = (id) => {
const userId = this.props.user.id
axios.post(`api/users/${userId}/board_games`, { userId, id })
.then(res => {
console.log(res);
})
}
dropDownMenu = () => {
return ( <Dropdown text='Sort'>
<Dropdown.Menu>
<Dropdown.Item text='A-Z' onClick={() => this.setState({sort: "A-Z"}) }/>
<Dropdown.Item text='Z-A' onClick={() => this.setState({sort: "Z-A"})} />
<Dropdown.Item text='Time Needed' onClick={() =>this.setState({sort: "Time Needed"})} />
</Dropdown.Menu>
</Dropdown>
)
}
userLibrary = () => {
const {user_games, sort} = this.state
switch(sort) {
case 'A-Z':
user_games.sort(function(game1, game2){
if(game1.title < game2.title) {return -1; }
if(game1.title > game2.title) {return 1; }
return 0;
});
break;
case 'Z-A':
user_games.sort(function(game1, game2){
if(game1.title > game2.title) {return -1; }
if(game1.title < game2.title) {return 1; }
return 0;
});
break;
case 'Time Needed':
user_games.sort(function(game1,game2){
return game1.time_needed-game2.time_needed
})
break;
default:
user_games.sort(function(game1, game2){
if(game1.title < game2.title) {return -1; }
if(game1.title > game2.title) {return 1; }
return 0;
});
}
return user_games.map( game =>
<Card key={game.id}>
<Card.Content>
<Card.Header>{game.title}</Card.Header>
<Card.Description>Players: {game.min_players} - {game.max_players}</Card.Description>
<Card.Description>Company: {game.company}</Card.Description>
<Card.Description>Time Needed: {game.time_needed}</Card.Description>
</Card.Content>
<Card.Content extra>
<Button basic color='red' onClick={() => this.removeGame(game.id)}>
Remove from Library
</Button>
</Card.Content>
</Card>
)
}
gamesList = () => {
//gives each game with a link to more info
const { games, user_games } = this.state
return games.map( game =>
<Card key={game.id}>
<Card.Content>
<Card.Header>{game.title}</Card.Header>
<Card.Description>Players: {game.min_players} - {game.max_players}</Card.Description>
<Card.Description>Company: {game.company}</Card.Description>
<Card.Description>Time Needed: {game.time_needed}</Card.Description>
</Card.Content>
{ user_games.include ? (
<Card.Content extra>
<Button basic color='green' onClick={() => this.addGame(game.id)}>
Add to Library
</Button>
</Card.Content>
)
: (
<Card.Content extra>
<Button basic color='red' onClick={() => this.removeGame(game.id)}>
Remove from Library
</Button>
</Card.Content>
)
}
</Card>
)
}
render() {
const { showGames } = this.state
return (
<Container>
<h1>Games</h1>
<Grid>
<Grid.Column floated="left" width={2}>
<h3>Your Games</h3>
</Grid.Column>
<Grid.Column floated="right" width={2}>
{this.dropDownMenu()}
</Grid.Column>
</Grid>
<Card.Group itemsPerRow={4}>{this.userLibrary()}</Card.Group>
{ showGames ? (
<div>
<Button basic onClick={this.toggleGames}>Done Adding</Button>
<Card.Group itemsPerRow={4}>{this.gamesList()}</Card.Group>
</div>
)
: (
<Button basic onClick={this.toggleGames}>Add a Game</Button>
)
}
</Container>
)
}
}
const mapStateToProps = state => {
return { user: state.user };
};
export default connect(mapStateToProps)(Games);
这是棋盘游戏控制器:
class Api::BoardGamesController < ApplicationController
before_action :set_board_game, except: [:index]
def index
render json: BoardGame.all
end
def show
render json: @board_game
end
def create
board_game = BoardGame.new(board_game_params)
if board_game.save
render json: board_game
else
render json: board_game.errors
end
end
def update
if @board_game.update(board_game_params)
render json: @board_game
else
render_error(@board_game)
end
end
def destroy
binding.pry
@board_game.destroy
end
private
def set_board_game
@board_game = BoardGame.find(params[:id])
end
def board_game_params
params.require(:board_game).permit(
:title,
:min_players,
:max_players,
:base_game,
:time_needed,
:company
)
end
end
棋盘游戏模型:
class BoardGame < ApplicationRecord
has_many :game_sessions, through: :game_session_games
has_many :users, through: :user_board_games
has_many :rounds
end
用户模型:
class User < ActiveRecord::Base
has_many :board_games, through: :user_board_games
has_many :game_sessions
# User.joins(:board_games).where("board_games.id == 'user.id'")
# Include default devise modules. Others available are:
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
include DeviseTokenAuth::Concerns::User
end
userBoardGame 模型:
class UserBoardGame < ApplicationRecord
belongs_to :user
belongs_to :board_game
end
那么 user_board_games_controller.rb 中的内容是什么?
class Api::UserBoardGamesController < ApplicationController
def destroy
@user.board_game.destroy
end
end
【问题讨论】:
-
您可能不需要显示那么多代码。当用户有很多棋盘游戏时,
@user.board_game也没有意义
标签: ruby-on-rails reactjs