condition in partial from other controller - ruby-on-rails-3

I have a model group -> has_many :questions and a question -> has_many :votes
In my my view show, for the controller groups, I have a partial that can display the list of the questions :
<%= render :partial => 'question', :collection => #group.questions.byvote %>
Then I have a link to vote with a style like this :
<%= link_to(question_votes_path(question), :controller => :vote, :action => :create, :method => :post, :id => 'vote') do %>
<%= image_tag("voteUp.png")%>
<%= question.votes_count%>
<%end%>
What I would like to do is make a condition, like :
<% if canvote?%>
… and change the style of the div.
BUT. Making a condition in the group controller can't be made because I need to make my request about the question and not about the group :
Vote.where(:user_id => current_user.id, :question_id => #question.id).first
How can I make it form the other controller group or tell an helper_method in the question controller ?

I think you should use a model method - you can then call it right in the view and do so unobtrusively. The following method will return true if the user has voted on a given question:
User.rb
def voted?(question)
#returns true if vote exists
Vote.exists?(:user_id => current_user.id, :question_id => question.id)
end
You can use it like this:
_question.html.erb
<% if current_user.voted?(#question) %>
#code to use if the user has voted on this question
<% else %>
#code to use if the user has NOT voted on this question
<% end %>

Related

params of the model not being returned rails 3

I have made a few posts before this regarding how to add a favourite recipe to a user..I have an app where you can upload recipes once logged in, users can search the entire table for all recipes and view their own recipes in a member area..
Now I want users to be able to save their favourite recipes, so far I can save a favourite recipe as such, the output that I get is
[#<Favourite id: 1, user_id: 8, recipe_id: nil, created_at: "2012-11-06 19:25:34", updated_at: "2012-11-06 19:25:34">,
so i am getting the correct user_id but no params for the actual recipe, ie dish name, country of origin.
My models are like so
User
class User < ActiveRecord::Base
has_many :recipes
has_many :favourites
Recipe
has_many :ingredients
has_many :preperations
has_many :favourites
Favourite
belongs_to :user
belongs_to :recipe
My favourite controller looks like so
def create
#favourite = current_user.favourites.new(params[:recipe])
if #favourite.save
redirect_to my_recipes_path, :notice => "Recipe added to Favourites"
end
end
Add to favourites link
<%= link_to "Add to favorites", {:controller => 'favourites', :action => 'create'}, {:method => :post } %>
I hope I haven’t missed anything out, any help appreciated
You need to add extra information in the link and modify the create action
# View
<%= link_to "Add to favorites", favorite_path(:recipe_id => #recipe.id), {:method => :post } %>
# Controller
def create
#favourite = current_user.favourites.new(recipe_id: params[:recipe_id)
if #favourite.save
redirect_to my_recipes_path, :notice => "Recipe added to Favourites"
end
end
The problem is you are sending nothing to the controller in the param params[:recipe]
NOTE: remember the attr_accessible :user_id, :recipe_id inside Favorite model.
as stated
<%= link_to "Add to favorites", favorite_path(:recipe_id => #recipe.id), {:method => :post } %>
BUT this all depends on what #recipe is defined as in your controller - for example, if you have
#recipes = Recipie.all
And in the view you have
#recipes.all do |recipe|
Then in your link (within the block) you need to have:
<%= link_to "Add to favorites", favorite_path(:recipe_id => recipe.id), {:method => :post } %>
Does that help?
You're not sending any parameters through in the link.
<%= link_to "Add to favorites", {:controller => 'favourites', :action => 'create'}, {:method => :post } %>
This isn't enough to add a recipe to the favourites. What you'll need to do is pass through a recipe's id along with this link:
<%= link_to "Add to favorites", {:controller => 'favourites', :action => 'create', :recipe_id => recipe.id}, {:method => :post } %>
Or you could make this much shorter by using a routing helper:
<%= link_to "Add to favorites", add_to_favorites_path(:recipe_id => recipe), {:method => :post } %>
Defining that routing helper inside your config/routes.rb like this:
post '/favorites' => "favorites#create", :as => "add_to_favorites"
Then just find the recipe with params[:recipe_id] inside the controller and do what you need to do with it.

Adding fields to nested forms

So I have a model called City and it has_many :places and it accepts_nested_attributes_for :places. Each Place belongs_to :category. When I render a form for a City I have f.fields_for :places do |place| and I do it like this:
<% f.fields_for :places do |place| %>
<%= render "place_fields", :f => place
<% end %>
My _place_fields.html.erb contains the folowing:
<div class="place_header"><%= f.object.category.name %></div>
<div><%= f.label :name %>: <%=f.text_field :name %> </div>
<div><%= f.text_area :description %> </div>
But the problem apears when I try to add a new place. First of all I want to bring up a simple select form to select a category for the new place, and then render that same partial based on the category_id.
I do that inside the same action:
def add_place
if params[:category_id]
#place = Place.new(:category_id => params[:category_id])
respond_to do |format|
format.html { return nil }
format.js {
#here comes the render
}
end
else
render_message :header => "Choose category", :partial => "category_select", :over => 10
end
end
But if I try to do $("#places_tab").append("<%= escape_javascript(render :partial => "place_fields", :f => #place %>"); it gives an error, wich is expected.
Once again: I need to render the fields for that new Place and just don't know how to do that.
UPDATE
Received some advice on passing the original City Formbuilder to the action and rendering that Place right from that builder, but don't have any idea of how to do that.
The problem is that you are passing an instance of the Place model (#place) as the form builder instead of the form builder itself.

Why isn't my increment working correctly?

I have a simple system in which photos have many comments.
I'm sure I'm not doing this right, but I am trying to build a simple rating system for the comments. comment.rating starts at 0 and can go up.
This is a portion of my Comments controller
class CommentsController < ApplicationController
def increment
#comment = Comment.find(params[:id])
#comment.rating += 1
redirect_to(#photo)
end
end
I think the increment method is fine, but how I'm calling it is not:
<%= link_to "+", :controller => 'comments', :method => 'increment' %>
That doesn't work. I realize this is a bit of a fundamental question, but I'd appreciate any advice. Thanks.
I believe you are not passing a comment :id to params.
You could do so by defining a route like this in your routes.rb file:
match 'increment_rating/:comment_id' => 'Comments#increment', :as => 'increment_rating'
with your increment action now beginning with
def increment
#comment = Comment.find(params[:comment_id])
...
end
and then call it from the view with
<%= link_to '+', increment_rating_path(comment.id) %>
where comment.id gives the id of the comment whose rating you want to increment
<%= link_to "+" , :controller => "comments", :action => "increment", :id => #comment %>
<%= link_to "+" , :controller => "comments", :action => "increment", :id => comment.id %>
Keep in mind usually such action would use POST or PUT, in which case you need to specify :method with either :post or :put.
If you have added the increment in routes, you could also use:
<%= link_to "+", increment_comment_path(comment.id) %>

Newbie Question - Finding Data Problems

This is probably a very basic question but I can't figure out what to do.
I need to find a username from an id in an unrelated view.
In my app, my Orders have many Milestones. Each Milestone has an associated user although there is no relationship between the Milestone model and User model. In my Milestones form, I used the following to grab the user id's and display as a name:
<%= f.input :milestone_user, :as => :select, :multiple => false, :input_html => { :size => 1 }, :label => "", :collection => User.find(:all, :order => "name ASC") %>
However, in my show Milestone view, I can only see an id.
In order to display the name, I was trying something like this in the console to test:
#user = User.where(:id => 2)
But when I run:
#user.name
I get a no method error.
My questions are as follows:
Should I just make the milestones belong to Users as well?
If not, what's the best way to display the username?
-- UPDATE --
I'm totally lost about calling this in my view. If I use the suggestion below:
#user = User.find(2)
Actually what we need is something like:
#user = User.find(:milestone_user)
Where milestone_user is an integer. But that gives me errors. Very confused...
-- UPDATE 2 --
In my index view, I'm actually using table builder to display the information. For simplicity, I've deleted the extra code. My home#index view contains:
<% for milestone in orders %>
<li><%= link_to milestone.name, milestone_path(milestone.id), { 'data-href' => milestone.notes, :class => 'selector' } %></li>
<li><%= #users.name %> </li>
<% end %>
And my home controller:
#milestones = Milestone.all
#users = User.find(params[:milestone_user])
Replace #user = User.where(:id => 2) with #user = User.find(2)
UPDATE 2
The easiest way - remove #users = User.find(params[:milestone_user]) from your home#index method and add correct your view file:
<% for milestone in orders %>
<li><%= link_to milestone.name, milestone_path(milestone.id), { 'data-href' => milestone.notes, :class => 'selector' } %></li>
<li><%= User.find(milestone.user_id).name %> </li>
<% end %>

Rails appends id to singular route when render edit after errors

I have the following singular route:
scope '/seller' do
resource :seller_profile, :path => "/profile", :only => [:show, :edit, :update]
end
and the following controller:
class SellerProfilesController < ApplicationController
before_filter :validate_user_as_seller
def show
#seller_profile = current_user.seller_profile
end
def edit
#seller_profile = current_user.seller_profile
end
def update
#seller_profile = current_user.seller_profile
if #seller_profile.update_attributes(params[:seller_profile])
redirect_to(seller_profile_path, :notice => 'Profile was successfully updated.')
else
render :action => "edit"
end
end
end
I use a singular route given that the user must be authenticated before gaining access to the controller and therefore I can get the seller_profile from the user logged in.
This works like a charm, with only one problem. When I edit the seller_profile and validation error happen, the form is edited again and the errors are displayed correctly. The problem is that rails appends to the url the id of the edited record. For instance,
when I first edit the record, the url is:
http://0.0.0.0:3000/seller/profile/edit
but if the form is submitted with validation errors, the form itself is redisplayed under
http://0.0.0.0:3000/seller/profile.2
where 2 is the ID of the record being edited.
The form is the following:
<%= simple_form_for #seller_profile do |f| %>
<%= f.input :name %>
<%= f.input :description %>
<%= f.submit %>
<% end %>
Everything, as said, works great but I would totally mask the ID in the url. What should I do?
I have not really worked too much with simple_form_for. But it looks like it is guessing your url always as if they were not single resources. You can provide a custom one:
<%= simple_form_for #seller_profile, :url => seller_profile_path do |f| %>
<%= f.input :name %>
<%= f.input :description %>
<%= f.submit %>
<% end %>