I am developing a Rails application and I wish to use the open graph protocol so that on the "articles" page perople can link to social media (facebook, twitter, and google+) to recommend/like etc the article.
As part of the this I endevour, unsuccessfully to set og metatags for the url, within the head section of the page. From the code partial ogmeta.html.erb
<meta property="og:title" content='<%= meta[:title] || "DrillInvestor" %>'>
<meta property="og:type" content='<%= meta[:type] || "website" %>'>
<meta property="og:image" content='<%= meta[:image] || "http://www.whatever.com/image.jpg" %>'>
<meta property="og:url" content='<%= meta[:url] || "post_url(#post)" %>'>
Which when I view the page source I see
<html>
<head>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<meta property="og:title" content='DrillInvestor'>
<meta property="og:type" content='website'>
<meta property="og:image" content='http://www.whatever.com/image.jpg'>
<meta property="og:url" content='post_url(#post)'>
What I am trying to pass as the url I can see from a print statement in the posts controller
puts "==================="
puts "url = " + post_url(#post).to_s
I see url = http://quiet-fortress-3338.herokuapp.com/posts/drill-01-more-updates which is what I am want, in this case, to see as the og:url.
I am a recovering COBOL pogrammer and sometimes (well perhaps more than that) lose my way with this sort of stuff.
If I hardcode the og:url I get the appropriate page. I have tried a numer of dfferent things including#{} enclosing the post_url(#post) etc.
Thanks in advance and any help welcome
Pierre
You need to get rid of the quotes around "post_url(#post)". Just change it to post_url(#post). Note that in your print statement you don't have it enclosed in quotes and it works.
As an aside, you don't need to call to_s in either case - post_url(#post) returns a string.
Related
I would like to use non-public images from an S3 bucket in my site's meta tag.
My <head> looks like this:
<meta property="og:image" content="<%= asset_path #list.image %>" />
And source like this:
<meta property="og:image" content="//mybucket-main.s3.amazonaws.com/uploads/asdflkj/myimage.jpg" />
My images render perfectly when I include them throughout the site:
<%= image_tag #list.image %> becomes
<img src="//mybucket.s3.amazonaws.com/uploads/asdflkj/myimage.jpg" alt="myimage" />.
(Incidentally, it even renders in this post if I use the real src.)
I receive this error from https://developers.facebook.com/tools/debug/sharing:
Object Invalid Value: Object at URL 'https://example.com/lists/1462' of type 'website' is invalid because the given value '//mybucket.s3.amazonaws.com/uploads/image.jpg' for property 'og:image:url' could not be parsed as type 'url'.
Please help!
I have a Rails personality test app that uses AJAX to render the questions and show the results.
I have been attempting to share personality test results via Facebook by sending the variable to one of my dashboard Rails controller to dynamically create tags.
However, the variable is nil when the page is first loaded (which causes an error), so I fixed it by adding a conditional (in application.html.erb):
<% if #cat %>
<meta property="og:title" content="You got <%= #cat.name %>!"/>
<meta property="og:image" content="<%= #cat.picture %>" />
<meta property="og:description" content="<%= #cat.description%>" />
<meta property="og:url" content="https://mysite" />
<meta property="fb:app_id" content= "<%=ENV['FACEBOOK_APP_ID']%>" />
<meta property="og:type" content="website">
<% end %>
Facebook does not recognize the tags when I checked the sharing debugger. I also tried initializing with another object (home controller):
def index
if params.has_key?("cat")
#cat = Cat.find_by(name: params["cat"])
else
#cat = Cat.find_by(name: "Colonel Meow")
end
end
With this, Facebook does not render the new value, but renders the old value instead. I put a debugger in my application.html to make sure the variables were changing (they did). Facebook did not refresh though.
Is there a way to use a conditional when assigning the tags? Or to refresh the tags so Facebook uses the new variable?
I have some dynamic images defined as follows on my page:
<%= image_tag(#recipe.image.url(:fixed), :class => 'recipe_image_show') %>
I am looking for a way to define og:image with this code. The og:description code seen below works perfectly:
<meta property="og:description" content= "<%= #recipe.description %>" />
But if I use the code below then it doesn't want to work:
<meta property="og:image" content='<%= image_tag(#recipe.image.url(:fixed), :class => 'recipe_image_show') %>'/>
Any suggestions? I realised I have used single quotes here but using double quotes for some reason results the page to disregard the '/>' part of the meta tag and display it as text.
As per the chat discussion, OP is hosting the images on S3.
So, define the meta tag as below:
<meta property="og:image" content='<%= #recipe.image.url(:fixed) %>'/>
This will be evaluated to:
<meta property="og:image" content='https://s3....amazonaws.com/path/to/image.jpg'/>
NOTE:
If image was stored on the your own application server then you could use it as:
<meta property="og:image" content='<%= image_url #recipe.image.url(:fixed) %>'/>
if you are on rails 6 with wepback this one worked for me
- meta 'og:image': "#{asset_pack_url "static/image.webp"}"
check asset_pack_url on github for reference
your image path may vary, lookup manifest.json for this manner
Use the tool https://developers.facebook.com/tools/debug/
Click "Scrape Again" to reload Facebook Cache
Use full path with image_url("example.png")
Im wondering if it is possible to use g:include to include only the body contents of a given page.
Say i have a main layout page as follows:
<html>
<head>
<title>My start page</title>
<g:layoutHead>
</head>
<body>
<g:layoutBody>
</body>
</html>
Then a main page (index.gsp)
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:include controller="book" action="list"/>
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And finally the book/list page
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
</body>
</html>
So what i want to achieve is that the main page (index.gsp) only includes the table defined in the book/list page. However, when i try this it includes the entire html defined (<html> tags and all).
is it possible to do this somehow? i've tried things like <g:include controller="book" action="list" view="someView.gsp"/> however this doesn't work. I really want to avoid having to add a book list logic to the "index controller" i want to reuse my existing controller.
I can't be the first person out there having this usecase, what solutions have you guys come up with?
You can use the applyLayout tag. Simply create an empty.gsp layout with only:
<g:layoutBody/>
And then decorate your include tag with applyLayout:
<g:applyLayout name="empty">
<g:include controller="book" action="list"/>
</g:applyLayout>
See the entry on the Grails guide for further reference.
This is IMHO directly not possible. An idea would be to create a custom tag based on g:include, that strips out parts of the code by e.g. an xpath expression. I'm not aware that this already exists somewhere.
An alternative would be to refactor the body part of book's list.gsp into a template and reference that template from index.gsp using g:render. But this means that the data model has to be available in index.gsp context since g:render does not invoke a controller.
Side note: when using g:include it's a good idea to use the springcache plugin for page fragment caching.
Yes, but you need you need one more level in there. Look at Grails templates. Essentially, you'd have a template: _books.gsp containing:
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
Then your index would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:render template="books">
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And your list would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<g:render template="books" />
</body>
</html>
(My syntax may not be 100% right, since it's been a couple months since I've done this, but the idea behind templates are short, reusable pieces of GSP code that aren't meant to be displayed on their own.
Hey. Imagine i have two separate gsp pages with diferent css formatting (with name conflicts between two). And i want to "display" or render one page with its ows formatation inside a div in the other page. Imagining this scenario:
page1.gsp
...
...
<div id="here"></div>
...
...
page2.gsp
Hello there!
I want my final page to be:
...
...
Hello there!
...
...
Is it possible to do that?
Yes use the g:render tag and create a "fragment" page to contain your content.
then use the g:render tag to pull it in.
Refer to the documentation or tutorials for more detail on this.
This is very similar to a question I posted a couple of days ago:
Can I display an inner dive with an independent stylesheet?
Is this something you want to work for every page? (Like a layout?)
If that is the case, use SiteMesh (built in already)
{app}/grails-app/views/layouts/mylayout.gsp
<html>
<head>
<g:layoutTitle default="My Application" />
<link rel="stylesheet" href="${resource(dir:'css',file:'layout.css')}" />
<g:layoutHead />
</head>
<body>
<div id="here"><g:layoutBody /></div>
</body>
</html>
{app}/grails-app/views/{somefolder}/page1.gsp
<html>
<head>
<meta name="layout" content="mylayout" />
<link rel="stylesheet" href="${resource(dir:'css',file:'page1.css')}" />
</head>
<body>
Hello There!!!!
</body>
</html>
If you already have that, and are just looking at breaking up you pages and keeping them DRY..
{app}/grails-app/views/{somefolder}/page1.gsp
<html>
<head>
<meta name="layout" content="yourLayout" />
<link rel="stylesheet" href="${resource(dir:'css',file:'page1.css')}" />
</head>
<body>
<div id="here2"><g:render template="page2" model="[foo:'bar']"/></div>
</body>
</html>
* The Model property of render is optional, but works for passing data to the template to be rendered
{app}/grails-app/views/{somefolder}/_page2.gsp
* Notice the "_" before the gsp name. (Convention for Template pages)
Hello There
Checkout the documentation for render and templating