ruby-on-rails – 从iOS应用程序连接到ActionCable

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 从iOS应用程序连接到ActionCable前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一整天都被困在这里.我有一个非常简单的ActionCable示例应用程序(聊天应用程序)由David Heinemeier Hansson正常工作( https://www.youtube.com/watch?v=n0WUjGkDFS0). @H_404_2@我试图用iPhone应用程序打到websocket连接.当我连接到ws:// localhost:3000 / cable时,我可以收到ping,但是我不太确定如何从JavaScript上下文中订阅频道.

解决方法

哦,我看完这个问题后也经历了这个问题. @H_404_2@过了一会儿,我终于发现了这个神奇的Github问题页面

@H_404_2@https://github.com/rails/rails/issues/22675

@H_404_2@I do understand that this patch would break some tests. That is not
surprising to me. But the original issue I believe is still relevant
and shouldn’t be closed.

@H_404_2@The following JSON sent to the server should succeed:

@H_404_2@{“command”: “subscribe”,”identifier”:{“channel”:”ChangesChannel”}}

@H_404_2@It does not! Instead you must send this:

@H_404_2@{“command”:
“subscribe”,”identifier”:”{\”channel\”:\”ChangesChannel\”}”}

@H_404_2@我终于得到了iOS应用程序订阅房间频道,按照Github用户对Rails问题的建议.

@H_404_2@我的设置如下:

@H_404_2@目标C
>使用PocketSocket框架进行Web套接字连接
> Rails 5 RC1
> Ruby 2.2.4p230

@H_404_2@我假设你知道如何使用Cocoapods来安装PocketSocket.

@H_404_2@相关规范如下:

@H_404_2@ViewController.h

#import <PocketSocket/PSWebSocket.h>

@interface ViewController : UIViewController <PSWebSocketDelegate,UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate>

@property (nonatomic,strong) PSWebSocket *socket;
@H_404_2@ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view,typically from a nib.

    [self initViews];
    [self initConstraints];
    [self initSocket];
}

-(void)initSocket
{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://localhost:3000/cable"]];

    self.socket = [PSWebSocket clientSocketWithRequest:request];
    self.socket.delegate = self;

    [self.socket open];
}

-(void)joinChannel:(NSString *)channelName
{
    NSString *strChannel = @"{ \"channel\": \"RoomChannel\" }";

    id data = @{
                @"command": @"subscribe",@"identifier": strChannel
                };

    NSData * jsonData = [NSJSONSerialization  dataWithJSONObject:data options:0 error:nil];
    NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    NSLog(@"myString= %@",myString);

    [self.socket send:myString];
}

#pragma mark - PSWebSocketDelegate Methods -

-(void)webSocketDidOpen:(PSWebSocket *)webSocket
{
    NSLog(@"The websocket handshake completed and is now open!");

    [self joinChannel:@"RoomChannel"];
}

-(void)webSocket:(PSWebSocket *)webSocket didReceiveMessage:(id)message
{
    NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
    id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    NSString *messageType = json[@"type"];

    if(![messageType isEqualToString:@"ping"] && ![messageType isEqualToString:@"welcome"])
    {
        NSLog(@"The websocket received a message: %@",json[@"message"]);

        [self.messages addObject:json[@"message"]];
        [self.tableView reloadData];
    }
}

-(void)webSocket:(PSWebSocket *)webSocket didFailWithError:(NSError *)error
{
    NSLog(@"The websocket handshake/connection Failed with an error: %@",error);
}

-(void)webSocket:(PSWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean
{
    NSLog(@"The websocket closed with code: %@,reason: %@,wasClean: %@",@(code),reason,(wasClean) ? @"YES": @"NO");
}
@H_404_2@重要的提示

@H_404_2@我还挖了一下订阅类源代码

def add(data)
        id_key = data['identifier']
        id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access

        subscription_klass = connection.server.channel_classes[id_options[:channel]]

        if subscription_klass
          subscriptions[id_key] ||= subscription_klass.new(connection,id_key,id_options)
        else
          logger.error "Subscription class not found (#{data.inspect})"
        end
      end
@H_404_2@注意行:

connection.server.channel_classes[id_options[:channel]]
@H_404_2@我们需要使用该通道的类名.

@H_404_2@DHH YouTube视频使用“room_channel”作为房间名称,但该频道的类文件名为“RoomChannel”.

@H_404_2@我们需要使用类名称而不是通道的实例名称.

@H_404_2@发送消息

@H_404_2@为了防止别人想知道如何发送消息,这里是我的iOS代码向服务器发送消息:

-(void)sendMessage:(NSString *)message
{
    NSString *strMessage = [[NSString alloc] initWithFormat:@"{ \"action\": \"speak\",\"message\": \"%@\" }",message];

    NSString *strChannel = @"{ \"channel\": \"RoomChannel\" }";

    id data = @{
                @"command": @"message",@"identifier": strChannel,@"data": strMessage
                };

    NSData * jsonData = [NSJSONSerialization  dataWithJSONObject:data options:0 error:nil];
    NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    NSLog(@"myString= %@",myString);

    [self.socket send:myString];
}
@H_404_2@这假定您已经连接了您的UITextField来处理按住返回键或某些“发送”按钮的UI.

@H_404_2@这个整个演示应用程序是一个快速的黑客,显然,如果我要在一个真正的应用程序中,我会使我的代码更干净,更可重用,并将其抽象为一个类.

@H_404_2@从真正的iPhone设备连接到Rails服务器:

@H_404_2@为了iPhone应用程序可以在实际的设备上与Rails服务器通话,而不是iPhone模拟器.

@H_404_2@执行以下操作:

@H_404_2@检查您的计算机的TCP / IP地址.例如,在我的iMac上,有些日子可能是10.1.1.10(如果使用DHCP,将来可能会自动更改).
>编辑您的Rail的配置>环境> development.rb文件放在以下行之前的某个地方,如end关键字之前:

@H_404_2@Rails.application.config.action_cable.allowed_request_origins = [‘http://10.1.1.10:3000’]
>使用以下命令启动Rails服务器:

@H_404_2@rails server -b 0.0.0.0
>构建并运行您的iPhone应用程序到iPhone设备上.您现在应该可以连接和发送消息:D

@H_404_2@我从以下链接中获得了这些解决方案:

@H_404_2@Request origin not allowed: http://localhost:3001 when using Rails5 and ActionCable

@H_404_2@Rails 4.2 server; private and public ip not working

@H_404_2@希望能在未来帮助别人.

猜你在找的Ruby相关文章