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, init_block, &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, init_block) ⇒ Resource
constructor
A new instance of Resource.
- #instance_variable_name ⇒ Object
- #many(name, init_block = nil, &block) ⇒ Object
- #member? ⇒ Boolean
- #one(name = nil, init_block = 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) ⇒ Object
- #sinatra_errors_to_hash(errors) ⇒ 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(method, sinatra, &block) ⇒ Object
- #sinatra_response(sinatra, method) ⇒ Object
- #sinatra_response_create_data(sinatra, response, method) ⇒ Object
- #sinatra_response_create_error(sinatra, response, method) ⇒ Object
- #sinatra_response_create_redirect(sinatra, response, method) ⇒ Object
- #sinatra_response_type(response) ⇒ Object
-
#sinatra_set_instance_variable(sinatra, name, value) ⇒ Object
————————–.
- #singleton(name, init_block = nil, &block) ⇒ Object
- #singleton? ⇒ Boolean
- #type ⇒ Object
Constructor Details
#initialize(sinatra, name, singleton, collection, parent, init_block) ⇒ Resource
Returns a new instance of Resource.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/nested.rb', line 42 def initialize(sinatra, name, singleton, collection, parent, init_block) 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(&(init_block||FETCH)) # puts "set @#{@__resource.instance_variable_name} to #{fetched.inspect} for #{self}" # self.instance_variable_set("@#{@__resource.instance_variable_name}", fetched) @__resource.sinatra_set_instance_variable(self, @__resource.instance_variable_name, fetched) end if member? serialize *@parent.instance_variable_get("@__serialize_args") end end |
Instance Attribute Details
#actions ⇒ Object (readonly)
Returns the value of attribute actions.
40 41 42 |
# File 'lib/nested.rb', line 40 def actions @actions end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
40 41 42 |
# File 'lib/nested.rb', line 40 def name @name end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
40 41 42 |
# File 'lib/nested.rb', line 40 def parent @parent end |
#resources ⇒ Object (readonly)
Returns the value of attribute resources.
40 41 42 |
# File 'lib/nested.rb', line 40 def resources @resources end |
Instance Method Details
#child_resource(name, singleton, collection, init_block, &block) ⇒ Object
168 169 170 171 172 |
# File 'lib/nested.rb', line 168 def child_resource(name, singleton, collection, init_block, &block) Resource.new(@sinatra, name, singleton, collection, self, init_block) .tap{|r| r.instance_eval(&block)} .tap{|r| @resources << r} end |
#collection? ⇒ Boolean
75 76 77 |
# File 'lib/nested.rb', line 75 def collection? @collection == true end |
#create_sinatra_route(method, action, &block) ⇒ Object
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/nested.rb', line 290 def create_sinatra_route(method, action, &block) @actions << {method: method, action: action, block: block} resource = self route = resource.route({}, action) puts "sinatra router [#{method}] #{@sinatra.nested_config[:prefix]}#{route}" @sinatra.send(method, route) do def self.error() errors.add(:base, ) end def self.errors @__errors ||= ActiveModel::Errors.new({}) end begin 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, method) rescue Exception => e context_arr = [] context_arr << "route: #{route}" context_arr << "method: #{method}" context_arr << "action: #{action}" context_arr << "resource: #{resource.name} (#{resource.type})" resource_object = instance_variable_get("@#{resource.instance_variable_name}") context_arr << "@#{resource.instance_variable_name}: #{resource_object.inspect}" puts context_arr.join("\n") raise e end end end |
#delete(action = nil, &block) ⇒ Object
150 151 152 |
# File 'lib/nested.rb', line 150 def delete(action=nil, &block) create_sinatra_route :delete, action, &block end |
#get(action = nil, &block) ⇒ Object
138 139 140 |
# File 'lib/nested.rb', line 138 def get(action=nil, &block) create_sinatra_route :get, action, &(block||proc {}) end |
#init(&block) ⇒ Object
108 109 110 |
# File 'lib/nested.rb', line 108 def init(&block) @__init = block end |
#instance_variable_name ⇒ Object
174 175 176 177 178 179 180 181 182 |
# File 'lib/nested.rb', line 174 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, init_block = nil, &block) ⇒ Object
158 159 160 161 |
# File 'lib/nested.rb', line 158 def many(name, init_block=nil, &block) raise ManyInManyError.new "do not nest many in many" if collection? child_resource(name, false, true, init_block, &block) end |
#member? ⇒ Boolean
71 72 73 |
# File 'lib/nested.rb', line 71 def member? !singleton? && !collection? end |
#one(name = nil, init_block = nil, &block) ⇒ Object
163 164 165 166 |
# File 'lib/nested.rb', line 163 def one(name=nil, init_block=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, init_block, &block) end |
#parents ⇒ Object
184 185 186 |
# File 'lib/nested.rb', line 184 def parents (@parent ? @parent.parents + [@parent] : []) end |
#post(action = nil, &block) ⇒ Object
142 143 144 |
# File 'lib/nested.rb', line 142 def post(action=nil, &block) create_sinatra_route :post, action, &block end |
#put(action = nil, &block) ⇒ Object
146 147 148 |
# File 'lib/nested.rb', line 146 def put(action=nil, &block) create_sinatra_route :put, action, &block end |
#route(args = {}, action = nil) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/nested.rb', line 112 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
188 189 190 |
# File 'lib/nested.rb', line 188 def self_and_parents (self.parents + [self]).reverse end |
#serialize(*args) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/nested.rb', line 91 def serialize(*args) @__serialize_args = args @__serialize = ->(obj) do args.inject({}) do |memo, field| case field when Symbol memo[field] = obj.is_a?(Hash) ? obj[field] : obj.send(field) when Hash field, proc = field.to_a.first memo[field] = self.instance_exec(obj, &proc) end memo end end end |
#sinatra_errors_to_hash(errors) ⇒ Object
278 279 280 281 282 283 |
# File 'lib/nested.rb', line 278 def sinatra_errors_to_hash(errors) errors.to_hash.inject({}) do |memo, e| memo[e[0]] = e[1][0] memo end end |
#sinatra_exec_delete_block(sinatra, &block) ⇒ Object
209 210 211 212 |
# File 'lib/nested.rb', line 209 def sinatra_exec_delete_block(sinatra, &block) sinatra_init_data(:delete, sinatra, &block) sinatra.instance_exec(*sinatra.instance_variable_get("@__data"), &block) end |
#sinatra_exec_get_block(sinatra, &block) ⇒ Object
204 205 206 207 |
# File 'lib/nested.rb', line 204 def sinatra_exec_get_block(sinatra, &block) sinatra_init_data(:get, sinatra, &block) sinatra.instance_exec(*sinatra.instance_variable_get("@__data"), &block) end |
#sinatra_exec_post_block(sinatra, &block) ⇒ Object
233 234 235 236 237 238 239 |
# File 'lib/nested.rb', line 233 def sinatra_exec_post_block(sinatra, &block) sinatra_init_data(:post, sinatra, &block) res = sinatra.instance_exec(*sinatra.instance_variable_get("@__data"), &block) sinatra.instance_variable_set("@#{self.instance_variable_name}", res) # TODO: do we need to check for existing variables here? # sinatra_set_instance_variable(sinatra, self.instance_variable_name, res) end |
#sinatra_exec_put_block(sinatra, &block) ⇒ Object
228 229 230 231 |
# File 'lib/nested.rb', line 228 def sinatra_exec_put_block(sinatra, &block) sinatra_init_data(:put, sinatra, &block) sinatra.instance_exec(*sinatra.instance_variable_get("@__data"), &block) end |
#sinatra_init(sinatra) ⇒ Object
199 200 201 202 |
# File 'lib/nested.rb', line 199 def sinatra_init(sinatra) sinatra.instance_variable_set("@__resource", self) sinatra.instance_exec(&@__init) end |
#sinatra_init_data(method, sinatra, &block) ⇒ Object
214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/nested.rb', line 214 def sinatra_init_data(method, sinatra, &block) raw_data = if [:put, :post].include?(method) sinatra.request.body.rewind HashWithIndifferentAccess.new(JSON.parse(sinatra.request.body.read)) elsif [:get, :delete].include?(method) sinatra.params else {} end 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, method) ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/nested.rb', line 245 def sinatra_response(sinatra, method) response = if sinatra.errors.empty? sinatra.instance_variable_get("@#{self.instance_variable_name}") else sinatra.errors end response = self.send(:"sinatra_response_create_#{sinatra_response_type(response)}", sinatra, response, method) case response when Nested::Redirect then sinatra.redirect(response.url) when String then response else response.to_json end end |
#sinatra_response_create_data(sinatra, response, method) ⇒ Object
268 269 270 271 272 273 274 275 276 |
# File 'lib/nested.rb', line 268 def sinatra_response_create_data(sinatra, response, method) data = if response && (collection? || response.is_a?(Array)) && method != :post 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, method) ⇒ Object
285 286 287 288 |
# File 'lib/nested.rb', line 285 def sinatra_response_create_error(sinatra, response, method) errors = response.is_a?(ActiveModel::Errors) ? response : response.errors {data: sinatra_errors_to_hash(errors), ok: false} end |
#sinatra_response_create_redirect(sinatra, response, method) ⇒ Object
264 265 266 |
# File 'lib/nested.rb', line 264 def sinatra_response_create_redirect(sinatra, response, method) response end |
#sinatra_response_type(response) ⇒ Object
241 242 243 |
# File 'lib/nested.rb', line 241 def sinatra_response_type(response) (response.is_a?(ActiveModel::Errors) || (response.respond_to?(:errors) && !response.errors.empty?)) ? :error : (response.is_a?(Nested::Redirect) ? :redirect : :data) end |
#sinatra_set_instance_variable(sinatra, name, value) ⇒ Object
194 195 196 197 |
# File 'lib/nested.rb', line 194 def sinatra_set_instance_variable(sinatra, name, value) raise "variable @#{name} already defined" if sinatra.instance_variable_defined?(:"@#{name}") sinatra.instance_variable_set(:"@#{name}", value) end |
#singleton(name, init_block = nil, &block) ⇒ Object
154 155 156 |
# File 'lib/nested.rb', line 154 def singleton(name, init_block=nil, &block) child_resource(name, true, false, init_block, &block) end |
#singleton? ⇒ Boolean
67 68 69 |
# File 'lib/nested.rb', line 67 def singleton? @singleton == true end |
#type ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/nested.rb', line 79 def type if singleton? :singleton elsif member? :member elsif collection? :collection else raise "undefined" end end |