passing a hash to a route in rails - ruby-on-rails

In the preview action in my controller, I have
#models = Model.all
In the view, Im trying to loop through all the models, draw out their associated images, and use those to link_to their own profiles.
<% #models.each do |m| %>
<div> <%= link_to(image_tag (m.avatar.url(:thumb)), model_path())%> </div>
<% end %>
I need to pass in the id of each model to the route. Using m.id doesn't work because the route is expecting a hash.
Not entirely sure how to do this. Other posts on SO refer to unsaved instances and such, which aren't really relevant to this.

Try changing your view code from this:
<% #models.each do |m| %>
<div> <%= link_to(image_tag (m.avatar.url(:thumb)), model_path())%> </div>
<% end %>
To:
<% #models.each do |m| %>
<div> <%= link_to(image_tag(m.avatar.url(:thumb)), model_path(m))%> </div>
<% end %>

As usual the error might be in a completely different place - your brackets.
model_path can accept both list of attributes and a hash. Most likely you think it is expecting a hash due to the error message (which you should include in the question). In fact however, you are passing the path to the image_tag, not to the link_to:
link_to(image_tag (m.avatar.url(:thumb)), model_path())
is parsed as
link_to( image_tag(m.avatar.url(:thumb), model_path()) )
While:
link_to(image_tag (m.avatar.url(:thumb)), model_path())
is parsed as
link_to( image_tag(m.avatar.url(:thumb)), model_path() )
This space between a method name and a bracket is a silent killer. It is a image_tag which is expecting a hash in a second argument. :)
That being said - it will still not work, but you should get a different problem now.

Related

Ruby on Rails: Store array value in variable and use as string

