Categories
Programming

Riding the Rails: Amazon S3 & Flowplayer

Vi har börjat använda Amazon S3 för att lagra filmer som vi sedan ska spela upp (med hjälp av Flowplayer) i en inloggningsskyddad applikation.

För att sätta upp kopplingen mot S3 så använder vi oss av Paperclip och AWS::S3. Att få igång uppladdningen mot S3 tillsammans med Paperclip var absolut inga problem, det fungerade i princip så fort vi hade lagt in något liknande detta i vår modell:

has_attached_file :media_file,
    :storage => :s3,
    :s3_credentials => Rails.root.join('config', 's3.yml'),
    :path => ":attachment/:id/:style/:basename.:extension",
    :bucket => 'our_bucket',
    :s3_permissions => 'authenticated-read',
    :url => ":s3_protected_url"
    
  # Video Validations
  validates_attachment_presence :media_file
  validates_attachment_content_type :media_file, :content_type => ['application/x-shockwave-flash', 'application/x-shockwave-flash', 'application/flv', 'video/x-flv', 'video/H264']

(Det är authenticated-read som sätter rättigheterna på anslutningen och gör att vi kan använda oss av Paperclips expiring_url-metod.)

Problemet uppstod när vi skulle använda Flowplayer för att streama direkt ifrån S3, vi vill bara ha verifierade användare som ser våra filmer. Det blev strul med tecknen i de meckiga länkarna som S3 genererar och Flowplayer kunde inte läsa de rakt av.

Vi använde oss då av en “Alternate embedding method” aka. flashembed.js. Så här beskrivs “Flashembed and Flowplayer”:

Flowplayer is a regular Flash component just like any other Flash component. It can be placed on your page with this tool or by using HTML-based object tags or you can use our “competitor”, SWFObject.

Sedan när vi skickade den “säkra” länken från controllern till viewn så fick vi manuellt ersätta lite tecken:

@media[:flash_url] = @media.media_file.expiring_url.gsub("&", "%26").gsub("?", "%3F").gsub("=", "%3D")

För att embedda den i viewn så får du även se till att säga åt Rails att det är en säker länk (med hjälp av html_safe):



Categories
Programming

Riding the Rails: Aktiva menyobjekt

Fredrik W visade mig en riktigt stilig sak häromdagen på ett Rails-projekt vi håller på med. Att göra layouter och framför allt visa vilket menyobjekt som är “aktivt”, dvs vilken sida du är på just nu.

Lägg in denna helpern, i exempelvis application_helper.rb:

  
def menu_item(text, link, options = {:use_span => false, :only_controller => false})
   active = Rails.application.routes.recognize_path link
   text = content_tag("span", text) if options[:use_span]
     
   link_is_currently_active = options[:only_controller] ? params[:controller] == active[:controller] : params[:controller] == active[:controller] && params[:action] == active[:action]
    
   klass = link_is_currently_active ? "active" : ""
   return content_tag("li", link_to(text, link), :class => klass)
end
  
def menu(options = {}, &block)
  return content_tag("ul", options, &block)
end

Vi läser alltså av existerande routen och jämför den med menyobjektets. Så nu istället för att länk runt dig i applikationen med link_to så kan du nu använda blocket menu:

<% menu do %>
  <%= menu_item "Link 1", project_path(@project) %>
  <%= menu_item "Link 2", project_medias_path(@project) %>
<% end %>

Vips, så har vi nu fått en lista med det aktiva objektets klass som “active“.

Nu är det klart att detta är en väldigt begränsad lösning och kanske inte lämpar sig i större projekt med stora menystrukturer, men för enklare projekt fungerar detta alldeles utmärkt.

Categories
Programming

WordPress pluginguide: Sätta ny titel i en shortcode

Jag håller på med ett Reddit-liknande WordPress-plugin på ett projekt hos Populate.

Systemet listar ett antal frågor som du som besökare kan “rösta upp”, sedan visar man de populäraste frågorna och lite annat. Varje fråga har en egen landningssida, exempelvis /fraga/10 (där 10 är id:t på frågan). Landningssidan och listningen av frågorna definieras av shortcodes i sidor, exempelvis: [poll_show_single] och [poll_list].

På sidan som innehåller [poll_show_single], i det här fallet är det sidan ‘fraga’, vill jag ha möjlighet att sätta frågans rubrik som ny titel (via filtret wp_title).

Det går tyvärr inte att ändra titeln inifrån shortcoden, utan man får identifiera vilken sida som shortcoden finns på och sen sätta titeln separat. Detta kan du göra på följande sätt:

function locate_shortcode ($shortcode) {
  global $wpdb;
  
  $search = ((!empty($search))?" OR ":"")."post_content LIKE '%$shortcode%'";
  
  $query = "SELECT ID,post_title,post_name,post_content FROM $wpdb->posts WHERE $search AND post_type='page'";
  $result = $wpdb->get_results($query);

  return array('id' => $result[0]->ID, 'title' => $result[0]->post_title, 'name' => $result[0]->post_name, 'uri' => get_page_uri($result[0]->ID) );
}

Sedan läser du av den:

$pollSingle = locate_shortcode( 'poll_show_single' );  
$pollSingleURI = $pollSingle['uri'];

Då får jag fram vilken sida som innehåller shortcoden för att visa en enskild fråga, därefter kan jag haka in mig på filtret ‘wp’ och sätta titeln:

add_filter('wp', 'titles' );

I titels() kollar vi sedan upp om vi står på rätt sida (den som finns i $pollSingleURI) och jämför den med $wp_query->query[‘pagename’]:

function titles() {
  global $wp_query, $wpdb, $newTitle, $pollSingleURI;
    
  // Single poll
  if ($wp_query->query['pagename'] == $pollSingleURI) {
    if (preg_match("/\d+\/?$/", $wp_query->query['page'])) {
      $pollID = str_replace('/', '', $wp_query->query['page']);
      $result = $wpdb->get_results( sprintf("SELECT subject FROM %spoll WHERE id = %d LIMIT 1", $wpdb->prefix, $wpdb->escape($pollID) ) );

      // Set title
      $newTitle = esc_html($result[0]->subject);
      add_filter('wp_title', 'frontend_set_title' , 10, 2 );
    }
  }
}

Ovanstående SQL-fråga hämtar just nu frågans titel, men detta ändrar du givetvis till det du vill ha som titel.

Och eftersom PHP fortfarande har lite problem med closures/anonyma funktioner så måste titeln sättas separat:

 
function frontend_set_title($title, $separator) {
  global $newTitle;
  return esc_html($newTitle)." ".$separator;
}

Allt är ryckt ur en klass för att lättare kunna visa hur det fungerar, därav alla globala variabler *urk*. Denna metod kräver inga “rewrites” eller “template redirect intercepts”.