Passing a link into view - ruby-on-rails-3

In Ruby on Rails 3 How would I create a view that decides by a parameter what link in view links to?
For example to a page in my view I pass a type parameter which displays all projects in my data base and depending on the type links to either the new show or edit action.
I am interested in only passing on the path of the link.
I would like to write something like:
<% link_to(enter_here_path) do %>
<div class="blah"><%=#project%></div>
<%end%>

You could use a conditional which returns the proper location or even creates the link, probably best wrapped in a helper method.
Something like that:
def your_link_method(type="delete")
case type
when "delete"
link_to …
when "foobar"
link_to …
else
link_to …
end
end
end
As a sidenote: This kind of construct smells IMO and I'd probably rethink my design first, before I implement a solution like this. Even if you can probably find a simpler and more elegant way to write it.

Related

ActiveRecord "select" results of model method

I have a Rails app that pulls in music from Soundcloud. This data contains a title, which I save as mix.sc_title but it's not always properly formatted. I have added an additional attribute on my Mix model which I call mix.override_title
For display on my site, I want to use the override title if available, and the sc_title in all other cases.
I have a Mix model method to do this for me
def display_title
override_title.blank? sc_title : override_title
end
Mixes#index grabs #mixes = Mix.where(:active => true) and mixes/index.html.erb looks like this:
<ul>
<% #mixes.each do |mix| %>
<li><%= link_to mix.display_title, mix %></li>
<% end %>
</ul>
As you can see, I'm not directly using any mix attributes, and so I take a huge hit when I go to the DB, and I don't actually benefit from it.
Is there a leaner way to get just the information I need? (mix.display_title)
I have tried Mix.select("display_title").where(:active => true) but it fails because display_title is not a real DB column
You can do Mix.select("sc_title, override_title").where(:active => true) and it will work, since those are the actual fields that the method uses. I don't really think getting the additional attributes gives you that much of a DB hit but sometimes selecting only what you need can be beneficial.
As you start chaining on more Arel commands, consider putting the select into a model method:
def select_active_titles
select("sc_title, override_title").where(:active => true)
end
Edit: Your link_to helper also secretly calls mix.id to link to the right mix, so make sure it's working and if not add id to the list of selected attributes.

Checking if a nested model attribute is true

So I have one model called Project, for which there is a nested model called Proposal (so every project has multiple proposals, and each proposal only belongs to one Project).
I have a column for Proposal called "winning" which just checks if one of the Proposals has won for the Project. I'd like to reference this on the Show page of the Project, but a little perplexed by the code.
What I really want to do is check if any of the proposals have status "winning"
This is what I'm trying for the Show view for Projects, but it isn't working:
<% if #project.proposals.winning %>
SUCCESSFUL
<% end %>
I feel like this should be pretty rudimentary but I'm having trouble figuring it out, thanks!
That's ideal candidate for:
<% if #idea.proposals.any? {|proposal| proposal.winning? } %>
Enumerable.any? returns true if for any array element the block returns true.
Use it instead:
<% if #idea.proposals.count{|a| a.winning } > 0 %>
Or even better to create a method for it in the Idea model:
def has_winning?
proposals.count{|a| a.winning } > 0
end
Okay, found this code on another post and it seems to be working, not sure if it's the best way to go about it though:
<% if #idea.proposals.map(&:winning).flatten %>

Correct way to share a view in the index page

I'm a Ruby-on-Rails newbie, just starting out.
I have an MVC called "account_types", generated via scaffold to produce:
controllers/account_types_controller.rb
helpers/account_types_helper.rb
models/account_type.rb
views/account_types/_form, edit, index etc...
Going to localhost:3000/account_types gives me the index view.
What I'd like to do is display the same data as selected from the account_types index method in the application index page as a list.
I wrote a new view called account_types/_list.html_erb as follows:
<ul>
<% #account_types.each do |account| %>
<li><% account.label %></li>
<% end %>
</ul>
I then edited home/index.html.erb (This is based on examples given in other questions on SO):
<%= render :partial => 'account_types/list', :module_types => #module_types %>
However I get
undefined method `each' for nil:NilClass
and the error displays the code from account_types/_list.html.erb where I've written
<% #account_types.each do |account| %>
The scaffolded views work fine, why aren't mine?
Are partials the right thing to use here?
Thanks in advance.
What is the correct way to define an application-wide partial and its variables in rails says to use a before_filter on ApplicationController.
You pass :module_types to partial, but use account_types. As I can see you just need to change your index.html.erb to:
<%= render :partial => 'account_types/list', :account_types => #module_types %>
You can use partials for this if you want, though it would be unnecessary in this case as far as I can tell (they are for sharing chunks of code between several views). In order to get this code to work you'll need to define #account_types in your controller with something like
#account_types = AccountType.all
You can see exact line in your account_types_controller.rb under index action. :module_types => #module_types is not necessary here, since I doubt you defined #module_types either and you don't use module_types in your partial at all.
It's obvious, that you don't understand how Rails works, so I suggest reading through a good tutorial (like this one) before you proceed with whatever you have in mind.

How to use to_sentence with an AR collection

I have User.all, which returns 3 results.
How can I make it so I can render each result to something like:
Foo, Bar, and Foobar
Which when rendered in the browser, will display as:
Foo, Bar, and Foobar
I know about the to_sentence helper. But not very sure how to execute this, since User.all returns 3 hash objects. I can use .map(&:first_name), but how will I be able to provide the route path in the link_to method.
Looking for an approach that works.
I think you're looking for something like this. (answer updated)
In a helper:
module ApplicationHelper
...
include ActionController::UrlWriter
def generate_user_links_sentence
links = User.all.collect do |user|
link_to user.first_name, user_path(user)
end
links.to_sentence
end
...
end
# Example: <%= generate_user_links_sentence %>
You can separate out the generation logic into your controller if you so wish, but it's difficult enough accessing route paths from a helper, let alone the controller. There may be a better way to do this in a view, but this is all I can really think of right now.
Update: Just in a view:
<%= User.all.collect{|u| link_to u.first_name, user_path(u)}.to_sentence %>

How can I use the 'unless' keyword in a view?

Can anyone tell me if there's a Rail3 replacement for something like this:
<%= unless #page.new_record? || !#page.background_image? %>
bla
<% end %>
I'm trying to display a checkbox on a form only when a user edits. Not when they create.
I think the statement is ok, but should not be included in your view. Instead, create a model method, probably named is_editable? or something, that includes this statement. Then get an instance variable in your controller and use that instead.
Logic in views is a very bad idea :)
Your mistake is including the = in the ruby code.
<% unless #page.new_record? || !#page.background_image? %>
bla
<% end %>
However, as other users have stated, it is probably better to hide this logic in the model rather than in the view. Additionally it considered a best practice to only use unless if there is only one boolean statement. It starts to get harder and harder to read when you have ors and nots included there.
<% if #page.is_editable %>
blah
<% end %>
This would be a nicer version, and even better than that (depending on how complicated 'blah' is) would be to hide the whole thing in a helper method.
<%= some_special_checkbox(f) %>
The parameter f would be the form object so that your helper can render the checkbox for the form.
You can write it like this:
<%= "bla" unless #page.new_record? || !#page.background_image? %>
May be you should write separate method with more human-readable name and replace this condition with one method. Try to keep your view as much cleaner as possible