Skip to content

Instantly share code, notes, and snippets.

@jmervine
Created March 16, 2012 20:30
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmervine/2052468 to your computer and use it in GitHub Desktop.
Save jmervine/2052468 to your computer and use it in GitHub Desktop.
Rails: Dynamic Model from JSON sans DB
require 'net/http'
class Item
#replaced with dynamic initialization below
#attr_reader :id, :user, :state
#
#
# Sample JSON
#
# [{ "id":1, "user":"john", "state":"active" },
# { "id":2, "user":"jane", "state":"inactive" },
# { "id":3, "user":"jack", "state":"active" },
# { "id":4, "user":"jeff", "state":"inactive" },
# { "id":5, "user":"jimm", "state":"active" }]
#
#
# Adding JSON class variable and setter to make this even more dynamic.
# note: I'm sure there's a better way to do this...
# e.g. with a configure block or something.
#
# Additionally, adding auto ssl stuff...
@@json_path = nil
@@use_ssl = false
def self.json_path=(path)
@@use_ssl = true if path =~ /^https/
@@json_path = path
end
# To use the above, add:
# Item.json_path = "<path>"
# to your config/environment.rb or
# config/environments/*.rb
#
# This will pre-load it in to your application.
#
def self.all
self.get_items_from_source.map { |i| new(i) }
end
def self.find( param )
all.detect { |i| i.id == param } || raise(ActiveRecord::RecordNotFound)
end
def self.where( query )
ret = []
all.each { |i| ret.push(i) if i.include?(query) } ||
raise(ActiveRecord::RecordNotFound)
return ret
end
def initialize item
raise "expected Hash param" unless item.kind_of? Hash
item.each do |key,value|
instance_variable_set("@#{key.to_s}".to_sym, value)
define_singleton_method(key.to_s) { instance_variable_get("@#{key.to_s}".to_sym) }
end
end
# replaced with dynamic initialization above
#def initialize hash
#@id = hash["id"]
#@user = hash["user"]
#@state = hash["state"]
#end
def include? query
raise InvalidParamType
unless query.respond_to?('has_key?') and query.respond_to?('has_value?')
query.each do |k,v|
return false unless self.instance_variable_get("@#{k.to_s}".to_sym) == v
end
end
protected
def self.get_items_from_source
raise MissingJsonPath if @@json_path.nil?
items = []
uri = URI.parse(@@json_path)
if @@use_ssl
require 'openssl'
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
else
response = Net::HTTP.get_response(uri)
end
JSON.parse(response.body).each { |i| items.push i }
items
end
# custom exceptions
class InvalidParamType < Exception
end
class MissingJsonPath < Exception
end
end
@jmervine
Copy link
Author

Rails requires JSON by default. This works perfectly without Rails, except you have to require 'json' before using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment