flickr-objects 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +49 -63
  3. data/lib/flickr/api/abstract/params_processor.rb +68 -0
  4. data/lib/flickr/api/abstract.rb +113 -0
  5. data/lib/flickr/api/general.rb +75 -0
  6. data/lib/flickr/api/person.rb +91 -39
  7. data/lib/flickr/api/photo.rb +213 -108
  8. data/lib/flickr/api/set.rb +114 -55
  9. data/lib/flickr/api/upload_ticket.rb +17 -6
  10. data/lib/flickr/api.rb +90 -35
  11. data/lib/flickr/attributes.rb +200 -0
  12. data/lib/flickr/base_converter.rb +29 -0
  13. data/lib/flickr/client/data.rb +47 -0
  14. data/lib/flickr/client/oauth.rb +44 -0
  15. data/lib/flickr/client/upload.rb +55 -0
  16. data/lib/flickr/client.rb +77 -33
  17. data/lib/flickr/configuration.rb +85 -14
  18. data/lib/flickr/error.rb +58 -0
  19. data/lib/flickr/middleware.rb +52 -28
  20. data/lib/flickr/oauth.rb +89 -74
  21. data/lib/flickr/object/attribute_locations/list.rb +25 -0
  22. data/lib/flickr/object/attribute_locations/location.rb +29 -0
  23. data/lib/flickr/object/attribute_locations/permissions.rb +31 -0
  24. data/lib/flickr/object/attribute_locations/person/upload_status.rb +32 -0
  25. data/lib/flickr/object/attribute_locations/person.rb +78 -0
  26. data/lib/flickr/object/attribute_locations/photo/exif.rb +29 -0
  27. data/lib/flickr/object/attribute_locations/photo/note.rb +36 -0
  28. data/lib/flickr/object/attribute_locations/photo/tag.rb +23 -0
  29. data/lib/flickr/object/attribute_locations/photo.rb +164 -0
  30. data/lib/flickr/object/attribute_locations/set.rb +53 -0
  31. data/lib/flickr/object/attribute_locations/upload_ticket.rb +30 -0
  32. data/lib/flickr/object/attribute_locations/visibility.rb +24 -0
  33. data/lib/flickr/object/list/kaminari.rb +30 -0
  34. data/lib/flickr/object/list/normal.rb +27 -0
  35. data/lib/flickr/object/list/will_paginate.rb +31 -0
  36. data/lib/flickr/object/list.rb +87 -0
  37. data/lib/flickr/object/location.rb +35 -0
  38. data/lib/flickr/object/permissions.rb +18 -0
  39. data/lib/flickr/object/person/upload_status.rb +22 -0
  40. data/lib/flickr/object/person.rb +93 -0
  41. data/lib/flickr/object/photo/exif.rb +35 -0
  42. data/lib/flickr/object/photo/note.rb +20 -0
  43. data/lib/flickr/object/photo/size.rb +67 -0
  44. data/lib/flickr/object/photo/tag.rb +23 -0
  45. data/lib/flickr/object/photo.rb +349 -0
  46. data/lib/flickr/object/set.rb +114 -0
  47. data/lib/flickr/object/upload_ticket.rb +31 -0
  48. data/lib/flickr/object/visibility.rb +16 -0
  49. data/lib/flickr/object.rb +118 -27
  50. data/lib/flickr/sanitized_file.rb +70 -0
  51. data/lib/flickr/version.rb +4 -2
  52. data/lib/flickr.rb +69 -15
  53. metadata +89 -103
  54. data/lib/flickr/api/api_methods/flickr.rb +0 -5
  55. data/lib/flickr/api/api_methods/person.rb +0 -14
  56. data/lib/flickr/api/api_methods/photo.rb +0 -26
  57. data/lib/flickr/api/api_methods/set.rb +0 -18
  58. data/lib/flickr/api/api_methods/upload_ticket.rb +0 -5
  59. data/lib/flickr/api/flickr.rb +0 -35
  60. data/lib/flickr/api_caller.rb +0 -98
  61. data/lib/flickr/client/methods_client.rb +0 -22
  62. data/lib/flickr/client/upload_client.rb +0 -62
  63. data/lib/flickr/errors.rb +0 -19
  64. data/lib/flickr/helpers/base_58.rb +0 -15
  65. data/lib/flickr/helpers/boolean.rb +0 -4
  66. data/lib/flickr/helpers/core_ext.rb +0 -5
  67. data/lib/flickr/object/attribute/converter.rb +0 -49
  68. data/lib/flickr/object/attribute/finder.rb +0 -32
  69. data/lib/flickr/object/attribute.rb +0 -45
  70. data/lib/flickr/objects/attribute_values/list.rb +0 -10
  71. data/lib/flickr/objects/attribute_values/location.rb +0 -14
  72. data/lib/flickr/objects/attribute_values/note.rb +0 -11
  73. data/lib/flickr/objects/attribute_values/permissions.rb +0 -12
  74. data/lib/flickr/objects/attribute_values/person/upload_status.rb +0 -16
  75. data/lib/flickr/objects/attribute_values/person.rb +0 -24
  76. data/lib/flickr/objects/attribute_values/photo.rb +0 -84
  77. data/lib/flickr/objects/attribute_values/set.rb +0 -17
  78. data/lib/flickr/objects/attribute_values/tag.rb +0 -9
  79. data/lib/flickr/objects/attribute_values/upload_ticket.rb +0 -9
  80. data/lib/flickr/objects/attribute_values/visibility.rb +0 -10
  81. data/lib/flickr/objects/list.rb +0 -86
  82. data/lib/flickr/objects/location.rb +0 -26
  83. data/lib/flickr/objects/note.rb +0 -14
  84. data/lib/flickr/objects/permissions.rb +0 -14
  85. data/lib/flickr/objects/person/upload_status.rb +0 -14
  86. data/lib/flickr/objects/person.rb +0 -43
  87. data/lib/flickr/objects/photo.rb +0 -113
  88. data/lib/flickr/objects/set.rb +0 -29
  89. data/lib/flickr/objects/tag.rb +0 -17
  90. data/lib/flickr/objects/upload_ticket.rb +0 -18
  91. data/lib/flickr/objects/visibility.rb +0 -12
  92. data/lib/flickr/objects.rb +0 -25
