I'm trying to return json-formatted data from my Sinatra REST API. I currently have a bunch of associations set up, but I'm having trouble getting the views I want from my API despite getting them easily in Ruby.
For example, from my tables:
DB.create_table?(:calendars) do
primary_key :id
end
DB.create_table?(:schedules) do
primary_key :id
foreign_key :resource_id, :resources
foreign_key :task_id, :tasks
foreign_key :calendar_id, :calendars
end
In Ruby, I'm able to run a block like this and display all the info I need through my associations:
Calendar.each do |c|
c.schedules.each do |s|
puts "RESOURCE ##{s.resource_id}"
s.tasks.each do |t|
p t
end
puts
end
end
the c.schedules
call works because my calendar
model contains a one_to_many :schedules
association.
Now, I'm wondering how this translates to my Sinatra API. In my simple GET
route, I've tried many variations trying to get the schedules associated with a calendar, and convert it to JSON:
get '/calendars' do
c = DB[:calendar].first
c.schedules.to_json
content_type :json
end
... but I'll end up with an error like undefined method 'schedules' for {:id=>1}:Hash
So it looks like it's returning a hash here, but I've tried a bunch of stuff and haven't figured out how I'm supposed to work with my associations in Sinatra. How can I do this?
Thanks!
The reason your first block works but the second doesn't is because in the first case, you're using a Sequel model instance of class Calendar
, whereas in the second case you're using a Sequel dataset
.
When you iterate over Calendar.each do |c|
, the c
variable gets populated with an instance of a Calendar
class Sequel model object. This object has relationship methods defined (one_to_many
) and you're able to query schedules
and run other model methods on it.
However, c = DB[:calendar].first
gets you a Sequel dataset. This object is different than a model instance, it returns a standard Ruby hash (or an array of hashes).
You can change your 2nd block to use a model instead and it will get the result you want:
get '/calendars' do
c = Calendar.first # <=== CHANGE FROM DATASET TO MODEL
c.schedules.to_json
content_type :json
end