How do I add 2 conditional classes to a div? - ruby-on-rails

Here is my div. What is the syntax for adding another conditional class?
.progress{ :class => list.overdue? ? "progress-danger" : "" }
I essential want to add list.dirty? ? "progress-warning" : ""
But what is the right way to fit that in along side the list.overdue? part?

Why dont you take it to a helper
View code
.progress{ :class => check_list_over_due }
Helper Code
def check_list_over_due
if condition
'classname'
elsif condition
'classname'
else
'classname'
end
end

I don't know if it's "right" per se, but this should work:
:class => [list.overdue? ? "progress-danger" : nil,
list.dirty? ? "progress-warning" : nil].compact.join(" ")

I think the best way is to write helper, like "progress_bar_class(list)" and implement all logic in light structurized code.

Related

Rails - button_tag using hash

I tried to simplify my code from this:
button_tag default_button[:name] ? default_button[:name] : t(button.to_s) , type: default_button[:type] ? default_button[:type] : 'submit', class: default_button[:class] ? default_button[:class] : "btn_#{button.to_s}"
To this:
button_tag(default_button)
But it doesn't work, I get the whole hash as text in the button. How can I make it smart to use the hash key/values?
I found this solution, the first parameter is a bit special.
concat button_tag(default_button[:name], default_button)

if condition in haml view

I want to set a :data attr if a condition is met. In this case a user should have a role. So it's a boolean statement. Let me give an example.
- #data = 'contract-confirm'
.create_button= link_to 'Something', new_some_path(#customer), :class => 'btn btn-success', :'data' => #data ? 'contract' : nil
.clearer
So I know this might look strange but I want to set a data attribute if customer is labeled and then hook js to that data attr. That part works. What does not work is that now I'm setting the attribute always. So even in the case that customer does not have the role the js gets hooked. I know that I am not explicitly indicating at all the role here. I have a #customer.role? but I cant seem to incorporate it properply. I managed it before with an if else statement but then with a lot of duplication which I'm not so fund of. Any tips?
You can try this piece of code:
link_to 'Something', ... , :data => #customer.role? ? 'contract' : nil
haml won't include nil attributes, so it should work as you expect.
Try to replace :'data' => #data ? 'contract' : nil with :'data' => 'contract' if #data.
I checked it and next code:
- #data_present = true
= link_to 'Something', root_path, :class => 'btn', :'data' => ('test' if #data_present)
renders to:
Something
And code without - #data_present = true renders to:
Something

How to use an if statement in HAML to control a tag class string?

I have a condition where if action_name contains "index" then the second class should return "index" only, otherwise, set it to action_name.
I was trying something along these lines:
- if action_name =~ /.*index.*/
%body{ :class => "#{controller_name} index" }
- else
%body{ :class => "#{controller_name} #{action_name}" }
Unfortunately I have the remainder of my body in the layout that follows these and it is only displayed for the else clause.
I figure there is a more readable one liner that I could use here as well that would perform an if within the line vs the more verbose multiline if statement, but I could use some help here in terms of gettin this to work as expected in HAML.
Well, here's a one liner:
%body{ :class => "#{controller_name} #{(action_name =~ /.*index.*/) ? 'index' : action_name}" }
Not that readable though!
I'd put a method in a helper. I like to keep logic out of my views.
application_helper.rb
def get_class(name)
"#{controller_name} #{(name =~ /.*index.*/) ? 'index' : name}"
end
view
%body{ :class => get_class action_name }
%body{:class => "#{controller_name} #{(action_name =~ /[index]/) ? 'index' : action_name}" }

Rails 3 - A better way... i'm a newbie!

Please, can you suggest me a better way to accomplish this:
#infos = #activity.infos
#infos.each do |info|
#activity.name = info.title if info.language_id == 1
end
EDIT
In my Rails app contents can be inserted in many languages, but are displayed only in one of them. Other languages are used only as XML output.
However the main cause i'm using this approach is that without a "name" attribute i wouldn't be able to create a collection like this:
<%= collection_select(:event, :activity_id, #activities, :id, :name) %>
Can you suggest me how to accomplish this without a "name" attribute in my Activity?
Thanks!
You can do something like this.
info = #activity.infos.select{|info| info.language_id == 1}.last
#activity.name = info.title
Same as the others but using the ARrel syntax that's available in rails 3.
#activity.name = #activity.infos.where(:language_id => 1).first.title
As the others mentioned ... you might want rethink your design. If you provide more detail on why you are trying to do this we may be able to help with the underlying design that lead to this.
Well, you could lose the iteration...
#activity.name = #activity.infos.find(:first, :conditions => { :language_id => 1 }).title
but that doesn't guarantee you'll get a result (in the real world). So:
info = #activity.infos.find(:first, :conditions => { :language_id => 1 })
#activity.name = info.title unless info.nil?
But as mentioned in the comments this is a strange approach - seems like there's something structurally wrong with your app/data if you're trying to assign a value this way.

How do I create a more meaningful error message in this case?

Say I have the following model:
class Information < ActiveRecord::Base
...
validates_length_of :name, :minimum=>3, :message=>"should be longer than 3 characters!"
...
What I want to have as an error is:
Information should be longer than 3 characters! (or similar)
and NOT "Information name should be longer than 3 characters!".
Two possible workarounds I've looked at:
human_attribute_name method (mentioned here): doesn't work with my Rails 2.3.2. :-(
directly do a information.errors.add "","..." if information.name.length < 3: however, this removes many useful properties triggered by the validated_length_of method like the special class-tags (for coloring the stuff red).
Any ideas? Thank you for your time.
I suppose that you display errors through full_messages method, which is meant for console, not for web application use. You should use error_message_on or error_messages_for helpers instead (see documentation for more info), which allow you to customize error messages.
Example:
<%= error_message_on "information", "name", :prepend_text => 'Information ' %>
don't use the rails helper to make the errors, normally i have inline errors so something like:
def inline_error_block(obj, meth, prepend="", append="", klass="error error-form", &block)
content = capture(&block)
obj = (obj.respond_to?(:errors) ? obj : instance_variable_get("##{obj}"))
if obj
errors = obj.errors.on(meth.to_s)
if errors
output = content_tag(:div, :class => klass) do
content_tag(:p, "#{prepend}#{errors.is_a?(Array) ? errors.first : errors}#{append}", :class => "error-msg clearfix") + content
end
return concat(output)
end
end
concat(content_tag(:div, content, :class => "no-error"))
end
tends to do the trick, but, it only shows one error per form field, am sure you could rearrange it to show them all, should you need to! (errors.first to errors.each).
To get the full name, just write the message with the field name as you want it displayed:
validates_length_of :name, :minimum=>3, :message=>"Information should be longer than 3 characters!"
You could always set your :message to an empty string in the model then set the :prepend_text in the view to whatever you like.

Resources