OK I'm sure I'm missing something here, but please forgive me I'm new to Rails.
Is there some way in Rails to display all the fields for an object rather than specifying each?
In my show.html template rather than going
<p>Name: <%=h #user.full_name %></p>
<p>Email: <%=h #user.email %></p>
I just want a oneliner to do this without having to type out each of the 15 or so fields I have.
Its an admin page so its fine if all the fields are shown (id, created_at, etc.)
If this was PHP it would take me about 5 secs using foreach, but I've googled (on the wrong things obviously) for an hour with no luck.
Thanks!
Something like
<% for attribute in #user.attributes.keys %>
<p><%= attribute.humanize %> <%= #user.attributes[attribute].to_s %></p>
<% end %>
could do the trick.
Matt
I suppose you want to display all attributes of a row from database table which is defined as ActiveRecord model. You can use class method column_names (every ActiveRecord model has it), which returns names of table columns in an array.
<%= User.column_names.collect { |col_name| "#{col_name.capitalize}: <p>#{#user[col_name]}</p>" }.join("\n") %>
<%= debug #user %>
simple way to show the object... that is what I usually use anyway!
#user.attributes.each{|key, value| puts "#{key} : #{value}"}
This is the snippet I used to blacklist some attributes I didn't want to show...
controller (user_controller.rb)
def show
keys_blacklist = %W(user_id name) #these are the fields to hide
#user_showlist = #user.attributes.except(*keys_blacklist)
end
view (show.html.erb):
<!-- language: ruby --><% for attribute in #user_showlist.keys %>
<b><%= attribute.humanize %></b>
<%= #user.attributes[attribute].to_s %>
<!-- language: ruby --><% end %>
You can also use instead:
#user_showlist = #user.attributes.slice(*keys_whitelist)
in order to display a whilelist of properties.
If you are using haml and want to loop through the attributes on for example a user object in a view:
- for attribute in #user.attributes.keys
%p
= attribute.humanize
= #user.attributes[attribute].to_s
Related
I am trying to pass a string to my view from controller like this:
controller:
def index
#str = 'foo'
end
view:
String: <% #str %>
The variable itself seems to arrive because I get no error. However, it arrives empty (only "String" is in html, nothing else). And it seems to work great with other built-in types, e.g. Time. What am I missing here? I use Ruby 2.2.1 and Rails 4.
As others have said, you need to use
<%= #str %>
I'll give you an explanation as well - you use <% %> for when you need to run some Ruby code that you don't want displayed to the screen. For example, you might have conditional logic like
<% if user_signed_in? %>
<%= #welcome_string %>
<% end %>
Use <%= %> when you want to output, drop the '=' for conditional logic or anything that doesn't need to display.
in your view
String: <%= #str %>
In view user following code:
String: <%= #str %>
In your view, use:
<%= #str %>
As the other users have pointed out, you need to use <%=
The = is an ERB flag to so export the result of the code inside of the tags and put it into the DOM.
If you want to put some logic into your page that you don't want to evaluate, you leave the = out.
<% if user_wants_to_see_output? %>
<%= "User will see this" %>
<% end %>
so I have a standard has_many through association in my models, very similar to the question here: Loop through ActiveRecord::Associations::CollectionProxy with each
I used the advice in that problem but I think I am having some trouble getting it through on my ERB file so that it shows up in my app. At the moment I have the following:
<%= #memberships.map do |a| %>
<%=a.name%>
<% end %>
In this scenario, the membership model is the one through which users and organizations have many though (#memberships = #user.organizations). So the #memberships.class returns
ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Organization
on the rails console. So the moment, in the browser the code returns on a page where the user is in two orgs:
orgone orgtwo["\n", "\n"]
I just don't know how to manipulate the proxy classes to return what I want. Thanks!
UPDATE:
I figured it out, I had to remove the = at the top of the block, and I added some styling with a comma:
<% #memberships.map do |a| %>
<h3><%=a.name %> <%= ", " unless a == #memberships.last %></h3>
<% end %>
If you want to print the name of each membership, what you want is
<% #memberships.each do |membership| %>
<%= membership.name %>
<% end -%>
The <% prefix in ERB executes code without appending the results to the output buffer, while the <%= prefix outputs the string representation of the result of the expression. Since each returns an enumerator, a <%= will return the string representation of the enumerator which is something like #<Enumerator:0xDEADBEEF.
Im trying to create a checkbox table of about 20 "interests" that lets the user select as many as they want. I have a Interest & User model with a HABTM relationship (through a "interests_users"join table).
So:
How do i seed the interests table (just has a name:string attribute) with the names of 20 or so pre set interests?
How do i display these in a ERB form allowing the user to select as many as they like?
Note.. Im using the Wicked gem to create a multistep form (<-working great)
If you're on Rails >= 3.0, then have a look the db/seeds.rb file. You get to put arbitrary Ruby code in that file, which you run through the Rake task rake db:seed. You can just put a lot of lines like Interest.create :name => 'World Domination'.
This one is going to depend on how you set up your form. Going off the information you've given, I'd do something like this:
<%= form_for #user do |f| -%>
<% Interest.all.each do |i| -%>
<div><%= i.name -%> <%= check_box_tag 'user[interests][]', i.id, #user.interests.detect{|ui| ui.name == i.name} -%></div>
<% end -%>
<% end -%>
In your controller you would then be able to just update your user model's attributes. Be sure to make sure you are able to mass-assign your parameters, and also keep in mind a limitation of the HTML spec with regard to unchecked checkboxes (read the part titled, "Gotcha").
EDIT: fixed some grammar-related typos.
<% for interest in Interest.find(:all) %>
<%= check_box_tag "user[interest_ids][]", interest.id, #user.interests.include?(interest) %>
<%= interest.name %>
<% end %>
Is it possible to loop over an object's attributes in Rails? I have an object and rather than code up each attribute in the view, I want to output each of them in the view as there are quite a few.
I have an object called #work_profile which has many attributes, mainly boolean check box values.
Edit: I see I can use #work_profile.attributes. Any help on formatting the hash into something more user friendly would be great.
The ActiveRecord::Base.attributes() method returns a hash of all the attributes. You can use that to loop over all attributes.
#work_profile.attributes.each do |attr_name, attr_value|
...
end
In a view, this would give:
<% #work_profile.attributes.each do |attr_name, attr_value| %>
<div class="work_profile_attribute">
<%= attr_name %>: <%= attr_value %>
</div>
<% end %>
Hey! I iterate through a hash with #lists.each do |list|. I create a div in every cycle that must have an id. I would have created a count variable in PHP to get a definite id. What is the best way to do that in a Rails view? Thank you!
Assuming these are ActiveRecord models (ie. from a database), you could just use the dom_id helper, like so:
<% #lists.each do |list| %>
<div id="<%= dom_id(list) %>">
... rest of list ...
</div>
<% end %>
That way each div will get an ID like list_49, with the number corresponding to the ID in the database.
An alternative would be to use the div_for helper:
<% #lists.each do |list| %>
<% div_for(list) do %>
... content in div ...
<% end %>
<% end %>
That will add the same format of id as Luke's suggestion. Be aware though that it would also add a class attribute of list. You can add additional classes by passing in :class => 'my-class'.
Why don't you just take the id of the list? Or must the id be any kind of "globally unique"?
Update: I think you should go with luke's answer.