Rendering an Edit partial while selected a defaulted value - ruby-on-rails

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.

Related

Rendering Rails from tag

I have my form_tag set up as follows:
<% Rating.find(:all, :conditions => ["recommendation_id = ? and rating_set = ? and product_id = ?", rec.id, params[:rating_set_id], params[:product_id]]).each do |rate| %>
<%= text_field_tag "recommendation_ratings[#{rec.id}][notes]", "#{rate.notes}", :id => "rec_note_text", :placeholder => 'Enter Notes..'%>
<% end %>
This works when the find conditions are met, however before the form is submitted, the recommendation_id is not persisted to the DB, so this find method does not return anything, and this causes my form tag not to render. It only render when all conditions of the find are met. How can I render my form regardless is the find condition is met?
You are using view/controller in a wrong way.
You should define new partial called _rating.html.erb
in there your form_tag (please replace with valid values, I have just put as an example)
<%= text_field_tag "recommendation_ratings[#{id}][notes]", "#{notes}", :id => "rec_note_text", :placeholder => 'Enter Notes..'%>
then, wherever you are rendering that list of Ratings, put for example in ratings/show.html.erb
<%= render #ratings%>
and in Ratings_controller you should put:
define show
#ratings = Ratings.find_all_with_conditions
end
and in model Rating.rb you should put:
define self.find_all_with_conditions
Rating..find(:all, :conditions => []) #put your logics here for finding all
end
I have just wrote just as an example how you should organize it, and I have not looked to put all valid parameters, I have put just for you to see how to organize you view.
I hope it will help.

Passing ActionView::Helpers::FormBuilder to a partial

