{"id":16222901,"url":"https://github.com/michael/ken-rb","last_synced_at":"2025-10-11T14:35:50.733Z","repository":{"id":63521679,"uuid":"161243","full_name":"michael/ken-rb","owner":"michael","description":"A Ruby API for accessing Freebase. It wraps the Metaweb Architecture to smart Ruby Objects.","archived":false,"fork":false,"pushed_at":"2012-08-15T04:57:47.000Z","size":324,"stargazers_count":135,"open_issues_count":4,"forks_count":16,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-01T21:02:27.451Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://quasipartikel.at/2009/05/02/ken/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michael.png","metadata":{"files":{"readme":"README.textile","changelog":"History.txt","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2009-03-27T20:15:40.000Z","updated_at":"2024-07-24T16:46:32.000Z","dependencies_parsed_at":"2022-11-20T14:45:25.202Z","dependency_job_id":null,"html_url":"https://github.com/michael/ken-rb","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/michael/ken-rb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael%2Fken-rb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael%2Fken-rb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael%2Fken-rb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael%2Fken-rb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michael","download_url":"https://codeload.github.com/michael/ken-rb/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael%2Fken-rb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279007448,"owners_count":26084313,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T12:15:44.987Z","updated_at":"2025-10-11T14:35:50.683Z","avatar_url":"https://github.com/michael.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"h1. Ken\n\nh2. Introduction\n\nKen is a Data Layer for Knowledge Representation.\n\nIt's being built to access the Metaweb Services supplied by Freebase.com.\nThe project’s goals are the provision of a concise API for querying and writing.\nTherefore it wraps the Metaweb Architecture to smart Ruby Objects.\n\nYou can navigate the Freebase Graph using a rubyish syntax.\nAlso you can use this library as a Data Layer (instead of or in addition to ActiveRecord/DataMapper) for your Web Framework of choice (Merb, Rails).\n\nh2. Installation\n\nUse \"Gemcutter\":http://gemcutter.org RubyGems:\n\n\u003cpre\u003e\n\u003ccode\u003e\n  $ gem install gemcutter\n  $ gem tumble\n  $ gem install ken\n\u003c/code\u003e\n\u003c/pre\u003e\n\nIn your Ruby files add:\n\n\u003cpre\u003e\n\u003ccode\u003e\n  require 'rubygems'\n  require 'ken'\n\u003c/code\u003e\n\u003c/pre\u003e\n\n\nh2. Getting started\n\nThe first place to get started with Freebase is of course, Freebase. Try out their Browser at \n\"http://www.freebase.com\":http://www.freebase.com.\n\nThe Freebase Database can be thought of as a huge graph of interconnected nodes that represent \nknowledge (in a much more structured way than wikipedia does).\nThat graph can be viewed at a higher level through an object-oriented lens which leads to easier interaction.\nTo understand the fundamental Metaweb Architecture please read the official\n\"MQL Reference guide\":http://wiki.freebase.com/images/8/87/MQLReferenceGuide.pdf (with focus on Chapter 2)\nprovided by Freebase.\n\nIn addition, you can learn a lot by employing the Freebase \"Query Editor\":http://www.freebase.com/tools/queryeditor/.\n\nh3. Fetching a Resource\n\nLet's ask Ken what he knows about the British Band New Order.\n\n\u003cpre\u003e\n\u003ccode\u003e\n  resource = Ken.get('/en/new_order') # =\u003e \u003cResource id=\"/en/new_order\" name=\"New Order\"\u003e\n\u003c/code\u003e\n\u003c/pre\u003e\n\nh3. Inspecting the Types\n\nEvery Resource can have multiple types.\n\n\u003cpre\u003e\n\u003ccode\u003e\n  resource.types\n  # =\u003e [ #\u003cType id=\"/film/music_contributor\" name=\"Film music contributor\"\u003e, #\u003cType id=\"/music/artist\" name=\"Musical Artist\"\u003e, \n         #\u003cType id=\"/common/topic\" name=\"Topic\"\u003e, #\u003cType id=\"/music/musical_group\" name=\"Musical Group\"\u003e,\n         #\u003cType id=\"/broadcast/artist\" name=\"Broadcast Artist\"\u003e, #\u003cType id=\"/music/group_member\" name=\"Musical Group Member\"\u003e ]\n\u003c/code\u003e\n\u003c/pre\u003e\n\nWe can see that New Order is a member of Music Artist, Film Music Contributor, Broadcast Artist and other types.\n\nh3. Inspecting a Type's properties\n\nA type defines a set of properties to describe a Resource.\n\n\u003cpre\u003e\n\u003ccode\u003e\n  resource.types.each do |type|\n    type.properties # =\u003e e.g. [ #\u003cProperty id=\"/music/musical_group/member\"\u003e ]\n  end\n\u003c/code\u003e\n\u003c/pre\u003e\n\nWe get sets of Properties for each Type. The Type Musical Group has just one Property @/music/musical_group/member@\nnamed Members Of Musical Group.\n\nh3. Listing all Attributes\n\nAfter inspecting a Resource's Types and Properties we now know what we could know. But actually we don't know nothing :)\nSo it's time to ask for the values of properties, the so called _Attributes_.\n\n~Note: In Ken's terminology we differ between _Properties_ and concrete Property instances, the _Attributes_, while\nFreebase itself doesn't.~ \n\n\u003cpre\u003e\n\u003ccode\u003e\n  resource.attributes.each do |att|\n    att # =\u003e e.g. #\u003cAttribute property=\"/music/artist/album\"\u003e\n    att.property.name # =\u003e e.g. \"Albums\"\n    \n    att.values\n    # e.g. =\u003e [ #\u003cResource id=\"/guid/9202a8c04000641f8000000002fa2556\" name=\"Ceremony\"\u003e, \n                #\u003cResource id=\"/guid/9202a8c04000641f8000000002fa24d5\" name=\"Procession\"\u003e,\n                #\u003cResource id=\"/guid/9202a8c04000641f8000000002fa20d3\" name=\"Everything's Gone Green\"\u003e, ... ]\n    # e.g. =\u003e [\"1980\"]\n  end\n  \n  # alternatively you can access them directly\n  resource.attribute('/music/artist/album') # =\u003e #\u003cAttribute property=\"/music/artist/album\"\u003e\n\u003c/code\u003e\n\u003c/pre\u003e\n\nAttributes are slightly more complicated to handle compared to Types and Properties.\n\nThere are four kinds of Attributes.\n  * Unique Value Type\n  * Unique Object Type\n  * Non-unique Value Type\n  * Non-unique Object\n  \nIn order to be able to use unique and non-unique Attributes in the same manner we always wrap the value of an Attribute\nin a Collection, no matter if there's one value or there are many.\n\nh3. Group Attributes by their Type using Views\n\n\n\u003cpre\u003e\n\u003ccode\u003e\n  resource.views.each do |view|\n    view # =\u003e e.g. #\u003cView type=\"/music/artist\"\u003e\n    view.type # =\u003e e.g #\u003cType id=\"/music/artist\" name=\"Musical Artist\"\u003e\n    view.attributes\n    # =\u003e [#\u003cAttribute property=\"/music/artist/home_page\"\u003e, #\u003cAttribute property=\"/music/artist/genre\"\u003e,\n          #\u003cAttribute property=\"/music/artist/active_start\"\u003e, #\u003cAttribute property=\"/music/artist/similar_artist\"\u003e,\n          #\u003cAttribute property=\"/music/artist/album\"\u003e, #\u003cAttribute property=\"/music/artist/label\"\u003e,\n          #\u003cAttribute property=\"/music/artist/track\"\u003e, #\u003cAttribute property=\"/music/artist/origin\"\u003e]\n            \n    view.attributes.each do |att|\n      att.values\n      # e.g. =\u003e [ #\u003cResource id=\"/en/alternative_dance\" name=\"Alternative dance\"\u003e,\n                  #\u003cResource id=\"/en/synthpop\" name=\"Synthpop\"\u003e, \n                  #\u003cResource id=\"/en/house_music\" name=\"House music\"\u003e,\n                  #\u003cResource id=\"/en/post-punk\" name=\"Post-punk\"\u003e ]\n      # e.g. =\u003e [\"1980\"]\n    end\n  end\n\u003c/code\u003e\n\u003c/pre\u003e\n\nh3. Fetching multiple Resources using a query\n\nAs of now you can ask for multiple Resources by specifying a query.\n\n\u003cpre\u003e\n\u003ccode\u003e\n  resources = Ken.all(:name =\u003e \"Apple\", :type =\u003e \"/music/album\")\n  # =\u003e [#\u003cResource id=\"/guid/9202a8c04000641f80000000031dae7c\" name=\"Apple\"\u003e,\n        #\u003cResource id=\"/guid/9202a8c04000641f8000000007ce31ec\" name=\"Apple\"\u003e]\n\u003c/code\u003e\n\u003c/pre\u003e\n\nKeep in mind that only the top level of the query is mapped to a Collection of Resource Objects.\nSo asking for values in a nested level does not make sense. Use nested statements just for\nlowering the top level result.\n\nHowever you can instead navigate the normal way to figure out that values.\n_But won't that require another query to triggered? Certainly._\n\nLet's look at a nested query:\n\n\u003cpre\u003e\n\u003ccode\u003e\n  query = {\n    :directed_by =\u003e \"George Lucas\",\n    :starring =\u003e [\n      {\n        :actor =\u003e \"Harrison Ford\"\n      }\n    ],\n    :type =\u003e \"/film/film\"\n  }\n  \n  resources = Ken.all(query)\n  # =\u003e [#\u003cResource id=\"/en/star_wars_episode_iv_a_new_hope\" name=\"Star Wars Episode IV: A New Hope\"\u003e,\n        #\u003cResource id=\"/en/american_graffiti\" name=\"American Graffiti\"\u003e,\n        #\u003cResource id=\"/en/the_star_wars_holiday_special\" name=\"The Star Wars Holiday Special\"\u003e]\n\u003c/code\u003e\n\u003c/pre\u003e\n\nh3. Access properties attributes directly\n\nKen is primarily designed for inspecting resources in a generic way, what's ideal for domain independent browsing applications.\nHowever, there are legitimate situations where you already know what you want to access.\n\nThat's why I now added direct Property/Attribute access, but only on a Type/View level:\n\n\u003cpre\u003e\n\u003ccode\u003e\n  resource = Ken.get('/en/new_order')\n  type = resource.types[1] # =\u003e #\u003cType id=\"/music/artist\" name=\"Musical Artist\"\u003e\n  # because we know _/music/artist_ has a _genre_ property we can access that directly\n  type.genre # =\u003e #\u003cProperty id=\"/music/artist/genre\" expected_type=\"/music/genre\" unique=\"false\" object_type=\"true\"\u003e\n\u003c/code\u003e\n\u003c/pre\u003e\n\nThe same works for views:\n\n\u003cpre\u003e\n\u003ccode\u003e\n  resource = Ken.get('/en/new_order')\n  view = resource.views[1] # =\u003e #\u003cView type=\"/music/artist\"\u003e\n  # because we know _/music/artist_ has a _genre_ property we can access attribute directly as well\n  view.genre # =\u003e #\u003cAttribute property=\"/music/artist/genre\"\u003e\n\u003c/code\u003e\n\u003c/pre\u003e\n\nIf you rather want to query based on Types and access Properties/Attributes directly you can consider using\nChris \"Eppsteins Freebase Library\":http://github.com/chriseppstein/freebase/tree/master as an alternative. \n\n\nh3. Low Level API\n\nSometimes you may want to do specific queries instead of inspecting Resources as a whole.\nIn such a case you would want to use Ken's low level API.\n\n_mqlread_ works like the regular _mqlread service_, except that you are able to pass Ruby hashes instead of JSON.\nAnd you don't have to deal with HTTP, parameter encoding and parsing JSON.\n\n\u003cpre\u003e\n\u003ccode\u003e\n  artists = Ken.session.mqlread([{\n    :type =\u003e \"/music/artist\",\n    :id =\u003e nil, \n    :\"/common/topic/webpage\" =\u003e [{:uri =\u003e nil}], \n    :home_page =\u003e [{:uri =\u003e nil}], \n    :limit =\u003e 2\n  }])  \n  \n  # =\u003e [\n         {\"type\"=\u003e\"/music/artist\", \"home_page\"=\u003e[{\"uri\"=\u003e\"http://www.massiveattack.co.uk/\"}], \"id\"=\u003e\"/en/massive_attack\", \"/common/topic/webpage\"=\u003e[{\"uri\"=\u003e\"http://musicmoz.org/Bands_and_Artists/M/Massive_Attack/\"}, {\"uri\"=\u003e\"http://www.discogs.com/artist/Massive+Attack\"}, {\"uri\"=\u003e\"http://www.massiveattackarea.com/\"}, {\"uri\"=\u003e\"http://www.massiveattack.co.uk/\"}, {\"uri\"=\u003e\"http://www.massiveattack.com/\"}]},\n         {\"type\"=\u003e\"/music/artist\", \"home_page\"=\u003e[{\"uri\"=\u003e\"http://www.apartment26.com/\"}], \"id\"=\u003e\"/en/apartment_26\", \"/common/topic/webpage\"=\u003e[{\"uri\"=\u003e\"http://www.discogs.com/artist/Apartment+26\"}, {\"uri\"=\u003e\"http://musicmoz.org/Bands_and_Artists/A/Apartment_26/\"}, {\"uri\"=\u003e\"http://www.apartment26.com/\"}]}\n       ]\n\u003c/code\u003e\n\u003c/pre\u003e\n\n\nh3. Topic API\n\nPlease first have a look at the official \"Topic HTTP API documentation\":http://www.freebase.com/docs/topic_api . \n\nThe API provides general meta-data such as name, description, links and images for a given topic,\nas well as all properties directly related to that topic in the graph.\nThe API wraps a series of MQL queries that are needed to get this data, which otherwise must be performed separately.\nSo for gaining common interest information about a specific topic the Topic API is a way faster alternative to mqlread.\n\nThe latest update of Ken provides an easy way to access Freebase Topics using Ruby.\nAs usual Ken wraps the JSON result of the web service to convenient Ruby Objects.\n\nFor now Ken only returns simple properties. Support for so called mediator properties (aka 'CVT') will be added later.\nTo be honest, I just don't know how to wrap them appropriately using the existing Ken object model. Any API ideas are welcome, btw! ;)\nHowever, in the meanwhile you can access CVT's by using the plain JSON result returned by the low level Ken.session.topic method.\n\n\nThe API for Topics is quite the same as for Resources.\n\n\u003cpre\u003e\n\u003ccode\u003e\nt = Ken::Topic.get(\"/en/new_order\")\n  # =\u003e \u003cTopic id=\"/en/new_order\" name=\"New Order\"\u003e\n    \nt.types\n  # =\u003e [ #\u003cType id=\"/music/artist\" name=\"Musical Artist\"\u003e, #\u003cType id=\"/music/musical_group\" name=\"Musical Group\"\u003e, ... ]\n\nt.views\n  # =\u003e [ #\u003cView type=\"/music/artist\"\u003e, #\u003cView type=\"/music/musical_group\"\u003e, ... ]\n    \nt.properties\n  # =\u003e [ #\u003cProperty id=\"/music/artist/similar_artist\" expected_type=\"/music/artist\"\u003e, ... ]\n\nt.attributes\n  # =\u003e [ #\u003cAttribute property=\"/music/artist/similar_artist\"\u003e, #\u003cAttribute property=\"/music/artist/album\"\u003e, ... ]\n\n\u003c/code\u003e\n\u003c/pre\u003e\n\nAdditionally you can access some general meta-data, most importantly the topic's description which otherwise would need an additional request to the raw service.\n\n\u003cpre\u003e\n\u003ccode\u003e\n\nt.name # =\u003e \"New Order\"\nt.description # =\u003e \"New Order were an English musical group formed in 1980 by Bernard Sumner ... \"\nt.aliases # =\u003e [ \"NewOrder\", \"Englandneworder\" ]\nt.webpages # =\u003e [ {\"url\"=\u003e\"http://en.wikipedia.org/wiki/index.html?curid=22146\", \"text\"=\u003e\"Wikipedia\"}, ... ]\nt.url # =\u003e \"http://www.freebase.com/view/en/new_order\"\nt.thumbnail =\u003e \"http://api.freebase.com/api/trans/image_thumb/en/new_order\"\n\n\u003c/code\u003e\n\u003c/pre\u003e\n\n\nh2. Project Status\n\nh3. Features\n\n* Fetching of single Resources\n* Fetching of multiple Resources by specifying a query\n* Accessing Properties/Attributes directly (on a type/view level)\n* Type inspection\n* Attribute inspection\n* Low Level API (mqlread)\n* Rails and Merb support\n* Views on Resources to group Attributes based on the Resource's types\n* Accessing Topics using the new Freebase Topic API\n\nh3. Roadmap\n\n# More tests\n# Write-Support\n\nInitial thoughts, obviously not up-to-date and not conforming to the current version, are available at \"http://wiki.github.com/michael/ken\":http://wiki.github.com/michael/ken.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael%2Fken-rb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichael%2Fken-rb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael%2Fken-rb/lists"}