Haml: Append class if condition is true in Haml - ruby

If post.published?
.post
/ Post stuff
Otherwise
.post.gray
/ Post stuff
I've implemented this with rails helper and it seems ugly.
= content_tag :div, :class => "post" + (" gray" unless post.published?).to_s do
/ Post stuff
Second variant:
= content_tag :div, :class => "post" + (post.published? ? "" : " gray") do
/ Post stuff
Is there a more simple and haml-specific way?
UPD. Haml-specific, but still not simple:
%div{:class => "post" + (" gray" unless post.published?).to_s}
/ Post stuff

.post{:class => ("gray" unless post.published?)}

- classes = ["post", ("gray" unless post.published?)]
= content_tag :div, class: classes do
/Post stuff
def post_tag post, &block
classes = ["post", ("gray" unless post.published?)]
content_tag :div, class: classes, &block
end
= post_tag post
/Post stuff

Really the best thing is to put it into a helper.
%div{ :class => published_class(post) }
#some_helper.rb
def published_class(post)
"post #{post.published? ? '' : 'gray'}"
end

HAML has a nice built in way to handle this:
.post{class: [!post.published? && "gray"] }
The way that this works is that the conditional gets evaluated and if true, the string gets included in the classes, if not it won't be included.

Updated Ruby syntax:
.post{class: ("gray" unless post.published?)}

Related

Export data to a .csv file on ruby app

I got an error
undefined method `form_for_results_path'
in my code to Export the data to a .csv file. Really don't know if I missed something. Here what I have:
item_controller
def export
CSV.open("result_data.csv", "w") do |csv|
csv << ["cod", "genre", "den_cont"]
end
end
In the view
<%= link_to 'Download CSV', form_for_results_path(#form), :method => :export %>
Thanks
Change it to this and read some more about rails basics.
<%= link_to 'Download CSV', controller: :item, action: :export%>
in your controller, you should do something like this, using rails send_data method:
def export
data = # your data in csv format
options = {
:filename => "some_name.csv",
:type => 'text/csv'
}
send_data(data, options)
end
you can also change your download link using a route_helper. add an entry in your routes file
get 'items/export', :as 'download_items_data"
then your link_to can look like this:
link_to 'Download CSV', download_items_data_path

Rails: How to add link_to with target blank

I am new to rails 3, I would like to add (:target => "_blank") to link_to helper below
link_to "GOOGLE", 'http://www.google.com', class: "btn btn-large btn-primary"
But I would like to use the application_helper to define link_to method.
How do I define the link_to methd in application_helper?
How do I pass the class: "btn btn-large btn-primary" in the link_to method?
Thank you for your assistance...
Why would you want to override link_to? It's already defined in Rails, just use it like this :
link_to "GOOGLE", "http://www.google.com", target: "_blank", class: "btn btn-large btn-primary"
Edit: OK, understood. I'd advise against overriding such a common method so create another one :
def link_to_blank(body, url_options = {}, html_options = {})
link_to(body, url_options, html_options.merge(target: "_blank"))
end
It should do the trick
Adding to Anthony's answer, this more closely resembles Rails' link_to implementation, including support for blocks and passing no parameters:
def link_to_blank(name = nil, options = nil, html_options = nil, &block)
target_blank = {target: "_blank"}
if block_given?
options ||= {}
options = options.merge(target_blank)
else
html_options ||= {}
html_options = html_options.merge(target_blank)
end
link_to(name, options, html_options, &block)
end
Up to now for Rails 7, I suggest a more elegant way according to Rails's implementation of link_to:
def link_to(name = nil, options = nil, html_options = nil, &block)
html_options, options, name = options, name, block if block_given?
link_to(name, options, (html_options || {}).merge(target: '_blank'))
end

Testing custom routes in rails 3.0.1 does not work, or is it me?

For some reason when I run this functional test
require 'test_helper'
class ListControllerTest < ActionController::TestCase
test "should get mylist" do
post :mylist, :format => :json
assert_response :success
end
end
routes.rb
SomeApplication::Application.routes.draw do
match "/mylist" => "list#mylist", :method => "POST"
end
list_controller.rb
class ListController < ApplicationController
def mylist
respond_to do |format|
format.json { render :json => []}
end
end
end
Sourcecode as a gist
I get this error:
1) Error:
test_should_get_mylist(ListControllerTest):
ActionController::RoutingError: No route matches {:controller=>"list", :format=>:json, :action=>"mylist"}
/test/functional/list_controller_test.rb:6:in `test_should_get_mylist'
Any ideas?
Regards,
Michal
OK. I got it. Those stupid errors are the most difficult to spot. Sometimes I cry for ruby to have strong typing ;)
the problem is in the routes.rb. Instead of:
match "/mylist" => "list#mylist", :method => "POST"
it should have been
match "/mylist" => "list#mylist", :via => :post
Thanks everyone who tried to help me.

