Arel
Arel

Reputation: 3938

Getting text to show up if a condition is true

I'm trying to get the text "Tags:" to show up only if tags are present, so I did the following in my view:

<% if @tags.present? %>  
    <%= puts "Tags:"%> 
    <% end %>

Which doesn't work... I'm a beginner, and have no idea what I'm doing wrong.

Thanks

EDIT:

A tag belongs to an Article.

Tags is defined in my Article model as:

def tag_tokens
    self.tags.collect{|t| t.name}.join(", ")
  end

  def tag_tokens=(tags_delimited)
    tags_delimited.split(",").each do |string|
            self.article_tags.build(:tag => Tag.find_or_create_by_name(string.strip.downcase))
    end     
  end

I'm trying to make it so that when an article has tags the word "Tags:" shows up before the list of tags, and when an article doesn't have any tags, the word "Tags:" doesn't show up.

Right now <% if @tags.nil %> just causes "Tags:" to show up on every post.

Upvotes: 0

Views: 1757

Answers (3)

severin
severin

Reputation: 10258

Check the answer by sgrif, it contains a lot of good points. To just answer your main question:

In erb (the "language" used for view templates in Rails) you can use <%= ... %> to interpolate the result of some Ruby code into your view template.

When you are doing:

<%= puts "Tags:" %>

the following happens:

  1. Ruby evaluates/executes your code: "Tags: " is printed to STDOUT and nil is returned since a call to puts alsways returns nil
  2. erb interpolates the result into your template, the result is nil, which shows up as "nothing"

To fix it, just use:

<% if @tags.present? %>  
  <%= "Tags:"%> 
<% end %>

or, since you are not doing anything in Ruby, you can just use:

<% if @tags.present? %>  
  Tags: 
<% end %>

Upvotes: 1

sgrif
sgrif

Reputation: 3822

You don't use puts in views -- puts causes the text to go to your console. This will fix it:

<% if @tags.present? %>  
    <%= "Tags:"%> 
<% end %>

You also don't need to use .present? by the sound of it. If you only want to see if it's been set, you should use .nil? instead. You can also condense this down to a single line.

<%= "Tags:" unless @tags.nil? %>

UPDATE: It looks like the tag_tokens method is broken for you in both the getter and setter. Your setter isn't actually saving anything by the looks of it (.build returns a new object, you need to save it). Your getter is also referencing tags, instead of article_tags which is what you're trying to save by the looks of it. Changing it to this should work for saving:

self.article_tags.build(:tag => Tag.find_or_create_by_name(string.strip.downcase)).save

This is assuming that you have a line that is something like:

has_many :article_tags
has_many :tags, through: :article_tags

Which I'm assuming you do based on your setter.

I assume this is a many-to-many relationship, but it looks like you're using has_many :through, rather than has_and_belongs_to_many. Is there a reason for this? If you're using has_and_belongs_to_many you should be able to do this:

has_and_belongs_to_many :tags

def tag_tokens=(tags_delimited)
  self.tags = []
  tags_delimited.split(",").each do |string|
    self.tags << Tag.find_or_create_by_name(name: string)
  end
end

If you do that, you should not have an ArticleTags model at all, and you should have a table called articles_tags with no primary column, and an article_id and tag_id column.

Update 2:

You're not setting @tags to anything, which is why it's always nil. @tags is a variable, which needs to be set to have a value just like @articles is being set in your controller's index method. Regardless, since this is for an index method, you wouldn't want it to be a single instance variable regardless. You should be accessing your tag_tokens method for that particular instance. app/views/articles/index.html.erb lines 53-55 should be changed to this:

<%= "Tags:" if article.tags.any? %>

Upvotes: 4

Nicholas Albion
Nicholas Albion

Reputation: 3284

What has @tags been defined as? Where do you want to check if it is present?

Do you want if @tags.nil?

Upvotes: 0

Related Questions