I'm in the process of refactoring some code. I'm trying to use arrays in my view as part of a for loop that makes columns in a table.
I have defined the arrays in my controller:
subjects_controller.rb
def index
...
#CRFS_TO_VIEW = [Baseline, TreatmentCompletion]
#CRF_PATH = {Baseline => 'baseline_path', TreatmentCompletion => tc_path}
end
So my goal; as the function iterates over #CRFS_TO_VIEW, the correct path is selected from #CRF_PATH and appended to the link_to function.
indext.html.erb
<% #CRFS_TO_VIEW.each do |crf| %>
<% path = #CRF_PATH[crf] %>
<%= link_to "edit", path(crf.where(subject_id: sub.subject_id).first %>
<% end %>
I also tried :
<%= link_to "edit", #CRF_PATH[crf](crf.where(subject_id: sub.subject_id).first %>
Which didn't work. I feel I must be getting close, any help or insight would be greatly appreciated.
Thanks.
A few things:
a. You should save yourself some time and loop through the dictionary instead of the array:
<% #CRF_PATH.each do |crf, path| %>
...
<% end %>
b. You are getting a string from the loop - you can invoke the equivalent method with send:
<%= send(path, ...) %>
c. You can simplify your retrieval of the objects using:
crf.find_by(subject_id: sub.subject_id)
That said - this seems like a pretty bad way of doing things. I'd recommend instead adding a view helper:
def crf_path(crf)
case crf
when Baseline then baseline_path(crf)
...
end
With something like this you could use (notice changed the find_by to find_by! for safety as well):
<% #CRFS_TO_VIEW.each do |crf| %>
<%= link_to "edit", crf_path(crf.find_by!(subject_id: sub.subject_id) %>
<% end %>
Finally instance variables should NOT be named upper case. If you want to use a constant define it as a constant (otherwise use lower case names).

How to check if an array index exists using Ruby and/or Rails

Is there a Ruby (preferably) or Rails way to check if the second index of an array exists?
In my Rails (4.2.6) app I have the following code in my view that shows the first two thumbnails for an array of photos:
<% if array.photos.any? %>
<%= image_tag array.photos.first.image.url(:thumb) %>
<%= image_tag array.photos[1].image.url(:thumb) %>
<% end %>
However if there is no second item in the array, then there is an error
I've tried the following if statements to make the rendering of the second thumbnail conditional, but they don't work:
<% if array.photos.include?(1) %>
<% if array.photos.second? %>
<% if array.photos[1]? %>
<% if array.photos[1].any? %>
I figured that another way to get what I want would be to simply check the length of the array
Still I was wondering if Ruby (or Rails) had a method or way to check if a specific index in an array exists or not. Thanks in advance
EDIT: To clarify I just want to show the first two thumbnails in the array, if any
You can use an .each, but if you want to follow this approach.
Instead of this:
<%= image_tag array.photos[1].image.url(:thumb) %>
Maybe you can use this:
<%= if(!array.photos[1].nil?) image_tag array.photos[1].image.url(:thumb) %>
Or:
<%= image_tag array.photos[1].image.url(:thumb) unless array.photos[1].nil? %>
Here, why not
(0...array.photos.size).each do |photo|
......
end
array.photos.each do |photo|
......
end

How to return ActiveRecord Association Proxy on ERB

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.

What's the cleanest way to add a class attribute to an html element in a view in rails

I'm writing some Rails code for a partial view, and I want it to only show a comment field if somebody is already logged onto a site here.
If the page is viewed by someone who isn't a member of the site yet, the shared/comment_not_logged_in fragment should be passed in.
However, I'm totally stumped as to why I can't run the same check to decide if the page should add the class attribute "missing_your_voice" to the enclosing div element here:
<li class="user_submission_form bubble comment_form <% "missing_your_voice" if not current_user %>">
<% if current_user %>
<%= image_tag(current_user.avatar(:comment), :class => "profile_pic") %>
<% form_for [parent, Comment.new] do |f| %>
<%= render "comments/form", :f => f %>
<% end %>
<% else %>
<%= render :partial => 'shared/comment_not_logged_in' %>
<% end %>
</li>
The same idiom, "missing_your_voice" if not current_user returns the string in irb, and also in the console debugger.
What am I doing wrong here?
You forgot an =. Replace <% by <%=, so that you get:
<%= "missing_your_voice" if not current_user %>
Remember that <% ... %> will only run Ruby code, but not display anything. Using <%= ... %> will run the code and display the result of the expression.
As molf already pointed out, there's a missing = on your view.
It should be <%=.
Other than that, be sure to make your controller method available to your view by calling helper_method in your controller.
Take a look on the documentation if needed.

Rails 'params' variable

In reference to this
I've created a question in a webform like this:
<div class="form_row">
<label for="features[]">Features:</label>
<% [ 'scenarios', 'role_profiles', 'private_messages', 'polls' ].each do |feature| %>
<br><%= check_box_tag 'features[]', feature,
(params[:features] || {}).include?(feature) %>
<% end %>
</div>
So if scenarios and private_messages gets checked and I print out params[:features] I will get:
scenariosprivate_messages
I was wondering how would I be able to obtain scenarios and private_messages separately from params. Is the mapping params[:features] = "scenariosprivate_messages" or is it really params[features] = ["scenarios", "private_messages"] ? If it's the latter how can I loop through them?
I write in my view:
<%= params[:features].each {|param|
param.capitalize
} %>
and I still just get scenariosprivate_messages printed.
Try this instead:
<% params[:features].each do |param| %>
<%= param.capitalize %>
<% end %>
The problem with your original solution is that you're printing out the result of the block, which is the array itself, rather than printing out each element of the array.
You shouldn't be using params in your views. You're best off assigning params[:features] to an instance variable in your controller and then iterating over that in your view.
But to answer your question, you're putting the equals sign for output in the wrong place. You want to output each element of the array individually instead of outputting the result of the loop.
You must use humanize:
<% params[:features].each do |param| %>
<%= param.humanize %>
<% end %>
According to this blog post you should be able to access them individually as params[:features]['scenarios'] etc. Looping should just work like with all other arrays -- eg
params[:features].each { |param|
# do something with param
}

Resources