supplejack_client 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +16 -0
  5. data/Guardfile +24 -0
  6. data/LICENSE.txt +674 -0
  7. data/README.md +153 -0
  8. data/Rakefile +9 -0
  9. data/lib/generators/locales/en.yml +11 -0
  10. data/lib/generators/supplejack/install_generator.rb +28 -0
  11. data/lib/generators/templates/README +19 -0
  12. data/lib/generators/templates/supplejack_client.rb +120 -0
  13. data/lib/supplejack/config.rb +116 -0
  14. data/lib/supplejack/controllers/helpers.rb +172 -0
  15. data/lib/supplejack/engine.rb +20 -0
  16. data/lib/supplejack/exceptions.rb +17 -0
  17. data/lib/supplejack/facet.rb +33 -0
  18. data/lib/supplejack/item.rb +94 -0
  19. data/lib/supplejack/item_relation.rb +73 -0
  20. data/lib/supplejack/log_subscriber.rb +58 -0
  21. data/lib/supplejack/paginated_collection.rb +61 -0
  22. data/lib/supplejack/record.rb +147 -0
  23. data/lib/supplejack/request.rb +95 -0
  24. data/lib/supplejack/search.rb +346 -0
  25. data/lib/supplejack/url_formats/item_hash.rb +208 -0
  26. data/lib/supplejack/user.rb +132 -0
  27. data/lib/supplejack/user_set.rb +349 -0
  28. data/lib/supplejack/user_set_relation.rb +143 -0
  29. data/lib/supplejack/util.rb +120 -0
  30. data/lib/supplejack/version.rb +10 -0
  31. data/lib/supplejack_client.rb +29 -0
  32. data/spec/spec_helper.rb +23 -0
  33. data/spec/supplejack/controllers/helpers_spec.rb +277 -0
  34. data/spec/supplejack/facet_spec.rb +44 -0
  35. data/spec/supplejack/item_relation_spec.rb +111 -0
  36. data/spec/supplejack/item_spec.rb +115 -0
  37. data/spec/supplejack/log_subscriber_spec.rb +40 -0
  38. data/spec/supplejack/paginated_collection_spec.rb +43 -0
  39. data/spec/supplejack/record_spec.rb +255 -0
  40. data/spec/supplejack/request_spec.rb +195 -0
  41. data/spec/supplejack/search_spec.rb +727 -0
  42. data/spec/supplejack/url_formats/item_hash_spec.rb +341 -0
  43. data/spec/supplejack/user_set_relation_spec.rb +149 -0
  44. data/spec/supplejack/user_set_spec.rb +465 -0
  45. data/spec/supplejack/user_spec.rb +159 -0
  46. data/supplejack_client.gemspec +30 -0
  47. metadata +159 -0
