supplejack_client 1.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +27 -0
- data/.rspec +2 -0
- data/Gemfile +16 -0
- data/Guardfile +24 -0
- data/LICENSE.txt +674 -0
- data/README.md +153 -0
- data/Rakefile +9 -0
- data/lib/generators/locales/en.yml +11 -0
- data/lib/generators/supplejack/install_generator.rb +28 -0
- data/lib/generators/templates/README +19 -0
- data/lib/generators/templates/supplejack_client.rb +120 -0
- data/lib/supplejack/config.rb +116 -0
- data/lib/supplejack/controllers/helpers.rb +172 -0
- data/lib/supplejack/engine.rb +20 -0
- data/lib/supplejack/exceptions.rb +17 -0
- data/lib/supplejack/facet.rb +33 -0
- data/lib/supplejack/item.rb +94 -0
- data/lib/supplejack/item_relation.rb +73 -0
- data/lib/supplejack/log_subscriber.rb +58 -0
- data/lib/supplejack/paginated_collection.rb +61 -0
- data/lib/supplejack/record.rb +147 -0
- data/lib/supplejack/request.rb +95 -0
- data/lib/supplejack/search.rb +346 -0
- data/lib/supplejack/url_formats/item_hash.rb +208 -0
- data/lib/supplejack/user.rb +132 -0
- data/lib/supplejack/user_set.rb +349 -0
- data/lib/supplejack/user_set_relation.rb +143 -0
- data/lib/supplejack/util.rb +120 -0
- data/lib/supplejack/version.rb +10 -0
- data/lib/supplejack_client.rb +29 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/supplejack/controllers/helpers_spec.rb +277 -0
- data/spec/supplejack/facet_spec.rb +44 -0
- data/spec/supplejack/item_relation_spec.rb +111 -0
- data/spec/supplejack/item_spec.rb +115 -0
- data/spec/supplejack/log_subscriber_spec.rb +40 -0
- data/spec/supplejack/paginated_collection_spec.rb +43 -0
- data/spec/supplejack/record_spec.rb +255 -0
- data/spec/supplejack/request_spec.rb +195 -0
- data/spec/supplejack/search_spec.rb +727 -0
- data/spec/supplejack/url_formats/item_hash_spec.rb +341 -0
- data/spec/supplejack/user_set_relation_spec.rb +149 -0
- data/spec/supplejack/user_set_spec.rb +465 -0
- data/spec/supplejack/user_spec.rb +159 -0
- data/supplejack_client.gemspec +30 -0
- 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
|