Do you mean something like Board:GetName() ?
Yup
Welp, guess I have to give up on this one, I was hoping to be able to create an API that used metamethods to read or edit properties on Trello. Thank you.
I believe you could fetch the board while using a method like @Crazyman32 said?
Perhaps I’m wrong but couldn’t you just return a table from your method that includes the name, etc…
local Board = Trello:GetBoard()
Board.Name = "Hey!"
I could be wrong but that seems like it’d work as long as you have a way in your index to actually update the boards name.
Only downside to this is that it won’t necessarily work both ways. For setting data, you’d still have to use the method approach.
In my opinion, using methods makes it more clear about what’s happening. If I access or write to something using dot-notation, I don’t expect it to yield. Getters and setters are good for these things. So in terms of OOP, I think it’s better to approach it with the Java-like coding practices (getters/setters), rather than C# (properties with implicit getters/setters).
Update:
After doing some research, I found out that this is a limitation in Lua 5.1.
In Lua 5.3 and LuaJIT, you can yield in metamethods.
I hope that some day ROBLOX updates to either. I understand it will be very difficult to do so, but I believe it would bring a lot of possibilities in regards of scripting. Stuff like bitwise operators, yielding in metamethods, etc.
You can make it a callback function and put the yielding part in a switch function or a coroutine. For example:
function fn()
end
local trello = {}
setmetatable(trello, {__index = function(self, i)
if i == 'Name' then
spawn(function()
local res = http:PostAsync....
fn(res)
end)
end
end})
Something similar to that approach can work, but I really don’t see why you need to use the meta method for this.
Another solution would be to immediately return a “promise” or another object which will later be updated when the response is ready. For example, you could write:
-- A method to wait for the value
local name = Board.Name.value()
or
-- A callback when the value is ready
Board.Name.ready(print)
or
-- functions that use promises wait for their value
local function newPrint(a)
if isPromise(a) then
print(a.value())
else
print(a)
end
end
local name = Board.Name
newPrint(name)
Promises are a common functional programming pattern (and therefore naturally better than OOP methods which I have a personal vendetta against).
Using PostAsync is not a problem here, I already took care of that part.
The problem is GetAsync, as it needs to wait for the value to be returned.
I am using metamethods to integrate Trello to ROBLOX in a way that would make it seem it is part of ROBLOX, in this case, manipulating the objects in the same manner you would manipulate any other object in the game.
I will look into this, thank you.
I have said PostAsync as an example. It’s will also work for GetAsync.
What does the 3rd argument “fn” in the __index function actually do?
I finally got a chance to test the code, fn is nil.
The 3rd argument is only used in __newindex.
fn is supposed to be an external callback function.
If you insist on using meta-methods for this project, I have created a small code for you. This is as close as you can go with meta-methods yielding.
local http = game:GetService'HttpService'
local mt = {}
setmetatable(mt, {
__newindex = function(self, i, name)
if i == 'Name' then
spawn(function()
-- HTTP Post code to change the name
end)
else
self[i] = name
end
end,
__index = function(self, i)
if i == 'Name' then
local t = {}
function t:wait()
return http:GetAsync'...' -- The http get request
end
return t
end
end,
})
mt.Name = 'something'
print(mt.Name:wait())
Ah, thank you. This will work wonderfully!
I might make the function :Get()
You are welcome. You could also create a function that will regularly update the name and save yourself from yielding. But this is less efficient as it will use more requests(Cant compare really, that depends on the usage).
I did think about that, but then there’s the rate limits.
Yeah, alright
I feel like this is making the task more complicated than it needs to be. It’s just much cleaner using standard getters/setters IMHO:
local Board = {}
Board.__index = Board
function Board.new()
local self = setmetatable({}, Board)
return self
end
function Board:GetName()
-- Fetch the name
if (not self.Name) then
self.Name = -- Whatever you need to do to fetch the name via HTTP
end
return self.Name
end
function Board:SetName(name)
-- Set the name
self.Name = name
-- Then push the name via HTTP
end
Obviously though the above code is not “thread-safe” per-se, since self.Name
might be in an in-between state where the HTTP service is fetching or setting the name.
After a lot of thinking, I concluded the same thing you did.
I’ll just have to give up on metamethods.