data/lib/flickr/object.rb CHANGED
@@ -1,49 +1,140 @@
1
- require "flickr/object/attribute"
2
- require "flickr/api_caller"
1
+ require "flickr/attributes"
3
2
 
4
- class Flickr
3
+ module Flickr
4
+
5
+ ##
6
+ # Every Flickr object inherits from this class. It provides interface for defining
7
+ # attributes and some helper methods.
8
+ #
5
9
  class Object
6
- def self.children
7
- @children ||= []
10
+
11
+ extend Flickr::Attributes
12
+ extend Flickr::AutoloadHelper
13
+
14
+ autoload_names \
15
+ :List, :Photo, :Person, :Set, :UploadTicket, :Permissions, :Location,
16
+ :Visibility
17
+
18
+ ##
19
+ # @private
20
+ #
21
+ def self.api_class
22
+ Flickr::Api.const_get(name.match(/^Flickr::Object::/).post_match)
23
+ end
24
+
25
+ ##
26
+ # Overriding Flickr::Attributes#attribute to add a default location.
27
+ # This means that `:<attribute>` will always first be searched in
28
+ # `@attributes["<attribute>"]`.
29
+ #
30
+ # @!macro [attach] attribute
31
+ # @attribute [r] $1
32
+ # @return [$2]
33
+ #
34
+ # @private
35
+ #
36
+ def self.attribute(name, type)
37
+ new_attribute = super
38
+ new_attribute.add_locations([-> { @attributes[name.to_s] }])
8
39
  end
9
40
 
10
- def self.inherited(child)
11
- child.send(:extend, Attribute)
12
- child.send(:include, ApiCaller)
41
+ ##
42
+ # @private
43
+ #
44
+ def initialize(attributes, access_token = [])
45
+ raise ArgumentError, "attributes should not be nil" if attributes.nil?
13
46
 
14
- Object.children << child
47
+ @attributes = attributes
48
+ @access_token = access_token
15
49
  end
16
50
 
17
- def self.find(id)
18
- new({"id" => id}, client)
51
+ ##
52
+ # @private
53
+ #
54
+ attr_reader :access_token
55
+ ##
56
+ # The raw hash of attributes returned from Flickr.
57
+ #
58
+ # @return [Hash]
59
+ # @see #[]
60
+ #
61
+ attr_reader :attributes
62
+
63
+ ##
64
+ # Shorthand for accessing the raw hash of attributes returned
65
+ # from Flickr.
66
+ #
67
+ # @see #attributes
68
+ #
69
+ def [](key)
70
+ @attributes[key]
19
71
  end
