haml using variable in rails layout for meta keywords - haml

We would like to adjust the meta keywords of a web page based upon the specific action. As a novice at haml, is there a way that this could be done via a provides statement. For example:
in client.html.haml
- provide(:keywords, 'here are unique keywords')
and in our application.html.haml, how would we do this? Like:
%meta{ name: "keywords", content: #{yield(:keywords)} ||= default keywords
but this doesn't work.

You don't say why your approach doesn't work, so I'm going to guess it's a syntax error in your haml (missing closing bracket). Also, I'm not sure what default keywords is or why you're using the ||= operator - either of those may also be causing your solution to "not work".
Something like the following will work as expected:
# application.html.haml
%meta{ name: "keywords", |
content: content_for?(:keywords) ? yield(:keywords) : "default" }
# this could also be achieved using content_for?(:keywords) || "default"
# client.html.haml
- provide :keywords do
this should work

Related

Use a locale translation inside of another

Is there a way to do something like this
en:
name: "Jimmy"
sentence: "my name is %{name}"
this way I would be able to construct translation which are built on each other and are more dynamic so I could do
es:
name: "Inigo Montoya"
sentence: "My-o name-o es %{name}" (still working on the spanish part)
is there a way to do this?
Unfortunately, there is not a way to do this in the way you want in YAML.
See the Passing variables inside rails internationalization yml file thread for an answer to a question nearly exactly the same as yours.

Dashes in property name not getting NoMethodError

I'm using the Linkedin gem to pull profile information for RoR 3.
Gem: https://github.com/pengwynn/linkedin
API Doc: https://developer.linkedin.com/documents/profile-fields#positions
Everything works except when I get to a property with a dash in the name.
<%=position.title %> displays correctly but<%= position.start-date %> return a NoMethodError in Users#show - undefined method start.
I've tried different operations like "startDate", "start_date", quotes around "start-date" but none have worked.
Is there a proper way to escape the dash/hyphen in the property name?
The expression in your ERB will be parsed as subtracting the value of the date variable from the result of a call to the start() method of the position object. Hyphens aren't valid in identifiers within Ruby.
I'm not familiar enough with the LinkedIn gem to suggest a solution, except to say that since it's based on an XML API, you should look for a way to manually pull data out of a tag pair. Most similar gems offer such a method. Also, this is a great case for using IRB as an exploratory tool: fire up an IRB session and see what happens when you call position.methods, after properly creating the position variable of course. My guess would be that you'll see something in that list which suggests an answer.
Looks like it returns a Hashie::Mash which converts keys, with a few extra rules:
https://github.com/pengwynn/linkedin/blob/master/lib/linked_in/mash.rb
You said you'd already tried position.start_date right? That should work. But if not, have you tried position['start-date'] or position['start_date'] one of those two should also work, since it's a Mash.

Rails - Use same attachment for all emails using layout

I'm probably missing something obvious, but I've got a logo I'd like to include in all of the emails I send from my app. I have a master layout I'm using for all of those Mailers. I assume there's a way to do keep it DRY and not have to add the line of code to attach the file in every mailer method. Can someone point me in the right direction or correct my line of thought.
Thanks!
Callbacks using before_filter and after_filter will be supported in a future Rails release:
http://github.com/rails/rails/commit/4f28c4fc9a51bbab76d5dcde033c47aa6711339b
Since they will be implemented using AbstractController::Callbacks, you can do the following to mimic the functionality that will be present in ActionMailer::Base once Rails 4 is released:
class YourMailer < ActionMailer::Base
if self.included_modules.include?(AbstractController::Callbacks)
raise "You've already included AbstractController::Callbacks, remove this line."
else
include AbstractController::Callbacks
end
before_filter :add_inline_attachments!
private
def add_inline_attachments!
attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
end
end
This includes the module that will be used in a future rails version, so the callback hooks available to you will be the same to ensure future compatibility. The code will raise when you try to upgrade to a Rails version that already includes AbstractController::Callbacks, so you will be reminded to remove the conditional logic.
I hacked a little something, it's not ideal, but it works.
If you use
default "SOMEHEADER", Proc.new { set_layout }
And then define set_layout
def set_layout
attachments.inline["logo.png"] = File.read("logopath.png")
attachments.inline["footer.jpg"] = File.read("footerpath.png")
"SOME HEADER VALUE"
end
Then because set_layout gets called to set the header, it also adds the inline attachments. It basically creates a callback for adding attachments.
An actual callback system in ActionMailer would be preferable, but this works too.
Thought I would share since I was looking for this answer on this question earlier today.
in the layout file that your mailer uses u can add the following
<%= image_tag('logo.png') %>
I am assuming that the mail being sent out is html or multipart.
Also you will need to make changes in the environment files. ActionMailer does not get a default base_url. For e.g in environments/development.rb I added the following
config.action_mailer.default_url_options = { :host => "localhost:3000" }
If you want to do it in a dRY manner (and as an attachment) maybe you could do something like
class MyMailer < ActionMailer::Base
default :attachment => File.read(File.join(Rails.root,'public','images','logo.png'))
end
I know you've asked about attaching inline images, but here's a different approach that achieves the same thing with less complexity..
Using inline base64 encoded images in the html layout - no attachments required!
Basically just change the src="..." of your logo image to the format:
<img alt="example logo"
width="32px"
height="32px"
src="data:image/png;base64,iVBORw0KGgoAAA....."/>
I use the online base64 encoder / decoder tool at http://www.base64-image.net for generating the complete <img /> tag
This approach has a few benefits:
- no attachment code, which makes the backend server code cleaner and easier to read
- no increase in email size - inline image attachments are converted to base64 anyway so this approach doesn't make the email payload any larger
- it's widely supported - if the receiving email client is showing html, it's pretty likely it also supports this method

Complete noob Jquery / Rails setup question (probably)

Background: I've been doing RoR for about a year now, and am fairly comfortable with it, however, I know next to nothing about Javascript.
I've been playing around with some jquery autocomplete stuff in my rails app. I pretty much had a version working, but needed some tokenized fields too for a one to many relationship.
Right on cue - good old Ryan Bates does a railscast on it. So I start following the instructions.
Got a little bit nervous when I had to start installing 'jquery-rails' gem (I'd already installed jrails to get the other stuff working).
As suspected, it broke some stuff but I managed to get that working again.
Anyway, I got most of the way through the tutorial, and everything was going fine - I've got the tokenizer script to find the correct input field and it acts as expected. I've tested the json link too - that sends back all the right stuff.
However when I start typing in the text field - nothing happens, and when I view the console window it comes back with:
Uncaught TypeError: Cannot call method 'replace' of undefined
jQuery.jQuery.extend._Deferred.deferred.resolveWith
done
jQuery.ajaxTransport.send.callback
I can make guesses as to why this is going wrong - but any expert advice would be greatly appreciated.
(I should also add - I'm using formtastic too)
Thanks in advance.
Ok, finally figured it out.
It turns out that my author's name column is not name but rather author. So I needed to make a change inside the js.coffee script to override that default search of name.
The line you need to use is:
propertyToSearch: "author"
My whole book.js.coffee file now looks like this:
jQuery ->
$('#book_author_tokens').tokenInput '/authors.json'
theme: 'mac'
prePopulate: $('#book_author_tokens').data('load')
propertyToSearch: "author"
This actually fixed the error Uncaught TypeError: Cannot call method 'replace' of undefined
Of course, if you do use a different column name you will want to also edit the functions in the author.rb file to reflect that:
def self.tokens(query)
authors = where("author like ?", "%#{query}%")
if authors.empty?
[{id: "<<<#{query}>>>", author: "New: \"#{query}\""}]
else
authors
end
end
def self.ids_from_tokens(tokens)
tokens.gsub!(/<<<(.+?)>>>/) { create!(author: $1).id }
tokens.split(',')
end
Edit
Another thing I had to do for the fieldsto be prepopulated with the existing authors was change this:
= f.input :author_tokens, :data => { :load => #book.author }
To this:
= f.input :author_tokens, :input_html => { :data => { :load => #book.author } }
And then they would show up.
Hope this helps you.

Can you remove the _snowman in Rails 3?

I'm building an app on Rails 3 RC. I understand the point behind the _snowman param (http://railssnowman.info/)...however, I have a search form which makes a GET request to the index. Therefore, submitting the form is creating the following query string:
?_snowman=☃&search=Box
I don't know that supporting UTF encoding is as important as a clean query string for this particular form. (Perhaps I'm just too much of a perfectionist...hehe) Is there some way to remove the _snowman param for just this form? I'd rather not convert the form to a POST request to hide the snowman, but I'd also prefer it not be in my query string. Any thoughts?
You can avoid the snowman (now a checkmark) in Rails 3 by.... not using Rails for the search form. Instead of using form_tag, write your own as outlined in:
Rails 3 UTF-8 query string showing up in URL?
Rails helpers are great unless they're not helping. Do-it-yourself is good as long as you understand the consequences, and are willing to maintain it in the future.
I believe the snowman has to be sent over the wire to ensure your data is being encoded properly, which means you can't really remove the snowman input from forms. Since, it's being sent in your GET request, it will have to be appended to the URL.
I suppose you could write some javascript to clean up the URL once the search page loads, or you could setup a redirect to the equivalent URL minus the snowman. Both options don't really feel right to me.
Also, it doesn't seem there is any way to configure Rails to not output it. If you really wanted to get rid of it, you could comment out those lines in Rails' source (the committed patches at the bottom of railssnowman.info should lead you to the files and line numbers). This adds some maintenance chores for you when you upgrade Rails. Perhaps you can submit a patch to be able to turn this off?
EDIT: Looks like they just switched it to what looks like a checkmark instead of a snowman.
EDIT: Oops, back to a snowman.
In Rails 4.1 you can use the option :enforce_utf8 => false to disable utf8 input tag.
However I want to use this in Rails 3, so I monkey-patched my Rails. I put the following in the config/initializers directory.
# allow removing utf8 using enforce_utf8, remove after Rails 4.1
module ActionView
module Helpers
module FormTagHelper
def extra_tags_for_form(html_options)
authenticity_token = html_options.delete("authenticity_token")
method = html_options.delete("method").to_s
method_tag = case method
when /^get$/i # must be case-insensitive, but can't use downcase as might be nil
html_options["method"] = "get"
''
when /^post$/i, "", nil
html_options["method"] = "post"
token_tag(authenticity_token)
else
html_options["method"] = "post"
tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag(authenticity_token)
end
enforce_utf8 = html_options.delete("enforce_utf8") { true }
tags = (enforce_utf8 ? utf8_enforcer_tag : ''.html_safe) << method_tag
content_tag(:div, tags, :style => 'margin:0;padding:0;display:inline')
end
end
end
end