Class: Nested::Resource
- Inherits:
-
Object
- Object
- Nested::Resource
- Defined in:
- lib/nested.rb
Constant Summary collapse
- FETCH =
-> do raise "implement fetch for resource #{@__resource.name}" unless @__resource.parent raise "implement fetch for singleton #{@__resource.name}" if @__resource.singleton? parent_resource = @__resource.parent parent_obj = instance_variable_get("@#{parent_resource.instance_variable_name}") if @__resource.name scope = parent_obj.send(@__resource.name.to_s.pluralize.to_sym) @__resource.collection? ? scope : scope.where(id: params["#{@__resource.name.to_s.singularize}_id"]).first else parent_obj.where(id: params["#{parent_resource.name.to_s.singularize}_id"]).first end end
Instance Attribute Summary collapse
-
#actions ⇒ Object
readonly
Returns the value of attribute actions.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#resources ⇒ Object
readonly
Returns the value of attribute resources.
Instance Method Summary collapse
- #child_resource(name, singleton, collection, &block) ⇒ Object
- #collection? ⇒ Boolean
- #create_sinatra_route(method, action, &block) ⇒ Object
- #delete(action = nil, &block) ⇒ Object
- #get(action = nil, &block) ⇒ Object
- #init(&block) ⇒ Object
-
#initialize(sinatra, name, singleton, collection, parent) ⇒ Resource
constructor
A new instance of Resource.
- #instance_variable_name ⇒ Object
- #many(name, &block) ⇒ Object
- #member? ⇒ Boolean
- #one(name = nil, &block) ⇒ Object
- #parents ⇒ Object
- #post(action = nil, &block) ⇒ Object
- #put(action = nil, &block) ⇒ Object
- #route(args = {}, action = nil) ⇒ Object
- #self_and_parents ⇒ Object
- #serialize(*args, &block) ⇒ Object
- #sinatra_exec_delete_block(sinatra, &block) ⇒ Object
- #sinatra_exec_get_block(sinatra, &block) ⇒ Object
- #sinatra_exec_post_block(sinatra, &block) ⇒ Object
- #sinatra_exec_put_block(sinatra, &block) ⇒ Object
-
#sinatra_init(sinatra) ⇒ Object
————————–.
- #sinatra_init_data(sinatra, &block) ⇒ Object
- #sinatra_response(sinatra) ⇒ Object
- #sinatra_response_create_data(sinatra, response) ⇒ Object
- #sinatra_response_create_error(sinatra, response) ⇒ Object
- #sinatra_response_type(response) ⇒ Object
- #singleton(name, &block) ⇒ Object
- #singleton? ⇒ Boolean
Constructor Details
#initialize(sinatra, name, singleton, collection, parent) ⇒ Resource
Returns a new instance of Resource.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/nested.rb', line 35 def initialize(sinatra, name, singleton, collection, parent) raise SingletonAndCollectionError.new if singleton && collection raise NameMissingError.new if (singleton || collection) && !name @sinatra = sinatra @name = name @singleton = singleton @collection = collection @parent = parent @resources = [] @actions = [] init &-> do fetched = instance_exec(&FETCH) puts "set @#{@__resource.instance_variable_name} to #{fetched.inspect} for #{self}" self.instance_variable_set("@#{@__resource.instance_variable_name}", fetched) end serialize &->(obj) do obj end end |
Instance Attribute Details
#actions ⇒ Object (readonly)
Returns the value of attribute actions.
33 34 35 |
# File 'lib/nested.rb', line 33 def actions @actions end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
33 34 35 |
# File 'lib/nested.rb', line 33 def name @name end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
33 34 35 |
# File 'lib/nested.rb', line 33 def parent @parent end |
#resources ⇒ Object (readonly)
Returns the value of attribute resources.
33 34 35 |
# File 'lib/nested.rb', line 33 def resources @resources end |
Instance Method Details
#child_resource(name, singleton, collection, &block) ⇒ Object
142 143 144 145 146 |
# File 'lib/nested.rb', line 142 def child_resource(name, singleton, collection, &block) Resource.new(@sinatra, name, singleton, collection, self) .tap{|r| r.instance_eval(&block)} .tap{|r| @resources << r} end |
#collection? ⇒ Boolean
67 68 69 |
# File 'lib/nested.rb', line 67 def collection? @collection == true end |
#create_sinatra_route(method, action, &block) ⇒ Object
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/nested.rb', line 235 def create_sinatra_route(method, action, &block) @actions << {method: method, action: action} resource = self route = resource.route({}, action) puts "sinatra router [#{method}] #{@sinatra.nested_config[:prefix]}#{route}" @sinatra.send(method, route) do content_type :json resource.self_and_parents.reverse.each do |res| res.sinatra_init(self) end resource.send(:"sinatra_exec_#{method}_block", self, &block) resource.sinatra_response(self) end end |
#delete(action = nil, &block) ⇒ Object
124 125 126 |
# File 'lib/nested.rb', line 124 def delete(action=nil, &block) create_sinatra_route :delete, action, &block end |
#get(action = nil, &block) ⇒ Object
112 113 114 |
# File 'lib/nested.rb', line 112 def get(action=nil, &block) create_sinatra_route :get, action, &(block||proc {}) end |
#init(&block) ⇒ Object
82 83 84 |
# File 'lib/nested.rb', line 82 def init(&block) @__init = block end |
#instance_variable_name ⇒ Object
148 149 150 151 152 153 154 155 156 |
# File 'lib/nested.rb', line 148 def instance_variable_name if @name @name.to_s.send(collection? ? :pluralize : :singularize).to_sym elsif member? && @parent @parent.name.to_s.singularize.to_sym else nil end end |
#many(name, &block) ⇒ Object
132 133 134 135 |
# File 'lib/nested.rb', line 132 def many(name, &block) raise ManyInManyError.new "do not nest many in many" if collection? child_resource(name, false, true, &block) end |
#member? ⇒ Boolean
63 64 65 |
# File 'lib/nested.rb', line 63 def member? !singleton? && !collection? end |
#one(name = nil, &block) ⇒ Object
137 138 139 140 |
# File 'lib/nested.rb', line 137 def one(name=nil, &block) raise OneWithNameInManyError.new("call one (#{name}) without name argument when nested in a many (#{@name})") if name && collection? child_resource(name, false, false, &block) end |
#parents ⇒ Object
158 159 160 |
# File 'lib/nested.rb', line 158 def parents (@parent ? @parent.parents + [@parent] : []) end |
#post(action = nil, &block) ⇒ Object
116 117 118 |
# File 'lib/nested.rb', line 116 def post(action=nil, &block) create_sinatra_route :post, action, &block end |
#put(action = nil, &block) ⇒ Object
120 121 122 |
# File 'lib/nested.rb', line 120 def put(action=nil, &block) create_sinatra_route :put, action, &block end |
#route(args = {}, action = nil) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/nested.rb', line 86 def route(args={}, action=nil) "".tap do |r| r << @parent.route(args) if @parent if singleton? r << "/" + @name.to_s.singularize elsif collection? r << "/" + @name.to_s.pluralize else if @name r << "/" + @name.to_s.pluralize end r << "/" key = ((@name || @parent.name).to_s.singularize + "_id").to_sym if args.key?(key) r << args[key].to_s else r << ":#{key}" end end r << "/#{action}" if action end end |
#self_and_parents ⇒ Object
162 163 164 |
# File 'lib/nested.rb', line 162 def self_and_parents (self.parents + [self]).reverse end |
#serialize(*args, &block) ⇒ Object
71 72 73 74 75 76 77 78 79 80 |
# File 'lib/nested.rb', line 71 def serialize(*args, &block) raise "pass either *args or &block" if args.empty? && !block @__serialize = ->(obj) do obj = self.instance_exec(obj, &block) if block obj = obj.attributes if obj.is_a?(ActiveRecord::Base) obj = obj.symbolize_keys.slice(*args) unless args.empty? obj end end |
#sinatra_exec_delete_block(sinatra, &block) ⇒ Object
177 178 179 |
# File 'lib/nested.rb', line 177 def sinatra_exec_delete_block(sinatra, &block) sinatra.instance_exec(&block) end |
#sinatra_exec_get_block(sinatra, &block) ⇒ Object
173 174 175 |
# File 'lib/nested.rb', line 173 def sinatra_exec_get_block(sinatra, &block) sinatra.instance_exec(&block) end |
#sinatra_exec_post_block(sinatra, &block) ⇒ Object
194 195 196 197 198 |
# File 'lib/nested.rb', line 194 def sinatra_exec_post_block(sinatra, &block) sinatra_init_data(sinatra, &block) res = sinatra.instance_exec(*sinatra.instance_variable_get("@__data"), &block) sinatra.instance_variable_set("@#{self.instance_variable_name}", res) end |
#sinatra_exec_put_block(sinatra, &block) ⇒ Object
189 190 191 192 |
# File 'lib/nested.rb', line 189 def sinatra_exec_put_block(sinatra, &block) sinatra_init_data(sinatra, &block) sinatra.instance_exec(*sinatra.instance_variable_get("@__data"), &block) end |
#sinatra_init(sinatra) ⇒ Object
168 169 170 171 |
# File 'lib/nested.rb', line 168 def sinatra_init(sinatra) sinatra.instance_variable_set("@__resource", self) sinatra.instance_exec(&@__init) end |
#sinatra_init_data(sinatra, &block) ⇒ Object
181 182 183 184 185 186 187 |
# File 'lib/nested.rb', line 181 def sinatra_init_data(sinatra, &block) sinatra.request.body.rewind raw_data = HashWithIndifferentAccess.new(JSON.parse(sinatra.request.body.read)) sinatra.instance_variable_set("@__raw_data", raw_data) sinatra.instance_variable_set("@__data", raw_data.values_at(*block.parameters.map(&:last))) end |
#sinatra_response(sinatra) ⇒ Object
204 205 206 207 208 209 210 211 212 |
# File 'lib/nested.rb', line 204 def sinatra_response(sinatra) response = sinatra.instance_variable_get("@#{self.instance_variable_name}") response = self.send(:"sinatra_response_create_#{sinatra_response_type(response)}", sinatra, response) case response when String then response else response.to_json end end |
#sinatra_response_create_data(sinatra, response) ⇒ Object
214 215 216 217 218 219 220 221 222 |
# File 'lib/nested.rb', line 214 def sinatra_response_create_data(sinatra, response) data = if response && collection? response.to_a.map{|e| sinatra.instance_exec(e, &@__serialize) } else sinatra.instance_exec(response, &@__serialize) end {data: data, ok: true} end |
#sinatra_response_create_error(sinatra, response) ⇒ Object
224 225 226 227 228 229 230 231 232 233 |
# File 'lib/nested.rb', line 224 def sinatra_response_create_error(sinatra, response) errors = response.is_a?(ActiveModel::Errors) ? response : response.errors data = errors.to_hash.inject({}) do |memo, e| memo[e[0]] = e[1][0] memo end {data: data, ok: false} end |
#sinatra_response_type(response) ⇒ Object
200 201 202 |
# File 'lib/nested.rb', line 200 def sinatra_response_type(response) (response.is_a?(ActiveModel::Errors) || (response.respond_to?(:errors) && !response.errors.empty?)) ? :error : :data end |
#singleton(name, &block) ⇒ Object
128 129 130 |
# File 'lib/nested.rb', line 128 def singleton(name, &block) child_resource(name, true, false, &block) end |
#singleton? ⇒ Boolean
59 60 61 |
# File 'lib/nested.rb', line 59 def singleton? @singleton == true end |