20
72
 
21
- def self.new_list(hashes, client, list_hash)
22
- List.new(hashes.map { |hash| new(hash, client) }, list_hash)
73
+ ##
74
+ # Compares by ID (if that object has an ID), otherwise compares by attributes.
75
+ #
76
+ def ==(other)
77
+ if not other.is_a?(Flickr::Object)
78
+ raise ArgumentError "can't compare Flickr::Object with #{other.class}"
79
+ end
80
+
81
+ if [self, other].all? { |object| object.respond_to?(:id) && object.id }
82
+ self.id == other.id
83
+ else
84
+ self.attributes == other.attributes
85
+ end
23
86
  end
87
+ alias eql? ==
24
88
 
89
+ ##
90
+ # Displays all the attributes and their values.
91
+ #
25
92
  def inspect
26
- attribute_values = {}
27
- self.class.attributes.each do |name|
28
- attribute_values[name] = send(name) unless send(name).nil?
29
- end
93
+ attribute_values = self.class.attributes
94
+ .inject({}) { |hash, attribute| hash.update(attribute.name => send(attribute.name)) }
95
+ .reject { |name, value| value.nil? or (value.respond_to?(:empty?) and value.empty?) }
96
+ attributes = attribute_values
97
+ .map { |name, value| "#{name}=#{value.inspect}" }
98
+ .join(" ")
99
+
30
100
  class_name = self.class.name
31
- "#<#{class_name}: #{attribute_values.map { |k, v| "#{k}=#{v.inspect}" }.join(" ")}>"
101
+ hex_code = "0x#{(object_id >> 1).to_s(16)}"
102
+
103
+ "#<#{class_name}:#{hex_code} #{attributes}>"
32
104
  end
33
105
 
34
- def ==(other)
35
- if (self.respond_to?(:id) && self.id) && (other.respond_to?(:id) && other.id)
36
- id == other.id
37
- else
38
- super
106
+ ##
107
+ # Tests if the object matches a hash of attributes. Supports nesting
108
+ # (see the example).
109
+ #
110
+ # @param attributes [Hash]
111
+ # @return [Boolean]
112
+ # @example
113
+ # photo.matches?(owner: {username: "janko"})
114
+ #
115
+ def matches?(attributes)
116
+ attributes.all? do |name, value|
117
+ if send(name).is_a?(Flickr::Object) and value.is_a?(Hash)
118
+ send(name).matches?(value)
119
+ else
120
+ send(name) == value
121
+ end
39
122
  end
40
123
  end
41
124
 
42
- protected
125
+ ##
126
+ # @private
127
+ #
128
+ def update(attributes)
129
+ @attributes.update(attributes)
130
+ self
131
+ end
43
132
 
44
- def initialize(hash, client)
45
- @hash = hash || {}
46
- @client = client
133
+ private
134
+
135
+ def api
136
+ self.class.api_class.new(@access_token)
47
137
  end
48
138
  end
139
+
49
140
  end
@@ -0,0 +1,70 @@
1
+ require "delegate"
2
+
3
+ module Flickr
4
+
5
+ ##
6
+ # File that users provide for uploading can come from various sources (Rails, Sinatra
7
+ # etc). This class attempts to sanitize it, pulling out the path, content type,
8
+ # and the actual file.
9
+ #
10
+ # @private
11
+ #
12
+ class SanitizedFile < SimpleDelegator
13
+
14
+ attr_reader :file, :content_type, :path
15
+
16
+ ##
17
+ # @param original [String, File, Rails, Sinatra]
18
+ #
19
+ def initialize(original)
20
+ @original = original
21
+ sanitize!
22
+ super(@file)
23
+ end
24
+
25
+ private
26
+
27
+ ##
28
+ # Extracts the tempfile, content type and path.
29
+ #
30
+ def sanitize!
31
+ if rails_file?
32
+ @file = @original
33
+ @content_type = @original.content_type
34
+ @path = @original.tempfile
35
+ elsif sinatra_file?
36
+ @file = @original[:tempfile]
37
+ @content_type = @original[:type]
38
+ @path = @original[:tempfile].path
39
+ elsif file?
40
+ @file = @original
41
+ @content_type = @original.content_type if @original.respond_to?(:content_type)
42
+ @path = @original.path
43
+ elsif string?
44
+ @file = File.open(@original)
45
+ @content_type = nil
46
+ @path = @original
47
+ else
48
+ raise ArgumentError, "invalid file format"
49
+ end
50
+ end
51
+
52
+ def rails_file?
53
+ defined?(Rails) and @original.is_a?(ActionDispatch::Http::UploadedFile)
54
+ end
55
+
56
+ def sinatra_file?
57
+ defined?(Sinatra) and @original.is_a?(Hash)
58
+ end
59
+
60
+ def file?
61
+ @original.respond_to?(:read) and @original.respond_to?(:path)
62
+ end
63
+
64
+ def string?
65
+ @original.is_a?(String)
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -1,3 +1,5 @@
1
- class Flickr
2
- VERSION = "0.2.0"
1
+ module Flickr
2
+
3
+ VERSION = "0.3.0"
4
+
3
5
  end
