Class: SocialLinker::Subject

Inherits:
Object
  • Object
show all
Defined in:
lib/social_linker/subject.rb

Constant Summary collapse

SHARE_TEMPLATES =

Constant defining how the different share-url’s look like and their parameters; the parameters can be set in the options directly, or will be derived from more generic options

{
  email: {
    base: "mailto:emailaddress?",
    params: [:subject,:body,:cc,:bcc]
  },
  pinterest: {
    base: "https://pinterest.com/pin/create/button/?",
    params: {url: :share_url, media: :media, description: :title}
  },
  linkedin: {
    base: "https://www.linkedin.com/shareArticle?mini=true&",
    params: {url: :share_url, title: :title, summary: :summary, source: :source}
  },
  google: {
    base: "https://plus.google.com/share?",
    params: {url: :share_url}
  },
  twitter: {
    base: "https://twitter.com/intent/tweet?",
    params: {text: :twitter_text, via: :via, url: :share_url, hashtags: :hashtags}
  },
  twitter_native: {
    base: "twitter://post?",
    params: {message: :twitter_text_with_url_and_hashags}
  },
  facebook: {
    base: "https://www.facebook.com/sharer/sharer.php?",
    params: {u: :share_url}
  },
  facebook_native: {
    base: "fb://publish/profile/me?",
    params: [:text]
  },
  whatsapp: {
    base: "whatsapp://send?",
    params: [:text]
  }

}

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Subject

Initialize the SocialLinker::Subject

options accepts:

  • tags

  • url

  • title

  • image_url & image_type(image/jpeg, image/png)

  • width and height for the images

  • description

  • facebook_app_id

  • twitter_username

  • language

  • site_title_postfix

  • … and more often medium specific attributes…

Note by default tracking parameters are added, turn this off by passing ‘utm_parameters: false`



224
225
226
227
228
# File 'lib/social_linker/subject.rb', line 224

def initialize(options={})
  # basic option syncing
  @options = {}
  self.merge!(options)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args) ⇒ Object

Catches method missing and tries to resolve them in either an appropriate share link or option value



372
373
374
375
376
377
378
379
380
381
# File 'lib/social_linker/subject.rb', line 372

def method_missing(m,*args)
  share_link_matcher = m.to_s.match(/([a-z]*)_share_link/)
  if share_link_matcher
    return share_link(share_link_matcher[1].to_sym)
  elsif options[m]
    return options[m]
  else
    super
  end
end

Instance Method Details

#bodyObject

Generates a large body of text (typical for email)

Returns:

  • String



280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/social_linker/subject.rb', line 280

def body
  return options[:body] if options[:body]
  rv = ""
  rv += "#{summary}\n" if summary
  rv += "\n#{share_url}\n" if share_url
  rv += "\n#{description}\n" if summary != description and description
  rv += "\n#{@options[:media]}\n" if options[:media] != share_url and options[:media]
  rv += "\n\n#{hashtag_string(@options[:tags])}" if options[:tags]
  rv.strip!
  rv = nil if rv == ""
  return rv
end

#camelize_tag_when_needed(tag) ⇒ String

single world tags don’t need any processing, but tags consisting of different words do (before they can use in hashtags following convention)

Parameters:

  • tag (String)

    to might need conversion

Returns:

  • (String)

    fixed tag



65
66
67
68
# File 'lib/social_linker/subject.rb', line 65

def camelize_tag_when_needed(tag)
  tag = tag.to_s
  tag.match(/\s/) ? tag.split(/\s/).collect{|a| a.capitalize}.join("") : tag
end

#canonical_urlObject



122
123
124
# File 'lib/social_linker/subject.rb', line 122

def canonical_url
  prefix_domain((@options[:canonical_url] || @options[:url]), @options[:domain])
end

#descriptionObject



293
294
295
# File 'lib/social_linker/subject.rb', line 293

def description
  @options[:description] || @options[:summary]
end

#filename_derived_image_typeObject



156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/social_linker/subject.rb', line 156

def filename_derived_image_type
  if media
    extension = media.to_s.split(".").last.downcase
    if extension == "jpg" or extension == "jpeg"
      "image/jpeg"
    elsif extension == "png"
      "image/png"
    elsif extension == "gif"
      "image/gif"
    end
  end
end

#hashtag_string(tags) ⇒ String

convert an array of strings to a Twitter-like hashtag-string

Parameters:

  • tags (Array)

    to be converted to string

Returns:

  • (String)

    containing a Twitter-style tag-list



52
53
54
55
56
57
58
59
# File 'lib/social_linker/subject.rb', line 52

def hashtag_string(tags)
  if tags and tags.count > 0
    tags = tags.collect{|a| camelize_tag_when_needed(a) }
    "##{tags.collect{|a| a.to_s.strip.gsub('#','')}.join(" #")}"
  else
    ""
  end
end

#hashtagsObject



179
180
181
# File 'lib/social_linker/subject.rb', line 179

def hashtags
  @options[:hashtags]
end

#image_typeObject



169
170
171
# File 'lib/social_linker/subject.rb', line 169

def image_type
  @options[:image_type] || filename_derived_image_type
end

#image_urlObject



77
78
79
# File 'lib/social_linker/subject.rb', line 77

def image_url
  @options[:image_url]
end

#mediaObject

default media accessor

Returns:

  • String with media-url



152
153
154
# File 'lib/social_linker/subject.rb', line 152

def media
  @options[:media]
end

#media_dimensionsObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/social_linker/subject.rb', line 81

def media_dimensions
  return @media_dimensions if @media_dimensions
  if media
    @media_dimensions = @options[:media_dimensions]
    if @media_dimensions.is_a? Array
      @media_dimensions = {
        width: @media_dimensions[0],
        height: @media_dimensions[1]
      }
    end
    @media_dimensions ||= {
      width: @options[:media_width],
      height: @options[:media_height]
    }
  else
    @media_dimensions = {}
  end
end

#media_heightObject



104
105
106
# File 'lib/social_linker/subject.rb', line 104

def media_height
  media_dimensions[:height].to_i if media_dimensions[:height]
end

#media_widthObject



100
101
102
# File 'lib/social_linker/subject.rb', line 100

def media_width
  media_dimensions[:width].to_i if media_dimensions[:width]
end

#merge!(options) ⇒ Object Also known as: update

Merges existing SocialLinker::Subject with a (potentially limited set of) new options

options accepts:

  • tags

  • url

  • title

  • image_url & image_type(image/jpeg, image/png)

  • description

  • facebook_app_id

  • twitter_username

  • render_site_title_postfix

  • … and more often medium specific attributes…

Note by default tracking parameters are added, turn this off by passing ‘utm_parameters: false`



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/social_linker/subject.rb', line 249

