Ruby instance backup variables with exceptions

I make a card game in ruby.

I have a Game class that has an array of Player objects.

array_of_players = Array[ Player.new("Ben"), Player.new("Adam"), Player.new("Peter"), Player.new("Fred"), ] my_game = Game.new(array_of_players) puts my_game.players[2].name #=> Peter 

Each player also has access to the game, so that they can access important bits of the game, thus

 self.game.last_card_dealt 

Each player also has cards (Player.cards), and I want to make sure that players cannot access other cards. However, the player needs access to the cards, so I don’t think private is suitable, and the players need access to some other information, so I don’t think I want it to be private either ...

Basically, I want them to work.

 self.cards #where self is a Player object self.players[0].cards #where self is the Game self.game.players[0].name #where self is a Player object 

And this fails:

 self.hand.players[0].cards #=> Nice try sucker! Cheating is for losers. 

How are more complex permissions, for example, handled? Thanks.

+4
source share
4 answers

Thanks for all your answers.

In the end, I realized that I could give the authorized object the key that is used to access the meat of the method.

The game object has @auth_object and sets it to the player object that it intends to access the secret methods, and the player’s secret method checks if hand.auth_object is self , otherwise it does nothing. Then @auth_object returns to zero. There is attr_reader, but no writer for @auth_object.

It works.

+1
source

This is more practical than my other answer, and uses the Game object as a delegate for all the information in the game itself (Players, Maps, etc.). Please note that you still need to trust the caller to get through yourself, but seriously, where do you draw the line?

 class Player attr_reader :name def initialize(name) @name = name end end class Cards attr_accessor :cards end class Game attr_reader :name, :players def initialize(players) @name = "Game Master" @hands = [] @players = players.each do |p| puts "Added %s to game." % p.name @hands << {:player => p, :cards => Cards.new} end end def view_hand(player, caller) @hands.each do |hand| if hand[:player] == player if hand[:player] == caller or caller == self puts "%s: You can access all these cards: %s" % [caller.name, hand[:cards]] else # Do something to only display limited cards depending on this caller view capabilities puts "%s: You can only access the cards I will let you see: %s" % [caller.name, hand[:cards]] end end end end def my_cards(player) @hands.each do |hand| puts "%s cards: %s" % [player.name, hand[:cards]] if hand[:player] == player end end end g = Game.new([Player.new('Bob'), Player.new('Ben')]) puts "\nCalling each Player cards as each Player:\n\n" g.players.each do |gp| g.players.each do |p| g.view_hand(gp, p) end end puts "\nCalling each Player cards as Game:\n\n" g.players.each do |p| g.view_hand(p, g) end puts "\nEach Player calls for their own cards:\n\n" g.players.each do |p| g.my_cards(p) end 

Exit:

  Added Bob to game. Added Ben to game. Calling each Player cards as each Player: Bob: You can access all these cards: #<Cards:0x100121c58> Ben: You can only access the cards I will let you see: #<Cards:0x100121c58> Bob: You can only access the cards I will let you see: #<Cards:0x100121bb8> Ben: You can access all these cards: #<Cards:0x100121bb8> Calling each Player cards as Game: Game Master: You can access all these cards: #<Cards:0x100121c58> Game Master: You can access all these cards: #<Cards:0x100121bb8> Each Player calls for their own cards: Bob cards: #<Cards:0x100121c58> Ben cards: #<Cards:0x100121bb8> 
+3
source

Keep Game.player private to prevent players from accessing other players through the array.

for example, When self is a player, self.game.players[0].name is stupid.

Perhaps you need a publicly available Game.player_names method that simply returns an array of player names?

Alternatively, you can make the Players.opponents method publicly available.

Examples

Game.player_names

 class Game # ... def player_names self.players.collect { |p| p.name } end private # private game methods end 

Player.opponents

 class Player # ... def opponents(i=nil) return i.nil? ? self.game.player_names : self.game.player_names[i] end end 
+2
source

It was fun to play with. I am not sure if this is the best answer, but it works. The key must pass the caller to Player.cards (obj) and check whether it is either the Player itself or the Game type, both of which have legal access.

 class Player attr_accessor :name, :game attr_writer :cards def initialize(name) @name = name @game = nil @cards = nil end def cards(caller) puts "%s cards called by %s." % [self, caller] if caller.kind_of?(Game) or caller == self puts "Here your cards %s." % @cards else puts "Nice try sucker! Cheating is for losers." end end end class Cards def initialize @cards = [1, 2, 3] end end class Game attr_reader :players def initialize(players) @players = players.each do |p| puts "Added %s to game." % p.name p.game = self p.cards = Cards.new end end end g = Game.new([Player.new('Bob'), Player.new('Ben')]) puts "\nCalling each Player cards as each Player:\n\n" g.players.each do |gp| g.players.each do |p| p.cards(gp) end end puts "\nCalling each Player cards as Game:\n\n" g.players.each do |p| p.cards(g) end 

And the conclusion:

  Added Bob to game. Added Ben to game. Calling each Player cards as each Player: #<Player:0x100122b30> cards called by #<Player:0x100122b30>. Here your cards #<Cards:0x1001229c8>. #<Player:0x100122ae0> cards called by #<Player:0x100122b30>. Nice try sucker! Cheating is for losers. #<Player:0x100122b30> cards called by #<Player:0x100122ae0>. Nice try sucker! Cheating is for losers. #<Player:0x100122ae0> cards called by #<Player:0x100122ae0>. Here your cards #<Cards:0x100122928>. Calling each Player cards as Game: #<Player:0x100122b30> cards called by #<Game:0x100122ab8>. Here your cards #<Cards:0x1001229c8>. #<Player:0x100122ae0> cards called by #<Game:0x100122ab8>. Here your cards #<Cards:0x100122928>. 
+2
source

Source: https://habr.com/ru/post/1303096/


All Articles