data/lib/flickr.rb CHANGED
@@ -1,26 +1,80 @@
1
- require "flickr/helpers/core_ext"
2
- require "flickr/configuration"
1
+ module Flickr
3
2
 
4
- class Flickr
5
- def self.configuration
6
- @configuration ||= Configuration.new
3
+ ##
4
+ # @private
5
+ #
6
+ module AutoloadHelper
7
+ def autoload_dir(directory, mappings)
8
+ mappings.each do |const_name, path|
9
+ autoload const_name, File.join(directory, path)
10
+ end
11
+ end
12
+
13
+ ##
14
+ # Flickr::Object and Flickr::Api contain too many constants, so rather than
15
+ # providing an explicit filename we rather use the underscored constant name.
16
+ #
17
+ def autoload_names(*class_names)
18
+ mappings = class_names.inject({}) do |mappings, class_name|
19
+ mappings.update(class_name => Flickr.underscore(class_name.to_s))
20
+ end
21
+ directory = Flickr.underscore(name)
22
+
23
+ autoload_dir directory, mappings
24
+ end
7
25
  end
8
26
 
9
- def self.configure
10
- yield configuration if block_given?
11
- @client = @upload_client = nil
12
- configuration
27
+ extend AutoloadHelper
28
+
29
+ autoload_dir "flickr",
30
+ :Configuration => "configuration",
31
+ :Api => "api",
32
+ :OAuth => "oauth",
33
+ :Object => "object",
34
+ :Client => "client"
35
+
36
+ ##
37
+ # ActiveSupport's `underscore` (simpler version), used in
38
+ # Flickr::AutoloadHelper#autoload_names
39
+ #
40
+ # @example
41
+ # Flickr.underscore("Foo::Bar::Baz") # => "foo/bar/baz"
42
+ # @private
43
+ #
44
+ def self.underscore(class_name)
45
+ class_name
46
+ .split("::")
47
+ .map { |s| s.split(/(?=[A-Z])/).map(&:downcase).join("_") }
48
+ .join("/")
13
49
  end
14
50
 
15
- def self.api_methods
16
- @api_methods ||= Hash.new { |hash, key| hash[key] = [] }
51
+ extend Flickr::Configuration
52
+
53
+ ##
54
+ # If you're obtaining the access token dynamically, then you can't set it in
55
+ # the global configuration. This method allows you to create a temporary
56
+ # instance with the access token.
57
+ #
58
+ # @example
59
+ # flickr = Flickr.new("KEY", "SECRET")
60
+ # flickr.photos.get_recent
61
+ # # ...
62
+ # @return [Flickr]
63
+ #
64
+ def self.new(access_token_key, access_token_secret)
65
+ dup.configure do |config|
66
+ config.access_token_key = access_token_key
67
+ config.access_token_secret = access_token_secret
68
+ end
17
69
  end
18
70
 
71
+ extend Flickr::Api
72
+
73
+ ##
74
+ # @private
75
+ #
19
76
  def self.deprecation_warn(message)
20
77
  warn "[FLICKR OBJECTS] #{message}"
21
78
  end
22
- end
23
79
 
24
- require "flickr/objects"
25
- require "flickr/api"
26
- require "flickr/oauth"
80
+ end