我是Ruby
的新用户,并使用ActiveAdmin
进行一些简单的管理。
我有一个模型Question
我想创建,填充并存储到数据库,它有一个属性themes
(Theme
模型数组)。当用户创建新记录时,他不会手动输入主题但提供一些字符串,系统将自动解析它并查找或创建主题。所以我有这样的代码:
form do |f|
f.inputs "Questions Details" do
f.input :question, as: :string
f.input :autocomplete_themes, hint: "You should enter here multiple themes,
divide them with `,` or `;`"
end
f.actions
end
它会为输入字符串创建一个新字段autocomplete_themes
,并且它不存在于模型Question
中。所以我想要的是 - 获取autocomplete_themes
值,如字符串,然后使用split()
和我的自定义逻辑 - 但它会出错。
before_create do |question|
array = []
puts "******"
puts :autocomplete_themes.text
themeTitles = :autocomplete_themes.split(",") #split(/,|;/)
for title in themeTitles do
theme = Theme.find_by(title: title)
theme = Theme.create(title: title) unless theme
array << theme
end
question.themes = array
end
问题:如何将autocomplete_themes
值作为字符串? THX!
更新:正如我所理解的here - 它看起来像是类似的情况,但是将默认值设置为自定义字段存在问题,但我需要从代码中获取其值。
答案 0 :(得分:2)
您没有指定所获得的错误,但根据您提供的信息,您不需要Question
成为before_create
模型的真正数据库支持的属性,而是您只需要临时获取信息,以便autocomplete_themes
过滤器可以使用它来执行适当的逻辑。
因此,您可以使Question
成为“虚拟属性”,就像class Question < ActiveRecord::Base
attr_writter :autocomplete_themes
attr_reader :autocomplete_themes
...other code
end
实例的传统成员变量。
@question.autocomplete_themes = "1,2,3"
themes_text = @question.auto_complete_themes
这将允许您执行以下操作:
form do |f|
f.inputs "Questions Details" do
f.input :question, as: :string
f.input :autocomplete_themes, hint: "You should enter here multiple themes,
divide them with `,` or `;`"
end
f.actions
end
最重要的是,ActiveAdmin支持将表单输入分配给虚拟属性。所以你可以保持这样的形式:
before_filter
你的before_create do |question|
array = []
themeTitles = question.autocomplete_themes.split(",") #split(/,|;/)
for title in themeTitles do
theme = Theme.find_by(title: title)
theme = Theme.create(title: title) unless theme
array << theme
end
question.themes = array
end
看起来像这样:
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
namespace blockbattle
{
public class AsyncServer
{
private const int port = 11000;
public int clientID = -1;
public string serverPos = "";
public string clientPos = "";
public string newBullets = "";
public bool bulletsSent = false;
public string receivedBullets = "";
public void StartServer()
{
Thread thread = new Thread(Run) { IsBackground = true };
thread.Start();
}
private void Run()
{
Debug.WriteLine("Running");
TcpListener tcpListener = new TcpListener(IPAddress.Loopback, port);
tcpListener.Start();
while (true)
{
Debug.WriteLine("Before Accept");
ServerState state = new ServerState { WorkSocket = tcpListener.AcceptSocket() };
Debug.WriteLine("Before Receive");
Receive(state);
}
}
private void Receive(ServerState state)
{
state.WorkSocket.BeginReceive(state.Buffer, 0, ServerState.BufferSize, 0, ReceiveCallBack, state);
}
private void ReceiveCallBack(IAsyncResult ar)
{
ServerState state = (ServerState)ar.AsyncState;
try
{
int byteReceived = state.WorkSocket.EndReceive(ar);
if (byteReceived > 0)
{
string receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
string[] receivedData = receivedString.Split('+');
clientID = int.Parse(receivedData[0]);
clientPos = receivedData[1];
if (receivedData[2].Length > 0)
receivedBullets = receivedData[2];
byte[] bytesToSend = Encoding.UTF8.GetBytes(string.Format("{0}+{1}", serverPos, newBullets));
if (newBullets.Length > 0)
{
newBullets = "";
bulletsSent = true;
}
Array.Copy(bytesToSend, state.Buffer, bytesToSend.Length);
state.WorkSocket.Send(state.Buffer, 0, bytesToSend.Length, SocketFlags.None);
Array.Clear(state.Buffer, 0, state.Buffer.Length);
Receive(state);
}
}
catch (Exception e)
{
Debug.Print(e.ToString());
}
}
private class ServerState
{
public const int BufferSize = 1024;
public readonly byte[] Buffer = new byte[BufferSize];
public Socket WorkSocket = null;
}
}
}