def merge!(options)
  options = options.options if options.is_a? SocialLinker::Subject
  options[:render_site_title_postfix] = true if options[:render_site_title_postfix].nil?
  options[:u] ||= options[:url] if options[:url]
  options[:media] ||= options[:image_url] if options[:image_url]
  options[:subject] ||= options[:title] if options[:title]
  options[:via] ||= options[:twitter_username] if options[:twitter_username]
  options[:text] = "#{options[:title]} #{options[:url]}" unless options[:text] #facebook & whatsapp native
  options[:domain] = options[:url].split(/\//)[0..2].join("/") if options[:url] and !options[:domain]
  options.select!{|k,v| !v.nil?}
  @options.merge!(options)

  if @options[:tags]
    @options[:tags].compact!
    @options[:hashtags] = @options[:tags][0..1].collect{|a| camelize_tag_when_needed(a) }.join(",") if @options[:tags] and !@options[:hashtags]
  end

  # make sure urls are absolute
  @options[:url] = prefix_domain(@options[:url],@options[:domain])
  @options[:image_url] = prefix_domain(@options[:image_url],@options[:domain])
  @options[:media] = prefix_domain(@options[:media],@options[:domain])

  @options.each do |k,v|
    @options[k] = v.strip if v and v.is_a? String
  end
  self
end

#optionsObject

Returns the given options, extended with the (derived) defaults

Returns:

  • Hash with the options



342
343
344
# File 'lib/social_linker/subject.rb', line 342

def options
  @options
end

#prefix_domain(path, domain) ⇒ Object

It is assumed that paths are relative to the domainname if none is given

Parameters:

  • path (String)

    to file (if it is already a full url, it will be passed along)

  • domain (String)

    of the file

Returns:

  • String with full url



328
329
330
331
332
333
334
335
336
337
# File 'lib/social_linker/subject.rb', line 328

def prefix_domain path, domain
  if path and !path.include?("//")
    return [
      domain.gsub(/\/$/,''),
      path.gsub(/^\//,'')
    ].join("/")
  else
    return path
  end
end

#quote_string(string) ⇒ String

puts quotes around a string

Returns:

  • (String)

    now with quotes.



185
186
187
# File 'lib/social_linker/subject.rb', line 185

def quote_string(string)
  "#{string}" if string and string.to_s.strip != ""
end

Generates a share link for each of the predefined platforms in the ‘SHARE_TEMPLATES` constant

Parameters:

  • platform (Symbol)

    to generate the link for



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/social_linker/subject.rb', line 349

def share_link(platform)
  share_options = SHARE_TEMPLATES[platform]
  raise "No share template defined" unless share_options

  url_params = {}
  share_options[:params].each do |k,v|
    value_key = v||k #smartassery; v = nil for arrays
    value = options[value_key]
    value = self.send(value_key) if self.methods.include?(value_key)
    if value and value.to_s.strip != ""
      value = value.gsub('<%=share_source%>', platform.to_s)
      url_params[k] = value
    end
  end

  return share_options[:base]+url_params.collect{|k,v| "#{k}=#{url_encode(v)}"}.join('&')
end

#share_urlObject



126
127
128
129
130
131
132
133
134
135
# File 'lib/social_linker/subject.rb', line 126

def share_url
  url_to_share = prefix_domain((@options[:share_url] || @options[:url]), @options[:domain])
  if utm_parameters?
    utm_url_params = utm_parameters.collect{|k,v| "#{k}=#{v}" unless url_to_share.match(k.to_s)}.compact.join("&")
    combine_with = url_to_share.match(/\?/) ? "&" : "?"
    return "#{url_to_share}#{combine_with}#{utm_url_params}"
  else
    return url_to_share
  end
end

#strip_string(string, max_length = 100) ⇒ String

strips a string to the max length taking into account quoting

Parameters:

  • string (String)

    that is about to be shortened

  • max_length (Integer) (defaults to: 100)

    of the string to be shortened (default 100)

Returns:

  • (String)

    shortened to the max lenght



193
194
195
196
197
198
199
200
201
202
203
# File 'lib/social_linker/subject.rb', line 193

def strip_string(string, max_length=100)
  if string and string.length > max_length
    elipsis = ""
    if string[-1] == ""
      elipsis = "#{elipsis}"
    end
    max_char = max_length-1-elipsis.length
    string = string[0..max_char]+elipsis
  end
  string
end

#summary(strip = false) ⇒ Object

default summary accessor

Returns:

  • String with summary



145
146
147
148
# File 'lib/social_linker/subject.rb', line 145

def summary(strip=false)
  summ = @options[:summary] || @options[:description]
  strip ? strip_string(summ, 300) : summ
end

#tagsObject

default tags accessor



175
176
177
# File 'lib/social_linker/subject.rb', line 175

def tags
  @options[:tags] ? @options[:tags] : []
end

#titleObject

default title accessor

Returns:

  • String with title



139
140
141
# File 'lib/social_linker/subject.rb', line 139

def title
  @options[:title] || "#{ strip_string(options[:summary], 120) }"
end

#twitter_hash_tagsObject

Turns the first two tags in to tweetable hash tags Conform recommendation never to have more than 2 tags in a twitter message

Returns:

  • String with two tags as #tags.



300
301
302
# File 'lib/social_linker/subject.rb', line 300

def twitter_hash_tags
  options[:tags] ? hashtag_string(options[:tags][0..1]) : ""
end

#twitter_textObject

Generatess the text to tweet (Twitter)

Returns:

  • String with text to tweet



306
307
308
309
310
311
312
# File 'lib/social_linker/subject.rb', line 306

def twitter_text
  return options[:twitter_text] if options[:twitter_text]
  return options[:tweet_text] if options[:tweet_text]

  max_length = 140 - (twitter_hash_tags.length + 12 + 4) #hashstring + url length (shortened) + spaces
  "#{quote_string(strip_string(@options[:title],max_length))}"
end

#twitter_text_with_url_and_hashagsObject Also known as: status

Generates a full twitter message includig url and hashtags

Returns:

  • String with full twitter message (typically for native app)



316
317
318
319
320
321
# File 'lib/social_linker/subject.rb', line 316

def twitter_text_with_url_and_hashags
  return options[:twitter_text_with_url_and_hashags] if options[:twitter_text_with_url_and_hashags]
  return options[:message] if options[:message]
  return options[:status] if options[:status]
  [twitter_text,twitter_hash_tags,share_url].delete_if{|a| a.nil? or a.empty?}.join(" ")
end

#urlObject

default url accessor

Returns:

  • String with url



73
74
75
# File 'lib/social_linker/subject.rb', line 73

def url
  @options[:url] || image_url
end

#url_encode(v) ⇒ Object



367
368
369
# File 'lib/social_linker/subject.rb', line 367

def url_encode(v)
  ERB::Util.url_encode(v)
end

#utm_parametersObject



112
113
114
115
116
117
118
119
120
# File 'lib/social_linker/subject.rb', line 112

def utm_parameters
  if utm_parameters?
    {
      utm_source: "<%=share_source%>",
      utm_medium: "share_link",
      utm_campaign: "social"
    }
  end
end

#utm_parameters?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'lib/social_linker/subject.rb', line 108

def utm_parameters?
  [nil, true].include?(@options[:utm_parameters]) ? true : false
end