I have this code in controller:
array = ["asd", "asd", "asd"]
#print = array.each do |i|
puts "Random text #{i}"
end
And now I want to print it in some pages view like show.html.erb:
<%= #print >
And I get this: ["asd", "asd", "asd"] But In controller I sayd to puts each object in array, but it is not doing it?
The puts method is for printing a string to the console. If you wanted to set each of the values of the array to a certain value in order to print it out later, you should use #map.
array = ['asd', 'asd', 'asd']
#print = array.map { |i| "Random text #{i}" }
Now, in your corresponding view, you should add:
<% #print.each do |val| %>
<%= val %>
<% end %>
puts prints to the stdout (standard output) that, in the majority of cases, corresponds to the console where you started the Rails server.
Check the console and you will find, in the middle of the request logs, also the result of the puts statement.
A better way to print out something from the console is to use the Rails logger, especially if you want such output to be logged in the logs in production.
Rails.logger.info "message"
Assuming it's just for debugging purpose, then it's fine to use puts (or p).
You should be doing the looping in your view. This helps maintain the separation between your application logic and your view code.
Controller
#array = ["asd", "asd", "asd"]
View
<% #array.each do |i|
<%= i %> # No need to use the puts method here
<% end %>
it seems that the variable #print is the array. The controller is run once per load of the page and then will output its contents at the end to the view. Plus, "puts" is for printing a string to the console. You should put the loop in question in the view like this:
<% #array.each do |i| %>
<%= i #>
<% end %>
Related
I have a text field that user's put in data that I'm converting to list items. So they may enter in the text area:
Apple
Tomato
Wrench
So I have the following that works:
<% regional_services = #region.services.split("\n") %>
<ul>
<%regional_services.each do |services| %>
<li><%=services%></li>
<%end%>
</ul>
It outputs correctly with something like
Apple
Tomato
Wrench
But I'm trying to get it to work in a helper instead since it's ugly in the view.
So I have the following:
def other_service
if #region.services.present?
something = #region.services.split("\r\n")
content_tag(:ul) do
content_tag(:li, something.each {|alpha| alpha })
end
else
content_tag(:p, 'Here is text')
end
end
It ends up outputting like:
["Apple", "Tomato", "Wrench"]
So it looks like it's not applying the iteration on the list item so I tried the following:
def other_service
if #region.services.present?
regional_service = #region.services.split("\n")
content_tag(:ul) do
regional_service.each do |service|
content_tag(:li, service)
end
end
else
content_tag(:p, 'Here is text')
end
end
No error but it's actually not displaying anything on the pages that actually have items. So how do I do a content_tag ul with an iteration?
each returns the array, so the block of content_tag :ul is going to receive an array itself as an inner HTML. Which is apparently not what you wanted.
In order to add HTML to an output buffer, you would use concat:
content_tag :ul do
regional_service.each do |service|
concat content_tag(:li, service)
end
end
I am trying to compare the names of the element at the current index and the previous index for each element to determine if they are the same name so I don't print out the name twice.
Unfortunately, trying to access the array element using array[i] doesn't work, but if I hard-code an index or just print out the index, it works fine so I'm not sure where it's messing up.
I need to be able to access the previous element though so I can't use other loops so only suggest something where I can access the previous element in the array.
<% for i in 1..count %>
<% if array[i].count > 1 %>
<% if array[i-1].name == array[i].name %>
<%= array[i].name %>
<%= array[7].name %>
<%= i %>
<% end %>
<% end %>
Does anyone know the correct way to access an element in an array?
This should do it if your list is sorted and all you care about is printing names:
<% array.map(&:name).uniq.each do |name| %>
<%= name %>
<% end %>
More generally, you can do it like this:
array.each_with_index do |el, i|
prev_el = array[i-1] #will be nil for the first element
next_el = array[i+1] #will be nil for the last element
if prev_el && el.name == prev_el.name
#name same as previous
end
if next_el && el.name == next_el.name
#name same as next
end
end
You should avoid index-based array access for loops, not because they don't work but because there are much nicer and more readable ways of looping through arrays in Ruby.
You can keep in mind that you are using Ruby, and the motto of Ruby is "Do More in Less Work".
You can use uniq to filter out all similar elements, then iterate through them to do whatever you want to do. uniq works like this:
a = [ "a", "a", "b", "b", "c" ]
a.uniq # => ["a", "b", "c"]
This should do it all what you tried to do:
<% array.uniq.each do |obj| %>
<%= obj.name %>
<% end %>
Just thought of another way of doing this:
grouped = array.group_by(&:name)
Now you have a hash where each key is a unique name and the corresponding value is all the array elements with that name. So next you can do stuff like
#list of names in alphabetical order
grouped.keys.sort
#get one element for each unique name
grouped.map{|name,els| els.first}
#print out how many you have for each name
grouped.each{|name, els| puts "#{name.inspect} => #{els.size} elements"};false
Let's say I've got the variable #var. Usually I would use <%= #var %> to write it into the view. Now I want to call a module method from within my view which internally decides to write the content of #var or not.
Inside the module I can't use <%= %>. How can I print the content of #var from within the module? The method would be called like this: <% my_method %>. Thanks
Update
Thanks for the answers so far. Maybe I should say more about my initial problem to be more clear. Sorry if I wasn't clear enough.
At first I used the <%= %> tag like this:
def print_if_present(var)
var ? var : ""
end
<%= print_if_present var %>
But then, when the var was nil, I got "" as output, which took space in the view. How can I prevent this behavior?
I assume that your module is actualy the view helper. If is that so, simply return var.
def my_method
if my_condition
#var
else # else clause is optional
#other_var
end
end
Note that the else clause is optional. If you want to write something or nothing, you can simply use the if. This is so because if the if is not executed and there is no else, it will return nil, that will be casted to an empty string in your template. Just to ilustrate,
if true
1
end
=> 1 #return if last value
if false
1
end
=> nil # return nil because there is no else block
Since you still want to print the return of your method on your template, you need to keep the equal sign:
<%= my_method %>
The best way to do this is to have your method return the string and use <%= ... %> as in fotanus’ answer, but in Rails if you really need to write output directly from a helper you could use the concat method:
The preferred method of outputting text in your views is to use the <%= “text” %> eRuby syntax. The regular puts and print methods do not operate as expected in an eRuby code block. If you absolutely must output text within a non-output code block (i.e., <% %>), you can use the concat method.
So you can define a helper like this:
def my_method
if some_condition
concat "Something or other"
else
concat "Something else"
end
end
And then use it in a non-output block:
<% my_method %>
I am building a prototype of a education application using Rails 3, omniauth and the facebook graph api. So when a User log in to my application he uses his facebook account, I grab all his education history and his friends education_history.
I would like to group every User friends education likes this:
I have tried something like this:
<ul class="friends-list">
<%= current_user.friends.group_by(&:highschool_name) do |highschool_name|
p "<li>#{highschool_name}</li>"
end
%>
</ul>
And I get a syntax error.
The User tabel look like this:
[id, name, image, location, highschool_name, highschool_year, college_name, college_year, graduteschool_name, graduate_year ]
And the Friend tabel looks like this:
[id, uid, name, image, higschool_name, college_name, graduateschool_name, user_id]
How do solve my problem using active record, without loops because their are not effectivity.. right?
You can't use p or puts in ERB files. Think of ERB files as one big string concatenated together. Like "string 1" + "string 2" + "string 3".
That's all ERB does - it just pastes strings together into one big string. You can't call puts inside this concatenation operation. So everything in the ERB file needs to be a string. The output from a puts call just 'goes up in smoke' since a puts call does not return a string, it writes to stdout instead.
Next we look at group_by: it returns a Hash:
---------------------------------------------------- Enumerable#group_by
enum.group_by {| obj | block } => a_hash
------------------------------------------------------------------------
Returns a hash, which keys are evaluated result from the block,
and values are arrays of elements in enum corresponding to the key.
(1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
So putting everything together we could do something like this:
<% current_user.friends.group_by(&:highschool_name).each do |hsname, friends| %>
<% next if hsname.blank? %>
<li><%= hsname %></li>
<% friends.each do |friend| %>
<%= image_tag(friend.img_url) %> # <- Or wherever you get the img url from
<% end %>
<% end %>
When I'm in irb and I do something like this:
node_list.each_element { |e| puts e.text }
It works and prints one line of text per element returned (plus I think it returns the xml object). However, when I head over to rails and have things moving between controllers, helpers, views and layouts it just dumps the xml object.
I should mention that for good reasons I'm using rails 1.2.3 and ruby 1.8.7.
Gratzi!
So the issue your having is that puts writes to console and not the template. Also, in ruby the a method will return by default its last object. So your method as written will loop through #child1, print each's text to the console, and then return the #child1 object at which point your erb tags of <%= %> tells it print the object (#child1 in this case)
You have two options, either you can move it out into the template:
<% tol_get_names(#child1) do |e| %> #note just <% and not <%=
<%= e.text %>
<% end %>
Or build your method so that it loops through building a string and then returns that string instead of the original object:
def tol_get_names(child)
texts = [] #empty array for all our values
child.each_element { |e|
texts << e.text #add the text string to our array
end
texts.join(", ") #build a string and seperate it with a comma
end
Several ways you could write this type of method, but this is my usual way.