only showing button to index action when there are objects listed in the index(in the database) - ruby

I have a button that links to the projects updates index action through all_project_updates_path i set in my routes. Here is my button code:
<%= button_tag type: "button", :class => "radius" do %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
I want this button to only be visible when there are project updates in the database. Otherwise I want this button to dissapear. I tried:
<% if all_project_updates_path(#project) != nil %>
<%= button_tag type: "button", :class => "radius" do %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
<% end %>
And also
<% if #updates != nil %>
<%= button_tag type: "button", :class => "radius" do %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
<% end %>
but that doesn't seem to work. Looking for a simple explanation as I am a relative beginner with ruby.
This is the route:
get 'all_project_updates/:id' => 'project_updates#index', as: 'all_project_updates'
This is my projects controller(show action)
def show
#project = Project.find(params[:id])
#comments = Comment.all.where(:project_id => #project.id)
#updates = ProjectUpdate.all.where(:project_id => #project.id)
end
And this is my project updates controller index action:
def index
#projectUpdates = ProjectUpdate.where(:project_id => params[:id])
respond_to do |format|
format.html
end
end

You’re examining a path helper, all_project_updates_path, when you need to be querying a model object. The all_project_updates_path call is a helper to return a path for linking between web pages.
all_project_updates_path(#project) # => /all_project_updates/1
So you’re really asking:
'/all_project_updates/1'.nil? # => false
Because it’s just a string, it won’t be nil.
Instead, you should be examining the project_updates directly. I’m not sure how your models are related, but assuming that a Project has_many :project_updates, try this:
if #project.project_updates.any?
That will return true if a #project has any updates.
Beyond your immediate question, I would recommend considering whether nested resources are a better fit for this usage. You could declare your routes like this:
resources :projects do
resources :project_updates
end
Then you would get project_project_updates_path(#project) and no longer need your custom route that pretty much duplicates that functionality.

Try this:
<% if #updates.any? %>
<%= button_tag ... %>
<% end %>
#updates is an empty collection (ActiveRecord_Relation to be precise) of ProjectUpdate objects if no records were found, it's not nil.

Related

How to save many items on one form rails?

I need to save many items to Cart on form, user enter quantity one form, and selected items goes to db, but now save only first entered quantity of item. Why?
my form
<%= form_for #cart_item do |f| %>
<% #category.items.each do |item| %>
<%= item.name %>
<%= f.hidden_field :item_id, :value => item.id %>
<%= f.text_field :qty %>
<% end %>
<%= f.submit %>
<% end %>
And controller
cart_items_controller.rb
class CartItemsController < ApplicationController
before_action :set_cart, only: [:create]
def create
#cart_items = CartItem.create(cart_items_params)
#cart_items.cart_id = #cart.id
if #cart_items.save
redirect_to :back
else
render root_path
end
end
private
def cart_items_params
params.require(:cart_item).permit(:id, :qty, :item_id, :cart_id)
end
def set_cart
#cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
#cart = Cart.create
session[:cart_id] = #cart.id
end
end
There are a few problems here. I'll give you a little bump:
<% #category.items.each do |item| %>
<%= item.name %>
<%= f.hidden_field :item_id, :value => item.id %>
<%= f.text_field :qty %>
<% end %>
For each CartItem, this is going to create an input like this
<input name="qty">
This is problematic because only one (the last one in the DOM) will be submitted. You need to research fields_for and incorporate that into your loop in order to get unique names for each Item in the form.
This same issue follows through into your controller
def cart_items_params
params.require(:cart_item).permit(:id, :qty, :item_id, :cart_id)
end
This is going to look for a single :id, :qty, :item_id, and :cart_id, when in reality you're looking to accept multiple :item_id and :qty fields. You need to research Strong Parameters with nested has_many associations.
Finally you have this
#cart_items = CartItem.create(cart_items_params)
which is going to attempt to create a single CartItem when you're really trying to create multiple items and associate them back to the Cart. You need to research accepts_nested_attributes_for as well as more generally "rails form save has_many association". It's a widely covered topic here on SO and elsewhere.
I do this:
def create
#cart_items = params[:cart_items]
#cart_items.each do |c|
#cart_item = CartItem.new(c)
if #cart_item.qty.present?
#cart_item.cart_id = #cart.id
#cart_item.save
end
end
and form
<%= form_tag cart_items_path do %>
<% #cart_items.each do |cart_item| %>
<%= fields_for "cart_items[]", cart_item do |f| %>
<% #category.items.each do |item| %>
<%= item.name %>
<%= f.hidden_field :item_id, value: item.id %>
<%= f.text_field :qty %>
<% end %>
<%= f.submit %>
<% end %>
<% end %>
<% end %>

skipping(going straight to the show page) the index page if there is only 1 item in the database

How can I skip the index page and go straight to the show page if there is exactly only 1 project update in my database for that project(while also making sure no button gets displayed if there is no update(zero) in the database?
I tried this:
<% if #project.updates.any? %>
<%= button_tag type: "button", :class => "radius" do %>
<% if #project.updates=1 %>
<%= link_to 'Project Update', project_update_path(#project), :style => "color: white" %>
<% else %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
<% end %>
<% end %>
but i get this error:
undefined method `each' for 1:Fixnum
On this line:
<% if #project.updates=1 %>
What is the proper syntax for this?
Below is the relevant code:
My button:
<% if #project.updates.any? %>
<%= button_tag type: "button", :class => "radius" do %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
<% end %>
These is my custom route:
get 'all_project_updates/:id' => 'project_updates#index', as: 'all_project_updates'
These are the final generated routes:
project_updates_path GET /project_updates(.:format) project_updates#index
project_update_path GET /project_updates/:id(.:format) project_updates#show
This is my projects controller(show action)
def show
#project = Project.find(params[:id])
#comments = Comment.all.where(:project_id => #project.id)
#updates = ProjectUpdate.all.where(:project_id => #project.id)
end
And this is my project updates controller index action:
def index
#projectUpdates = ProjectUpdate.where(:project_id => params[:id])
respond_to do |format|
format.html
end
end
And this is my project updates controller show action:
def show
#projectUpdate = ProjectUpdate.find(params[:id])
respond_to do |format|
format.html
end
end
You probably meant:
<% if #project.updates.count == 1 %>
== is for comparison, = is usually for assignment. Also, you need to compare updatesnumber to1(you can get number withcountmethod), notupdates` themselves.
Instead of comparison, you can use Enumerable#one? method:
<% if #project.updates.one? %>

Formtastic Creating a form without users

I'm creating a web application with formtastic. I installed the gem and wrote my code like this:
<%= semantic_form_for #index do |form| %>
<%= form.inputs do %>
<%= form.input :name %>
<%= form.input :born_on, :start_year => 1997 %>
<%= form.input :description, :as => :text %>
<%= form.input :female, :as => :radio, :label => "Gender", :collection => [["Male", false], ["Female", true]] %>
<% end %>
<%= form.actions do %>
<%= form.action :submit, :as => :button %>
<% end %>
<% end %>
I want the form to appear on the index page which is why I have #index. For some reason I can't do #index. How would I reference the top line so that it renders a form on the index page? Currently my index page has nothing in it, but it is defined in the controller
form_for helper expects some object that responds to fields You refer inside Your form. Here is an example of using semantic_form_for with plain Ruby object: http://affy.blogspot.com/2010/02/using-formtasic-without-activerecord.html.
Also the object You specify for form doesn't effect which page is being rendered. Are You sure You are not mixing up something? Maybe if You share a bit more of Your controller code we might help You better.

RoR: how can I search only microposts with a certain attribute?

Right now in app/views/microposts/home.html.erb I have..
<% form_tag purchases_path, :method => 'get', :id => "products_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<% form_tag sales_path, :method => 'get', :id => "sales_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
and then in micropost.rb I have
scope :purchases, where(:kind => "purchase")
scope :sales, where(:kind => "sale")
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
and then finally in the microposts_controller.rb I have
def home
#microposts=Micropost.all
#purchases=#microposts.purchases
#sales=#microposts.sales
end
Right now I am getting an error saying undefined local variable or method `purchases_path' and it does the same for sales_path.
What I want to be able to do is search only some of the microposts instead of all of them. In my micropost table I have a column called kind which can be either "purchase" or "sale". How can I change these three pieces of code so that one search searches through and displays results for only those microposts with the kind "purchase". And then the other searches through and displays results for only those microposts with the kind "sale"
this question (on another post) has a bounty with 50 rep at RoR: how can I search only microposts with a specific attribute?
You might try this.
Your model:
class Micropost
# ...
scope :purchase_only, where(:kind => "purchase")
# ...
def self.search(search)
if search
self.purchase_only.find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
self.purchase_only
end
end
end
But, this stuff looks very strange to me.
E.g.: You should remove the .find(...), this finder will be deprecated with Rails 4.

Paperclip multiple upload & save extra field

Im stuck uploading multiple photos to my model when adding an extra field to the photo model. In the code i hard code "1" value to the hidden_field, but i will change it eventually. The paperclip gem raises a rollback and won't insert the photos in the post. If i erase the "hidden_field" line it will success. Any ideas on how to add extra field to the upload in the view?
<%= form_for #campaign_point_of_sale, :html => {:multipart => true }, :url => "/pos/#{#point_of_sale.id}/post/#{#campaign.id}", :method => :post do |f| %>
<%= f.hidden_field :id %>
<label>Add photo <br />
<%= f.fields_for :campaign_result_point_of_sale_photos do |builder| %>
<% if builder.object.new_record? %>
<%= builder.hidden_field :is_mount_photo, :value => "1" %>
<%= builder.file_field :photo %>
<% end %>
<% end %>
<%= f.submit(:value => "Save") %>
Got it!
Just needed to delete the whole builder with both hidden_field and file_field, so the server would not try to insert a picture without an image file (just with a hidden_field value)
This can be achivied by surrounding both inputs with a div and deleting it (with jquery) at form submit if the file_field value was empty. Pretty cheap but works!

Resources