Configure the label of Active Admin has_many

Well I have a two models related with a on-to-many assoc.
#models/outline.rb
class Outline < ActiveRecord::Base
has_many :documents
end
#models/document.rb
class Document < ActiveRecord::Base
belongs_to :outline
end
#admin/outlines.rb
ActiveAdmin.register Outline do
form do |f|
f.inputs "Details" do
f.input :name, :required => true
f.input :pages, :required => true
...
f.buttons
end
f.inputs "Document Versions" do
f.has_many :documents, :name => "Document Versions" do |d|
d.input :file, :as => :file
d.buttons do
d.commit_button :title => "Add new Document Version"
end
end
end
end
end
Well as you can see in the admin/outlines.rb I already tried setting up the :name, in the has_many :documents, and the :title in the commit_button, but neither of that options work, I also tried with :legend, :title, and :label, instead of :name in the .has_many. Not working.
This is the result of that code:
Screenshot
What I want to display is "Document Versions" instead of "Documents", and "Add new Document Version" instead of "Add new Document"
If someone can have a solution it would be great
To set has_many header you can use
f.has_many :images, heading: 'My images' do |i|
i.input :src, label: false
end
See here
Looking at ActiveAdmin tests("should translate the association name in header"), there may be another way of doing this. Use your translation file.
If you look at ActiveAdmin has_many method (yuck!!! 46 lines of sequential code), it uses ActiveModel's human method.
Try adding this to your translation file
en:
activerecord:
models:
document:
one: Document Version
other: Document Versions
One quick hack is that you can hide the h3 tag through its style.
assets/stylesheets/active_admin.css.scss
.has_many {
h3 {
display: none;
}}
This will hide any h3 tag under a has_many class.
You can customise the label of the "Add..." button by using the new_record setting on has_many. For the heading label you can use heading:
f.has_many :documents,
heading: "Document Versions",
new_record: "Add new Document Version" do |d|
d.input :file, :as => :file
end
Sjors answer is actually a perfect start to solving the question. I monkeypatched Active Admin in config/initializers/active_admin.rb with the following:
module ActiveAdmin
class FormBuilder < ::Formtastic::FormBuilder
def titled_has_many(association, options = {}, &block)
options = { :for => association }.merge(options)
options[:class] ||= ""
options[:class] << "inputs has_many_fields"
# Set the Header
header = options[:header] || association.to_s
# Add Delete Links
form_block = proc do |has_many_form|
block.call(has_many_form) + if has_many_form.object.new_record?
template.content_tag :li do
template.link_to I18n.t('active_admin.has_many_delete'), "#", :onclick => "$(this).closest('.has_many_fields').remove(); return false;", :class => "button"
end
else
end
end
content = with_new_form_buffer do
template.content_tag :div, :class => "has_many #{association}" do
form_buffers.last << template.content_tag(:h3, header.titlecase) #using header
inputs options, &form_block
# Capture the ADD JS
js = with_new_form_buffer do
inputs_for_nested_attributes :for => [association, object.class.reflect_on_association(association).klass.new],
:class => "inputs has_many_fields",
:for_options => {
:child_index => "NEW_RECORD"
}, &form_block
end
js = template.escape_javascript(js)
js = template.link_to I18n.t('active_admin.has_many_new', :model => association.to_s.singularize.titlecase), "#", :onclick => "$(this).before('#{js}'.replace(/NEW_RECORD/g, new Date().getTime())); return false;", :class => "button"
form_buffers.last << js.html_safe
end
end
form_buffers.last << content.html_safe
end
end
end
Now in my admin file I call titled_has_many just like has_many but I pass in :header to override the use of the Association as the h3 tag.
f.titled_has_many :association, header: "Display this as the H3" do |app_f|
#stuff here
end
Does not deserve a prize but you could put this in config/initializers/active_admin.rb . It will allow you to tweak the headers you want using a config/locales/your_file.yml (you should create the custom_translations entry yourself). Dont forget to restart the server. And use the f.hacked_has_many in your form builder.
module ActiveAdmin
class FormBuilder < ::Formtastic::FormBuilder
def hacked_has_many(association, options = {}, &block)
options = { :for => association }.merge(options)
options[:class] ||= ""
options[:class] << "inputs has_many_fields"
# Add Delete Links
form_block = proc do |has_many_form|
block.call(has_many_form) + if has_many_form.object.new_record?
template.content_tag :li do
template.link_to I18n.t('active_admin.has_many_delete'), "#", :onclick => "$(this).closest('.has_many_fields').remove(); return false;", :class => "button"
end
else
end
end
content = with_new_form_buffer do
template.content_tag :div, :class => "has_many #{association}" do
# form_buffers.last << template.content_tag(:h3, association.to_s.titlecase)
# CHANGED INTO
form_buffers.last << template.content_tag(:h3, I18n.t('custom_translations.'+association.to_s))
inputs options, &form_block
# Capture the ADD JS
js = with_new_form_buffer do
inputs_for_nested_attributes :for => [association, object.class.reflect_on_association(association).klass.new],
:class => "inputs has_many_fields",
:for_options => {
:child_index => "NEW_RECORD"
}, &form_block
end
js = template.escape_javascript(js)
_model = 'activerecord.models.' + association.to_s.singularize
_translated_model = I18n.t(_model)
js = template.link_to I18n.t('active_admin.has_many_new', :model => _translated_model), "#", :onclick => "$(this).before('#{js}'.replace(/NEW_RECORD/g, new Date().getTime())); return false;", :class => "button"
form_buffers.last << js.html_safe
end
end
form_buffers.last << content.html_safe
end
end
end
If you have issues with locale files not being loaded good in staging/production mode, adding this to your application.rb might help (substitute :nl for the right locale)
config.before_configuration do
I18n.load_path += Dir[Rails.root.join('config','locales','*.{rb,yml}').to_s]
I18n.locale = :nl
I18n.default_locale = :nl
config.i18n.load_path += Dir[Rails.root.join('config','locales','*.{rb,yml}').to_s]
config.i18n.locale = :nl
config.i18n.default_locale = :nl
I18n.reload!
config.i18n.reload!
end
config.i18n.locale = :nl
config.i18n.default_locale = :nl

Element.update rjs error while using link_to_remote in rails

I am using rails 2.3.2
I have a link_to_remote functions
<%= link_to_remote "Comments ", {
:url => {:controller => "blogs",:action => "fetchcomments",:id => blog.id}} %> |
and the rails action as
def fetchcomments
unless params[:id].nil?
#blog = Blog.find(params[:id])
respond_to do |format|
format.js do
render :update do |page|
page.replace_html("comm", 'hi')
end
end
end
end
The above code throws me the error as
try {
Element.update("comm", "hi");
} catch (e) { alert('RJS error:\n\n' + e.toString());
alert('Element.update(\"comm\", \"hi\");'); throw e }
Please give me suggestions
Remove unless params[:id].nil? and it will work if you have an element with the id 'comm' on the page that makes the request. Of course it will replace whatever is inside with the word 'hi'.

Resources