Using link_to with an instance variable and arguments - ruby-on-rails

I am trying to render a comments partial to use with both the blog and video models. Here's the blog show page asking for the comments partial and passing #blog as the model (I will pass #video on the video's show page):
<%= render :partial => 'comments/comments', :locals => {:model => #blog} %>
This next code is to order the comments as newest first/oldest first:
<% if #comments.count > 1 %>
<span class="list_order">
<%= link_to('Newest First', model, :order => "DESC", :anchor => "comments") + " | " +
link_to('Oldest First', model, :order => "ASC", :anchor => "comments") %>
</span>
<% end -%>
This works fine when I say:
link_to('Newest First', blog_path(#blog, :order => "DESC".... etc.)
But I know that you can also just pass:
link_to('Newest First', #blog)
and it will automatically go to the blog show page. So in my code, I'm passing the "model" local, and it does refresh the page, but it does not take my argument for :order or :anchor. How do you pass arguments when using only the instance variable rather than the path on the link_to method?

Ok, I finally got the chance to ask a friend of mine and found the solution. I needed to use polymorphic paths. So in my example above, the following code works:
<%= link_to('Newest First', polymorphic_path(model, :order => "DESC", :anchor => "comments") + " | " + link_to('Oldest First', polymorphic_path(model, :order => "ASC", :anchor => "comments") %>
Then it knows to generate the right path for the variable used. Here's some info on that:
http://apidock.com/rails/ActionDispatch/Routing/PolymorphicRoutes/polymorphic_path

Related

Ruby on Rails new objects in partial identifier stops at 1

I have Article(s), that has_many ArticleAssets. Fairly simple. On the edit form for the Article I just want to add new article assets. I don't need to edit the current ones, so I created a partial like this:
<% f.fields_for :article_assets, article_asset do |builder| -%>
<div class="article_asset">
<%= builder.file_field :image %>
<%= builder.check_box :is_flagged, :class => "isFlagged" %> isFlagged
</div>
<% end -%>
No collection, because I only need one object at a time and need no data from the existing article assets. In the form of edit.erb I render the following:
<%= render :partial => 'article_asset', :locals => {:f => f}, :object => ArticleAsset.new %>
This makes one new article asset show up that I can add information to, all cool so far. Important is that this field gets the name-form of article[article_assets_attributes][0][is_flagged]. All good since this will also group the hidden field that always comes with a checkbox in rails to the rest of the fields. Then I have an "Add item" link that does this:
page.insert_html :bottom, :article_assets_fields, :partial => "article_asset", :locals => {:f => f}, :object => ArticleAsset.new
Clicking on this link gives a new field under the created one, as expected, with the name-form of the checkbox field of article[article_assets_attributes][1][is_flagged]. Incremented, that's perfect! Adding another one with the same link however, also gives the same form (also with the identifier of 1, duplicate), which makes submitting the form only have 2 items instead of 3. Does anyone know why this happens and what I can do to solve it?
Ruby on Rails 2.3.11
Nested form 2.3 fail. This one was the bane of my existence for some time, even having watched the railscast etc. Here's my how to:
1) this goes in article.rb
after_update :save_article_assets
def new_article_asset_attributes=(article_asset_attributes)
article_asset_attributes.each do |attributes|
article_assets.build(attributes)
end
end
def existing_article_asset_attributes=(article_asset_attributes)
article_assets.reject(&:new_record?).each do |article_asset|
attributes = article_asset_attributes[article_asset.id.to_s]
if attributes
article_asset.attributes = attributes
else
article_assets.delete(article_asset)
end
end
end
def save_article_assets
article_assets.each do |article_asset|
article_asset.save(false)
end
end
2) In a helper somewhere:
def add_article_asset_link(name)
button_to_function name, :class => "new_green_btn" do |page|
page.insert_html :bottom, :article_assets, :partial => "article_asset", :object => ArticleAsset.new()
end
end
def fields_for_article_asset(article_asset, &block)
prefix = article_asset.new_record? ? 'new' : 'existing'
fields_for("article[#{prefix}_article_asset_attributes][]", article_asset, &block)
end
3) in your partial:
<% fields_for_article_asset(article_asset) do |aa| %>
<tr class="article_asset">
<td><%= aa.text_field :foo %></td>
<td><%= link_to_function "remove", "$(this).up('.article_asset').remove()" %></td>
</tr>
<% end %>
4) in the _form:
<table>
<%= render :partial => "article_asset", :collection => #article.article_assets %>
</table>
<%= add_article_asset_link "Add asset" %>

Rendering an Edit partial while selected a defaulted value

I have a partial in my rails app that loads the vote form (It's just a select with numbers ranging from 1-5). I'm now making another partial that loads up if the user has already voted it's suppose to be an EDIt partial where you get selected the value that you voted and if you wanted to you could change it. But for some reason is not working, here's the code for it.
#Finds the vote by passing the user and the article
<%= #vote = Vote.find_vote_by(current_user,#article) %>
#Renders the partial with the vote variable loaded up with the vote that was found
<%= render :partial => "votes/edit_vote", :locals => {:vote => #vote} %>
And this is the partial
<% form_for(vote, :url => {:controller => 'votes', :action => 'edit'}) do |f| %>
<%= error_messages_for :vote %>
<p><%= f.hidden_field :article_id %></p>
<p>
<%= f.label :value, "Value for the vote: "%>
<%= f.select :value, {"1" => "1","2" => "2","3" => "3","4" => "4", "5" => "5"}, :selected => vote.value %>
</p>
<p>
<%= f.submit "Cloud-it!" %>
</p>
<% end %>
But for some reason the vote variable is not containing anything not the article_id, nor the value method, any ideas?
EDIT1: Per request here's what's debug #vote is outputting (It it indeed a sane value)
attributes:
created_at: 2010-09-02 14:39:04
updated_at: 2010-09-02 14:39:04
id: 1
value: 4
article_id: 1
user_id: 1
attributes_cache: {}
EDIT2
I tried clearing the partial code, in order to output this:
<%= debug #vote%>
<%= #vote.value %>
If i debug #vote it comes out perfect, will all the attributes and such. But whenever i add the second line it, It's not working it tells me that there's no .value, i tried .id, .article and nothing is as if it didn't exist. Any ideas?
EDIT3
Here's the vote by
named_scope :find_vote_by, lambda {|user,article| {:conditions => {:user_id => user, :article_id => article}}}
The reason behind it, it's that named scopes actually return named scopes, and you can't access the attributes just like it were a Vote class. I fixed this by changing the way to retrieve the vote and just forgetting about using that named scope. I accomplished it by using:
<% #vote = current_user.votes.find_by_article_id(#article)%>
which is a Rails method and actually returns a vote class. Then i just passed it to the partial and the magic worked!
Thank you so much to thenduks, without his help i couldn't had done it.
So first thing to fix is this line:
<%= #vote = Vote.find_vote_by(current_user,#article) %>
Should be:
<% #vote = Vote.find_vote_by(current_user,#article) %>
The former is for outputting in ERB and the latter is for executing arbitrary ruby code.
Next, put a line below that like so:
<%= debug #vote %>
And make sure it's a sane value. If not, paste the definition of your Vote class method find_vote_by.
EDIT: In that case it's probably just because using :locals => {...} makes instance variables, so you want #vote in your partial with the form.

Simple link_to_remote function - can't get it to work

After utilizing the great trial and error for over an hour along with dozens of tutorials and blogs posting examples, I still cannot get the simple ajax functionality to work. Here is what is in my partial:
<span id="friend">
<%= link_to_remote image_submit_tag("/images/add_as_friend.gif"), :url => {:controller => 'friends', :action => 'add', :id => id} %>
</span>
This is what is in my controller:
class FriendsController < ApplicationController
def add
unless params[:id].nil?
Friend.create(:user_id => #current_user.id, :friend_id => params[:id], :friend_type => 2)
end
end
end
This is what is in my add.rjs file:
page.replace_html 'friend', "A request to be friends with this player has been sent."
The image for the link comes up fine. When I click on it, however, nothing happens. I've checked the database and nothing is going on. I must be missing something, any thoughts?
It may be because you are using image_submit_tag rather than image_tag for the content of your link. image_submit_tag is for submitting forms so will have its own onclick behaviour which may override the onclick behaviour that will be added as part of the link_to_remote functionality.
I would try:
<%= link_to_remote image_tag("/images/add_as_friend.gif"),
:url => {:controller => 'friends', :action => 'add', :id => id} %>

Ajax observe_field not working on ruby on rails

I am trying to create some kind of search in my ruby on rails application and I want to add ajax support. I want when a user types in a search box a word, ajax automatically generates the results. And I have searched almost all internet and I couldn't find answer to following question:
When I type into my text area nothing happens. It is like ajax is not working at all.
Tre problem is in observe_field which should observe my id= 'query' but it seem like it not doing anything
I am using Prototype 1.6.1 and the newest version of rails.
The code I wrote is:
viewer:
<form name="sform" action="" style="display:inline;">
<label for="item_name">Filter on Property No : </label>
<%= text_field_tag(:query, params['query'], :size => 10, :id => 'query' ) %>
</form>
<%= image_tag("/images/system/blue_small.gif",
:align => "absmiddle",
:border => 0,
:id => "spinner",
:style =>"display: none;" ) %>
</p>
<%= observe_field 'query', :frequency => 1,
:update => 'table',
:before => "$('#spinner').show()",
:success => "$('#spinner').hide()",
:url => {:action => 'list'},
:with => 'query' %>
<div id="table">
<%= render :partial => "items_list" %>
</div>
And my controler is:
def list
sort = case params['sort']
when "Title" then "title"
when "address" then "address"
when "close date" then "close_date"
when "property_no_reverse" then "property_no DESC"
when "address_reverse" then "address DESC"
when "close_date_reverse" then "close_date DESC"
end
conditions = ["title LIKE ?", "%#{params[:query]}%"] unless params[:query].nil?
#total = Message.count(:conditions => conditions)
#accounts = Message.paginate :page => params[:page], :per_page => 10, :order => sort, :conditions => conditions
if request.xml_http_request?
render :partial => "items_list", :layout => false
end
end
I would greatly appreciate any help I can get!
You said your using the newest version of Rails, if that is Rails 3.0.0 then observe_field and the way they are doing javascript is definitely different. Either downgrade to Rails 2.3.8 (I would not), learn the new way, or use the old way in Rails 3.0.0
New Way in Rails 3.0.0: http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/
Old way in Rails 3.0.0: http://github.com/rails/prototype_legacy_helper
If you want 2.3.8 I can show you observe field, just let me know...

Ruby on Rails Country/State Select Enigma

I am trying to implement something seemingly very simple, and I have been beating my head against it for days at this point.
My desired end result is a Country select drop-down, tied to a State select drop-down, in such a way that when a given country is selected, IF states are known THEN those states are displayed in a select drop down, and if NO states are known for that country, then a text field is displayed instead.
I feel like I am almost there. At this point the interface will actually generate that list of states based on the persons' country, except it is refusing to update the drop-down dynamically.
The portion of my view where country and state location is gathered looks like:
# _person_setup.html.erb
<td>
<%= f.label :country, 'Select your country' %>*<br />
<%= f.select :country, Carmen::country_names, {},
{:style => 'width: 200px',
:id => 'country_select',
:onchange => remote_function(
:url => {:action => 'update_states'},
:with => "'country='+value")} %>
</td><td>
<p>
<div id="states_div">
<%= render :partial => 'states',
:object => Carmen::states(
Carmen::country_code(
#person.country)),
:locals => {:form => f} %>
</div>
</p>
</td>
The partial being referenced in the DIV is as follows:
# _states.html.erb
<% unless states.nil? or states.empty? %>
<%= form.label :state, 'Select your state' %>*<br />
<%= form.select :state, states.collect{|s| [s[0], s[0]]} %>
<% else %>
<%= form.label :state, 'Please enter state or province' %>*<br />
<%= form.text_field :state %>
<% end %>
Finally, the controller code which is intended to update the list of states dynamically:
def update_states
puts "Attempting to update states..."
q = params[:country]
states = Carmen::states(Carmen::country_code(q))
puts "Country = #{q}, states = #{states.collect{|s| s[0]}.join(", ")}."
render :update do |page|
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(#person)}
end
puts "OK"
end
Now, this code is being called at the proper time and generating the appropriate lists of states. For example, when the user clicks Australia, "Attempting to update states... Country = Australia, states = Australian Capital Territory, New South Wales, Northern Territory, Queensland, South Australia, Tasmania, Victoria, Western Australia" shows up in the server process. However it doesn't update the page, and won't print the "OK" at the end. In short the line which is failing is undoubtedly
page.replace_html "states_div",
:partial => 'states',
:object => states,
:locals => {:form => form_for(#person)}
Note that replacing this line with
page.replace_html 'states_div', "<b>is it working</b>"
properly replaces the div, but of course not with anything useful.
Can someone help me understand what is going on here?
It looks like you're assuming that the #person variable is still available from your original action. This could be set up by a filter for the current person but you don't show that in your question.
If you do need to lookup the #person again you'll have to pass the id through in your remote_function I think.
Ryan Bates has a Railscast that shows how to select a category for a product or create a new category by typing the name. It sounds like a similar scenario to what you have, so you might want to check it out: Create Model Through Text Field.
This took me a full day to figure out something that would at least "work". I am also using Carmen and also messing with the select tag in a form_for model form (actually, fields_for nested within forms_for...which adds additional complications).
I would think there is a better solution but this worked for me. The select needs to be referenced by the form but the options don't. Thus, first time through, I use the Carmen state_select method which populates the select tag correctly and all the nested options tags. The second time through, I just replace the options. Take a look:
In the view, I chose to use an observe_field method since I do other things besides update the states (some other localization changes) but this should work for remote_function and others, too:
<%= address_form.country_select :country, {:prompt => "--Select One--"} %>
Don't be confused by the id (user_address_attributes_country) it is just my silly forms_for/fields_for implementation)
<%= observe_field :user_address_attributes_country, :url => { :action => :changecountry }, :with => 'new_country' %>
<%= address_form.state_select :state, #user.address.country, {:prompt => "--Select One--"}, :style => 'width: 90px' %>
Then in my controller, it just looks like this:
def changecountry
c = params[:new_country]
respond_to do |format|
format.html
format.js {
render :update do |page|
page['user_address_attributes_state'].innerHTML = \
"<option>--Select One--</option>" + state_options_for_select(nil, c)
end
}
end
end
Note: state_options_for_select is also from Carmen. I could not get it to work unless I put it inside the respond_to block where I guess the view helpers are available. Also, I hard code user_address_attributes_state which is my nested id generated from the form_for/fields_for address_form.state_select rendering call in the view.
I hope this helps. If anyone can do it better, believe me, I'm all ears. I'll change the design in time...but needed something that just worked today and this was the best I could figure out in a limited time.

Resources