@@ -0,0 +1,208 @@
1
+ # The Supplejack Client code is Crown copyright (C) 2014, New Zealand Government,
2
+ # and is licensed under the GNU General Public License, version 3.
3
+ # See https://github.com/DigitalNZ/supplejack_client for details.
4
+ #
5
+ # Supplejack was created by DigitalNZ at the National Library of NZ
6
+ # and the Department of Internal Affairs. http://digitalnz.org/supplejack
7
+
8
+ module Supplejack
9
+ module UrlFormats
10
+ class ItemHash
11
+
12
+ attr_accessor :params, :search, :i_unlocked, :i_locked, :h_unlocked, :h_locked
13
+
14
+ def initialize(params={}, search=nil)
15
+ @params = params || {}
16
+ @search = search
17
+ @i_unlocked = filters_of_type(:i)
18
+ @i_locked = filters_of_type(:il)
19
+ @h_unlocked = filters_of_type(:h)
20
+ @h_locked = filters_of_type(:hl)
21
+ end
22
+
23
+ def to_api_hash
24
+ hash = {}
25
+ text_value = text(params[:text])
26
+ hash[:text] = text_value if text_value
27
+ hash[:geo_bbox] = params[:geo_bbox] if params[:geo_bbox]
28
+ hash[:record_type] = params[:record_type] || 0
29
+ hash[:record_type] = hash[:record_type].to_i unless hash[:record_type]=="all"
30
+ hash[:page] = (params[:page] || 1).to_i
31
+ hash[:per_page] = (params[:per_page] || Supplejack.per_page).to_i
32
+ hash[:and] = and_filters if and_filters.try(:any?)
33
+ hash[:without] = without_filters if without_filters.try(:any?)
34
+ hash[:facets] = params[:facets] if params[:facets].present?
35
+ hash[:facets_per_page] = params[:facets_per_page].to_i if params[:facets_per_page].present?
36
+ hash[:fields] = params[:fields] || Supplejack.fields.join(',')
37
+ hash[:query_fields] = query_fields if query_fields
38
+ hash[:solr_query] = params[:solr_query] if params[:solr_query].present?
39
+
40
+ if params[:sort].present?
41
+ hash[:sort] = params[:sort]
42
+ hash[:direction] = params[:direction] || "asc"
43
+ end
44
+
45
+ hash
46
+ end
47
+
48
+ # Returns all the active filters for the current search
49
+ # These filters are used to scope the search results
50
+ #
51
+ def filters(filter_type=nil)
52
+ filters = {}
53
+
54
+ symbol = filter_symbol(filter_type)
55
+
56
+ memoized_filters = self.instance_variable_get("@#{symbol}_filters")
57
+ return memoized_filters if memoized_filters
58
+
59
+ unlocked = filters_of_type(symbol.to_sym)
60
+ locked = filters_of_type("#{symbol}l".to_sym)
61
+
62
+ filters = Supplejack::Util.deep_merge!(unlocked, locked)
63
+
64
+ @all_filters = filters.dup.symbolize_keys.to_hash rescue {}
65
+ self.instance_variable_set("@#{symbol}_filters", @all_filters)
66
+ @all_filters
67
+ end
68
+
69
+ def and_filters(filter_type=nil)
70
+ @and_filters ||= {}
71
+ @and_filters[filter_symbol(filter_type)] ||= filters(filter_type).reject {|filter, value| filter.to_s.match(/-(.+)/) or is_text_field?(filter)}
72
+ end
73
+
74
+ def is_text_field?(filter)
75
+ return false if filter.nil?
76
+ filter.to_s.split(//).last(5).join('').to_s == '_text'
77
+ end
78
+
79
+ def without_filters(filter_type=nil)
80
+ symbol = filter_symbol(filter_type)
81
+ @without_filters ||= {}
82
+ return @without_filters[symbol] if @without_filters[symbol]
83
+
84
+ @without_filters[symbol] = {}
85
+ filters(filter_type).each_pair do |filter, value|
86
+ if filter.to_s.match(/-(.+)/)
87
+ @without_filters[symbol][$1.to_sym] = value
88
+ end
89
+ end
90
+ @without_filters[symbol]
91
+ end
92
+
93
+ def all_filters
94
+ return @all_filters if @all_filters
95
+ self.filters
96
+ @all_filters
97
+ end
98
+
99
+ def filter_symbol(filter_type=nil)
100
+ if filter_type
101
+ filter_type == :items ? 'i' : 'h'
102
+ else
103
+ params[:record_type].to_i == 0 ? 'i' : 'h'
104
+ end
105
+ end
106
+
107
+ # Returns the value from the text param and joins any values from
108
+ # fields which end in _text (ie. creator_text)
109
+ #
110
+ # @param [ String ] default_text A string with the user query
111
+ #
112
+ def text(default_text=nil)
113
+ text_values = []
114
+ text_values << default_text if default_text.present?
115
+
116
+ all_filters.each do |filter, value|
117
+ text_values << value if is_text_field?(filter)
118
+ end
119
+
120
+ return nil if text_values.empty?
121
+ text_values.join(' ')
122
+ end
123
+
124
+ # Returns the query_fields from the current search filters so that
125
+ # specific fields can be searched.
126
+ # The '_text' is removed from the end of the field name
127
+ #
128
+ def query_fields
129
+ query_fields = []
130
+
131
+ all_filters.each do |filter, value|
132
+ if is_text_field?(filter)
133
+ query_fields << filter.to_s.chomp!('_text').to_sym
134
+ end
135
+ end
136
+
137
+ return nil if query_fields.empty?
138
+ query_fields
139
+ end
140
+
141
+ # Returns one type of filters
142
+ #
143
+ # @param [ :i, :il, :h, :hl ] filter_type The symbol of the filter type
144
+ #
145
+ def filters_of_type(filter_type)
146
+ params[filter_type].dup.symbolize_keys.to_hash rescue {}
147
+ end
148
+
149
+ # Returns a hash options to be used for generating URL's with all the search state.
150
+ #
151
+ # @param [ Hash ] filter_options A hash of options to be able to remove or add filters
152
+ #
153
+ # @filter_option option [ Array ] :except A array of filter names to be removed
154
+ # @filter_options option [ Hash ] :plus A hash with filters and their values to be added
155
+ #
156
+ def options(filter_options={})
157
+ filter_options.reverse_merge!({:except => [], :plus => {}})
158
+ filter_options[:except] ||= []
159
+
160
+ hash = {}
161
+ {:i => :i_unlocked, :il => :i_locked, :h => :h_unlocked, :hl => :h_locked}.each_pair do |symbol, instance_name|
162
+ filters = self.send(instance_name).clone || {}
163
+
164
+ filters.each_pair do |name, value|
165
+ filters.delete(name) if value.blank?
166
+ end
167
+
168
+ filter_options[:except].each do |exception|
169
+ if exception.is_a?(Hash)
170
+ facet, values_to_delete = exception.first
171
+ values_to_delete = Util.array(values_to_delete)
172
+ existing_values = Util.array(filters[facet])
173
+ new_values = existing_values - values_to_delete
174
+
175
+ if new_values.any?
176
+ new_values = new_values.first if new_values.size == 1
177
+ filters[facet] = new_values
178
+ else
179
+ filters.delete(facet)
180
+ end
181
+ else
182
+ filters.delete(exception)
183
+ end
184
+ end
185
+
186
+ if filter_options[:plus].try(:any?) && filter_options[:plus][symbol].try(:any?)
187
+ filters = Util.deep_merge(filters, filter_options[:plus][symbol])
188
+ end
189
+
190
+ hash[symbol] = filters.symbolize_keys if filters.any?
191
+ end
192
+
193
+ [:text, :direction, :sort].each do |attribute|
194
+ attribute_value = search.send(attribute)
195
+ hash.merge!(attribute => attribute_value) if attribute_value.present?
196
+ end
197
+
198
+ unless filter_options[:except].include?(:page)
199
+ hash.merge!(:page => search.page) if search.page.present? && search.page != 1
200
+ end
201
+
202
+ hash.merge!(:record_type => 1) if search.record_type > 0
203
+ return hash
204
+ end
205
+
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,132 @@
1
+ # The Supplejack Client code is Crown copyright (C) 2014, New Zealand Government,
2
+ # and is licensed under the GNU General Public License, version 3.
3
+ # See https://github.com/DigitalNZ/supplejack_client for details.
4
+ #
5
+ # Supplejack was created by DigitalNZ at the National Library of NZ
6
+ # and the Department of Internal Affairs. http://digitalnz.org/supplejack
7
+
8
+ module Supplejack
9
+
10
+ # The +User+ class represents a User on the Supplejack API
11
+ #
12
+ # A User instance can have a relationship to many UserSet objects, this
13
+ # relationship is managed through the UserSetRelation class which adds
14
+ # ActiveRecord like behaviour to the relationship.
15
+ #
16
+ # A User object can have the following values:
17
+ # - id
18
+ # - name
19
+ # - username
20
+ # - email
21
+ # - api_key
22
+ # - encrypted_password
23
+ #
24
+ class User
25
+ extend Supplejack::Request
26
+
27
+ attr_reader :id, :attributes, :api_key, :name, :username, :email, :encrypted_password, :sets_attributes
28
+ attr_accessor :use_own_api_key, :regenerate_api_key
29
+
30
+ def initialize(attributes={})
31
+ @attributes = attributes.try(:symbolize_keys) || {}
32
+ @api_key = @attributes[:api_key] || @attributes[:authentication_token]
33
+ @id = @attributes[:id]
34
+ @sets_attributes = @attributes[:sets]
35
+ @use_own_api_key = @attributes[:use_own_api_key] || false
36
+ @regenerate_api_key = @attributes[:regenerate_api_key] || false
37
+
38
+ [:name, :username, :email, :encrypted_password].each do |attr|
39
+ self.instance_variable_set("@#{attr}", @attributes[attr])
40
+ end
41
+ end
42
+
43
+ # Initializes a UserSetRelation class which adds behaviour to build, create
44
+ # find and order sets related to this particular User instance
45
+ #
46
+ # @return [ UserSetRelation ] A UserSetRelation object
47
+ #
48
+ # def sets
49
+ # @sets ||= UserSetRelation.new(self)
50
+ # end
51
+
52
+ # Executes a PUT request to the API with the user attributes
53
+ #
54
+ # @return [ true, false ] True if the API returned a success response, false if not.
55
+ #
56
+ def save
57
+ begin
58
+ updated_user = self.class.put("/users/#{self.api_key}", {}, self.api_attributes)
59
+ @api_key = updated_user['user']['api_key'] if regenerate_api_key?
60
+ return true
61
+ rescue StandardError => e
62
+ return false
63
+ end
64
+ end
65
+
66
+ # Execures a DELETE request to the API to remove the User object.
67
+ #
68
+ # @return [ true, false ] True if the API returned a success response, false if not.
69
+ #
70
+ def destroy
71
+ begin
72
+ id_or_api_key = self.id || self.api_key
73
+ self.class.delete("/users/#{id_or_api_key}")
74
+ return true
75
+ rescue StandardError => e
76
+ return false
77
+ end
78
+ end
79
+
80
+ # Returns a Hash of attributes which will be sent with the POST request.
81
+ #
82
+ # @return [ Hash ] A hash of field names and their values
83
+ #
84
+ def api_attributes
85
+ attrs = {}
86
+
87
+ [:name, :username, :email, :encrypted_password].each do |attr|
88
+ value = self.public_send(attr)
89
+ attrs[attr] = value if value.present?
90
+ end
91
+
92
+ attrs[:sets] = @sets_attributes if @sets_attributes.present?
93
+ attrs[:authentication_token] = nil if regenerate_api_key?
94
+ attrs
95
+ end
96
+
97
+ # Returns true/false depending whether it will use it's own API Key
98
+ # for managing sets
99
+ #
100
+ # @return [ true/false ] False by default, true when intentionally set at user initialization.
101
+ #
102
+ def use_own_api_key?
103
+ !!@use_own_api_key
104
+ end
105
+
106
+ # Returns true/false depending whether it will regenerate it's API Key
107
+ #
108
+ # @return [ true/false ] False by default, true when intentionally set.
109
+ #
110
+ def regenerate_api_key?
111
+ !!@regenerate_api_key
112
+ end
113
+
114
+ # Executes a GET request to the API to find the user with the provided ID.
115
+ #
116
+ # @return [ Supplejack::User ] A Supplejack::User object
117
+ #
118
+ def self.find(id)
119
+ response = get("/users/#{id}")
120
+ new(response["user"])
121
+ end
122
+
123
+ # Executes a POST request to the API with the user attributes to create a User object.
124
+ #
125
+ # @return [ Supplejack::User ] A Supplejack::User object with recently created id and api_key.
126
+ #
127
+ def self.create(attributes={})
128
+ response = post("/users", {}, {user: attributes})
129
+ new(response["user"])
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,349 @@
1
+ # The Supplejack Client code is Crown copyright (C) 2014, New Zealand Government,
2
+ # and is licensed under the GNU General Public License, version 3.
3
+ # See https://github.com/DigitalNZ/supplejack_client for details.
4
+ #
5
+ # Supplejack was created by DigitalNZ at the National Library of NZ
6
+ # and the Department of Internal Affairs. http://digitalnz.org/supplejack
7
+
8
+ module Supplejack
9
+
10
+ # The +UserSet+ class represents a UserSet on the Supplejack API
11
+ #
12
+ # A UserSet instance can have many Item objects, the relationship
13
+ # with the Item objects is managed through the ItemRelation class which adds
14
+ # ActiveRecord like behaviour to the relationship.
15
+ #
16
+ # A Item object can have the following values:
17
+ # - id
18
+ # - name
19
+ # - description
20
+ # - privacy
21
+ # - priority
22
+ # - count
23
+ # - tags
24
+ #
25
+ class UserSet
26
+ extend Supplejack::Request
27
+ include ActiveModel::Conversion
28
+ extend ActiveModel::Naming
29
+
30
+ ATTRIBUTES = [:id, :name, :description, :privacy, :url, :priority, :count, :tags, :tag_list, :homepage, :records, :created_at, :updated_at, :approved, :record]
31
+ attr_accessor *ATTRIBUTES
32
+ attr_accessor :api_key, :errors, :user
33
+
34
+ PRIVACY_STATES = ['public', 'hidden', 'private']
35
+
36
+ def initialize(attributes={})
37
+ @attributes = attributes.try(:symbolize_keys) || {}
38
+ @user = Supplejack::User.new(@attributes[:user])
39
+ self.attributes = @attributes
40
+ end
41
+
42
+ def attributes
43
+ attributes = {}
44
+ ATTRIBUTES.each do |attribute|
45
+ value = self.send(attribute)
46
+ attributes[attribute] = value if value.present?
47
+ end
48
+ attributes
49
+ end
50
+
51
+ # Return a Hash of attributes which is used to extract the relevant
52
+ # UserSet attributes when creating or updating a UserSet
53
+ #
54
+ # @return [ Hash ] A hash with field names and their values
55
+ #
56
+ def api_attributes
57
+ api_attributes = {}
58
+ [:name, :description, :privacy, :priority, :tag_list, :homepage, :approved].each do |attr|
59
+ api_attributes[attr] = self.send(attr)
60
+ end
61
+ api_attributes[:records] = self.api_records
62
+ api_attributes
63
+ end
64
+
65
+ # Return a array of hashes with the format: {record_id: 123, position: 1}
66
+ # Each hash represents a Supplejack::Item within the UserSet
67
+ #
68
+ # This array is used to send the UserSet items information to the API.
69
+ #
70
+ # @return [ Array ] An array of Hashes.
71
+ #
72
+ def api_records
73
+ records = self.records.is_a?(Array) ? self.records : []
74
+ records.map do |record_hash|
75
+ record_hash = record_hash.try(:symbolize_keys) || {}
76
+ if record_hash[:record_id]
77
+ {record_id: record_hash[:record_id], position: record_hash[:position] }
78
+ else
79
+ nil
80
+ end
81
+ end.compact
82
+ end
83
+
84
+ # Initializes a ItemRelation class which adds behaviour to build, create and
85
+ # find items related to this particular UserSet instance
86
+ #
87
+ # @return [ ItemRelation ] A ItemRelation object
88
+ #
89
+ def items
90
+ @items ||= ItemRelation.new(self)
91
+ end
92
+
93
+ # Returns the UserSet priority which defaults to 1
94
+ #
95
+ def priority
96
+ @priority || 1
97
+ end
98
+
99
+ # Returns the api_key from the UserSet or from the User which this set belongs to.
100
+ #
101
+ def api_key
102
+ @api_key || @user.try(:api_key)
103
+ end
104
+
105
+ # Returns a comma separated list of tags for this UserSet
106
+ #
107
+ def tag_list
108
+ return @tag_list if @tag_list
109
+ self.tags.join(', ') if self.tags
110
+ end
111
+
112
+ def favourite?
113
+ self.name == "Favourites"
114
+ end
115
+
116
+ def private?
117
+ self.privacy == "private"
118
+ end
119
+
120
+ def public?
121
+ self.privacy == "public"
122
+ end
123
+
124
+ def hidden?
125
+ self.privacy == "hidden"
126
+ end
127
+
128
+ # Convinience method to find out if a particular record_id is part of the UserSet
129
+ #
130
+ # @param [ Integer ] A record_id
131
+ #
132
+ # @return [ true, false ] True if the provided record_id is part of the UserSet, false otherwise.
133
+ #
134
+ def has_record?(record_id)
135
+ !!self.items.detect {|i| i.record_id == record_id.to_i }
136
+ end
137
+
138
+ # Returns the record id of the associated record in a safe manner
139
+ #
140
+ # @return [Intger, nil ] the record id if it exists, false otherwise
141
+ def set_record_id
142
+ self.record['record_id'] if self.record
143
+ end
144
+
145
+ # Executes a POST request when the UserSet hasn't been persisted to the API, otherwise it executes
146
+ # a PUT request.
147
+ #
148
+ # When the API returns a error response, the errors are available through the UserSet#errors
149
+ # virtual attribute.
150
+ #
151
+ # @return [ true, false ] True if the API response was successful, false if not.
152
+ #
153
+ def save
154
+ begin
155
+ if self.new_record?
156
+ response = self.class.post("/sets", {api_key: self.api_key}, {set: self.api_attributes})
157
+ self.id = response["set"]["id"]
158
+ else
159
+ self.class.put("/sets/#{self.id}", {api_key: self.api_key}, {set: self.api_attributes})
160
+ end
161
+ Rails.cache.delete("/users/#{self.api_key}/sets") if Supplejack.enable_caching
162
+ return true
163
+ rescue StandardError => e
164
+ self.errors = e.inspect
165
+ return false
166
+ end
167
+ end
168
+
169
+ # Updates the UserSet attributes and persists it to the API
170
+ #
171
+ # @return [ true, false ] True if the API response was successful, false if not.
172
+ #
173
+ def update_attributes(attributes={})
174
+ self.attributes = attributes
175
+ self.save
176
+ end
177
+
178
+ # Assigns the provided attributes to the UserSet object
179
+ #
180
+ def attributes=(attributes)
181
+ attributes = attributes.try(:symbolize_keys) || {}
182
+ attributes.each do |attr, value|
183
+ self.send("#{attr}=", value) if ATTRIBUTES.include?(attr)
184
+ end
185
+ self.records = ordered_records_from_array(attributes[:ordered_records]) if attributes[:ordered_records]
186
+ end
187
+
188
+ # Define setter methods for both created_at and updated_at so that
189
+ # they always return a Time object.
190
+ #
191
+ [:created_at, :updated_at].each do |attribute|
192
+ define_method("#{attribute}=") do |time|
193
+ self.instance_variable_set("@#{attribute}", Util.time(time))
194
+ end
195
+ end
196
+
197
+ # Takes an ordered Array of record_ids and converts it into a Array
198
+ # of Hashes which the API expects, inferring the position value from
199
+ # the position of the record_id in the Array.
200
+ #
201
+ # @param [ Array ] A array of record_ids
202
+ #
203
+ # @return [ Array ] A array of hashes in the format {record_id: 1, position: 1}
204
+ #
205
+ # @example
206
+ # user_set.ordered_records_from_array([89,66]) => [{record_id: 89, position: 1}, {record_id: 66, position: 2}]
207
+ #
208
+ def ordered_records_from_array(record_ids)
209
+ records = []
210
+ record_ids.each_with_index do |id, index|
211
+ records << {record_id: id, position: index+1}
212
+ end
213
+ records
214
+ end
215
+
216
+ # Returns if the UserSet is persisted to the API or not.
217
+ #
218
+ # @return [ true, false ] True if the UserSet is persisted to the API, false if not.
219
+ #
220
+ def new_record?
221
+ self.id.blank?
222
+ end
223
+
224
+ # Executes a DELETE request to the API with the UserSet ID and the user's api_key
225
+ #
226
+ # @return [ true, false ] True if the API response was successful, false if not.
227
+ #
228
+ def destroy
229
+ if self.new_record?
230
+ return false
231
+ else
232
+ begin
233
+ self.class.delete("/sets/#{self.id}", {api_key: self.api_key})
234
+ Rails.cache.delete("/users/#{self.api_key}/sets") if Supplejack.enable_caching
235
+ return true
236
+ rescue StandardError => e
237
+ self.errors = e.inspect
238
+ return false
239
+ end
240
+ end
241
+ end
242
+
243
+ def persisted?
244
+ !new_record?
245
+ end
246
+
247
+ # Fetches the UserSet information from the API again, in case it had changed.
248
+ # This can be useful if they items for a UserSet changed and you want the relation
249
+ # to have the most up to date items.
250
+ #
251
+ def reload
252
+ begin
253
+ self.instance_variable_set("@items", nil)
254
+ self.attributes = self.class.get("/sets/#{self.id}")["set"]
255
+ rescue RestClient::ResourceNotFound => e
256
+ raise Supplejack::SetNotFound, "UserSet with ID #{id} was not found"
257
+ end
258
+ end
259
+
260
+ # A UserSet is viewable by anyone if it's public or hidden
261
+ # When the UserSet is private it's only viewable by the owner.
262
+ #
263
+ # @param [ Supplejack::User ] A Supplejack::User object
264
+ #
265
+ # @return [ true, false ] True if the user can view the current UserSet, false if not.
266
+ #
267
+ def viewable_by?(user)
268
+ return true if self.public? || self.hidden?
269
+ self.owned_by?(user)
270
+ end
271
+
272
+ # Compares the api_key of the user and the api_key assigned to the UserSet
273
+ # to find out if the user passed is the owner of the set.
274
+ #
275
+ # @param [ Supplejack::User ] A Supplejack::User object
276
+ #
277
+ # @return [ true, false ] True if the user owns the current UserSet, false if not.
278
+ #
279
+ def owned_by?(user)
280
+ return false if user.try(:api_key).blank? || self.api_key.blank?
281
+ user.try(:api_key) == self.api_key
282
+ end
283
+
284
+ # Executes a GET request with the provided UserSet ID and initializes
285
+ # a UserSet object with the response from the API.
286
+ #
287
+ # @return [ UserSet ] A UserSet object
288
+ #
289
+ def self.find(id, api_key=nil)
290
+ begin
291
+ response = get("/sets/#{id}")
292
+ attributes = response["set"] || {}
293
+ user_set = new(attributes)
294
+ user_set.api_key = api_key if api_key.present?
295
+ user_set
296
+ rescue RestClient::ResourceNotFound => e
297
+ raise Supplejack::SetNotFound, "UserSet with ID #{id} was not found"
298
+ end
299
+ end
300
+
301
+ # Executes a GET request to the API /sets/public endpoint to retrieve
302
+ # all public UserSet objects.
303
+ #
304
+ # @param [ Hash ] options Supported options: :page, :per_page
305
+ #
306
+ # @option options [ Integer ] :page The page number used to paginate through the UserSet objects
307
+ # @option options [ Integer ] :per_page The per_page number to select the number of UserSet objects per page.
308
+ #
309
+ # @return [ Array ] A array of Supplejack::UserSet objects
310
+ #
311
+ def self.public_sets(options={})
312
+ options.reverse_merge!(page: 1, per_page: 100)
313
+ response = get("/sets/public", options)
314
+ sets_array = response["sets"] || []
315
+ user_sets = sets_array.map {|attrs| new(attrs) }
316
+ Supplejack::PaginatedCollection.new(user_sets, options[:page].to_i, options[:per_page].to_i, response["total"].to_i)
317
+ end
318
+
319
+ # Execute a GET request to the API /sets/home endpoint to retrieve
320
+ # all UserSet objects which have the :homepage flag set to true
321
+ #
322
+ # @return [ Array ] A array of Supplejack::UserSet objects
323
+ #
324
+ def self.homepage_sets
325
+ path = "/sets/home"
326
+ if Supplejack.enable_caching
327
+ response = Rails.cache.fetch(path, expires_in: 1.day) do
328
+ get(path)
329
+ end
330
+ else
331
+ response = get(path)
332
+ end
333
+ sets_array = response["sets"] || []
334
+ user_sets = sets_array.map {|attrs| new(attrs) }
335
+ end
336
+
337
+ # This method is normally provided by ActiveModel::Naming module, but here we have to override it
338
+ # so that in the Supplejack Website application it behaves as if the Supplejack::UserSet class was not under the
339
+ # Supplejack namespace.
340
+ #
341
+ # This is useful when using a Supplejack::UserSet object in the Rails provided routes helpers. Example:
342
+ #
343
+ # user_set_path(@user_set)
344
+ #
345
+ def self.model_name
346
+ ActiveModel::Name.new(self, nil, "UserSet")
347
+ end
348
+ end
349
+ end