flickr-objects 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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