I am atempting to dinamically create form elements given a certain AJAX request.
This is my setup:
View:
<%= link_to 'Next', check_unique_id_students_path, :remote => true %>
<div id="guardian_student_details"></div>
Controller:
def check_unique_id
#student = Student.new
#this_form = ActionView::Helpers::FormBuilder.new(:student, #student, #template, {}, proc{})
end
JS:
jQuery("#guardian_student_details").html("<%=escape_javascript(render :partial => "student_details", :locals => { :s => #this_form }) %>");
Partial:
<% puts s.text_field :first_name %>
<% puts s.field_helpers %>
For debugging purposes i placed the following lines at the very beginning of my partial:
<% puts s.class.to_s %>
<% puts s.object.to_s %>
This prints out :
ActionView::Helpers::FormBuilder
Student
This should work. However rails is giving the following error:
ActionView::Template::Error (undefined method `text_field' for nil:NilClass):
1: <% puts s.class.to_s %>
2: <p>
3: <%= s.text_field :first_name, :class => 'text_input is_empty' %>
4: <%= s.label :first_name %><strong>*</strong>
5: </p>
6:
app/views/students/_student_details.html.erb:3:in _app_views_students__student_details_html_erb__2485891544130782916_2214680440'
app/views/students/check_unique_id.js.erb:2:in_app_views_students_check_unique_id_js_erb__3504800328150418937_2214933160'
Which implies that "s" is NIL something I verified just 2 lines before. Does anybody have any ideas? i dont know if this has something to do with the "#template" variable initialized in the controller. Which i played around with and accepts practically anything and if printed is nil.
Any help would be appreciated. Thanks
Final note:
I tried to implement this: AJAX update of accepts_nested_attributes_for partials
For anyone needing to build a form builder in the controller, view_context still works there. Using Rails 4.1.4:
#object = Object.new
#f = ActionView::Helpers::FormBuilder.new(:object, #object, view_context, {})
In the view, I've found that 'view_context' does not work in Rails 3.1. Instead try 'self' when creating a FormBuilder object.
s = ActionView::Helpers::FormBuilder.new(:student, #student, self, {}, proc{})
Try this in a console :
s = ActionView::Helpers::FormBuilder.new(:student, #student, #template, {}, proc{})
s.text_field :first_name
You will have the same error. I think the problem come from your creation of the form_builder object, even if I don't know the exact mistake...
Your solution seems to me to be a little much complex. You can try this solution :
#html.erb
<% form_for #student do |f| %>
<div id='guardian_student_details' class='hide-this-block'>
<%= render :partial => "student_details", :locals => { :s => f }) %>
</div>
<% end %>
#js
jQuery("#guardian_student_details").show();
Generally, I prefer keep javascript and ruby separated.

Handling an undefined variable

I render a partial in one view:
<%= render 'video', :video => #video, :video_id => 'video_show_id' %>
and have this code in the partial:
<% if video_id %>
<%= link_to "video", video.video_url, :class => "oembed", :id => video_id %>
<% else %>
<%= link_to "video", video.video_url, :class => "oembed" %>
<% end %>
The problem is that this partial gets rendered in a number of places in my app, and in those other views I do not want to pass :video_id into the partial. Therefore my app throws an error that video_id is undefined. I could pass :video_id => "" into the partial in the other views, but since the partial is rendered in many places, that is kind of a pain. Is there a simpler way to handle this?
Try defined? and not that it really matters but it's actually an operator.
<% if defined? video_id %>
I think the better way to handle this is to create a helper that then manages the values of variables that need to fed to a partial. Something like:
module VideoHelper
def show_video(video, options = {})
options[:id] ||= ""
render 'video', :video => video, :video_id => options[:id]
end
end
Now, instead of having to have that long render partial line in your view, you get to shorten it to a show_video call.
Also, I've found that in the long term, this allows for a lot more flexibility and I have to think a lot less about what variables the partial needs at this time and whether or not they are defined.
Change the check to <% if defined? video_id %>

passing in parent id to remote_form partial on item creation

I am still kind of fuzzy on controllers in rails, especially so because a lot of things seem to happen magically behind the scenes, and that's not happening in this case.
So say I have a person model, which has many photos (using paperclip) and has many favorite quotes. The quotes can have the text, the attributed author, etc. In both of those models, they are set as belonging to my person model.
Within a new person form, I used some code elsewhere to create a new photo:
<% form.fields_for :screenshots, :html => { :multipart => true } do |screen_form| %>
<%= render :partial => 'screenshot', :locals => { :form => screen_form } %>
<% end %>
The partial for that is very simple, like this (minus some ajax javascript stuff I put in for nested models):
<%= form.label :photo, "Screenshot:" %>
<%= form.file_field :photo %>
This all works fine and magically the ID of the person is associated with a screenshot upon creation in person_id. I don't even have a controller for screenshots and it still works.
However, it's not working for my quotes.
<% remote_form_for :quote, :html => { :method => :put }, :url => {:controller => "quote", :action => "create", :person_id => #person.id} do |quote_form| %>
<%= render :partial => 'quote', :locals => { :form => quote_form } %>
<% end %>
The partial for this is also very simple.
<%= form.label :quote_text %>
<%= form.text_field :quote_text %>
.........
<%= form.submit 'Create' %>
I am not really sure if I can put person ID in there, but it didn't complain. However it didn't work, either. The quotes controller is very simple.
def create
#quote = Quote.create(params[:quote])
end
Currently it gets put in the DB but person_id is not populated so I can't pull up the quotes associated with a particular person. Sorry if this is a silly question, but I'm kind of learning Rails by tweaking tutorials and mashing them together so bear with me :) It's just kind of mysterious how the photo thing works with NO controllers or special stuff and this doesn't.
The first form is a person form mainly that has snapshots fields associated to it, so looking at your HTML you will find something like person[snapshots][photo], this form will be submitted to person controller.
Passing person id to second form the is key to make it work, however it's a bit weird that it's not working, the form will submit to quote controller. Did you make sure(watch the log) that the params hash has person_id attribute?

Rails: Using form (collection select) to call show-action

A model named 'book' with attributes 'name' and 'id' is given. How can i use this collection select to call the show-action of a certain book? The one code mentioned below returns the following error message:
Couldn't find Book with ID=book_id
<% form_tag(book_path(:book_id)), :method => :get do %>
<p>
<%= label(:book, :id, 'Show Book:') %>
<%= #books = Books.find(:all, :order => :name)
collection_select(:book, :id, #books, :id, :name)
%>
</p>
<p>
<%= submit_tag 'Go' %>
</p>
<% end %>
book_path is generated once only, for the form tag itself. It won't be updated whenever your selection changes.
When you submit that form, it's going to request the following URL:
/books/book_id?book[id]=5
Since your book_path thinks book_id is the ID number you wanted, it tries to look that up. You could do what you want you by changing the code in your controller from:
#book = Book.find(params[:id])
to:
#book = Book.find(params[:book][:id])
But it kind of smells bad so be warned.
You can create a new route that is not based on the id, like
get 'books/show' # put this above your "resources :books"
and change your form to
<% form_tag books_show_path, :method => :get %>

Resources