In my rails app, I have product and order models. Lets say the products controller look like this:
def index
#products = Product.all
#order = Order.new
end
I have listed all products in the index view as divs. I would like to assign a product's id to the order (#order.product_id = product.id) when I click on its div.
= #products.each do |product|
.product
= product.name
= product.price
Any ideas how to do this :? Thank you!
You need to trigger another request that includes the product ID, and land on a new action that assigns the ID to #order.product_id. In this case, it makes no sense to have #order = Order.new in your products#index action; instead you probably want a nested resource for orders within products, and a new controller for handling orders for a product.
config/routes.rb
resources :products do
resources :orders
end
app/controllers/products_controller
def index
#products = Product.all
end
Now, the products#index view can link to the nested route for a new order within a product. This will product a URL like /products/123/orders/new:
app/views/products/index.html.shaml
= #products.each do |product|
.product
= link_to new_product_order_path(product) do
= product.name
= product.price
Finally, you can render the new Order form using the product specified in the route:
app/controllers/orders_controller
def new
#product = Product.find(params[:product_id])
#order = #product.orders.new
end
Related
I have an album model, that has one 'cover_image' and has_many 'images'. I also have a product model. I am using pg_search to filter my products.
Independently, they both work flawlessly. What I would like to do is show an albums cover_image based on the pg_search filter param.
For example: If I had a filter param called "limestone", I would create an album called "limestone" and when a user filters the page by limestone, they would get the product results along with the matching cover_image.
product_controller - this works for filtering
def index
#products = if params[:query]
Product.search_for(params[:query])
else
Product.order(:name)
end
end
product_controller - this breaks the page
I tried this in an attempt to keep it simple and filter the image in the model
def index
#products = if params[:query]
Product.search_for(params[:query])
*#albums = Album.where(name:(params[:query]))*
else
Product.order(:name)
end
end
products/index.html.erb Then I would just call the album as normal.
...
<% #albums.each do |a| %>
<%= image_tag("#{a.cover_image_url(:original)}") %>
<% end %>
...
The problem is that you're assigning #albums to #products. This is in effect what you're doing:
#products = #albums = Album.where(name: (params[:query]))
because the if statement is returning #albums. So this should work (assuming that the rest of your logic is correct):
def index
#products = if params[:query]
#albums = Album.where(name: params[:query])
Product.search_for(params[:query])
else
Product.order(:name)
end
end
However, I would not assign #albums where you are doing so right now. I think this is clearer thus slightly better:
def index
if params[:query]
#products = Product.search_for(params[:query])
#albums = Album.where(name: params[:query])
else
#products = Product.order(:name)
#albums = []
end
end
So I've built a system of products and a shopping cart in my rails app. The goal I have is to associate saved products from a cart with user model.
I'm struggling to find a solution on how could I save ids of the items from a cart from each current_user to the column from user's model?
So in my cart view page there is a list of all added products in a cart and I want to add a save button which will save those products by their ids.
As an example, if current_user ads three products in the cart with ids 1,2,3 and clicks on "Save" button in a cart, I want to be able to save those three ids by integers to the "addedproducts" column of the current_user.
This is part of my cart_controller:
def additems
id = params[:id]
if session[:cart] then
cart = session[:cart]
else
session[:cart] = {}
cart = session[:cart]
end
if cart[id] then
cart[id] = cart[id] + 1
else
cart[id] = 1
end
redirect_to :action => :index
end
and a part of my product controller(generated through scaffold):
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update, :destroy]
respond_to :html, :json, :js
def index
#products = Product.where(availability: true)
end
def show
end
def new
#product = Product.new
end
def edit
end
def create
#product = Item.new(item_params)
#product.save
respond_with(#product)
end
Is this possible to achieve?
(I'm using standard Devise setup if it's of any help)
How you want to save multiple items to a single column "addedproducts" ? I think the best solution is adding a foreign key to the cart. Making the cart belongs_to a user. And the user having many carts. Just the same way you have probably created a Cart model and an Item model too. With the proper relationship between the two... (If you do that you will have to add a new migration to the cart model with a reference to User.)
My app is a web forum. Root page is a list of user-submitted
categories. I click one and it links to a list of user-submitted posts
about that category. I click a post and it links to a list of comments
about that post. Those are the 3 tiers.
CATEGORIES INDEX This is a list of clickable categories
<% #categories.each do |category| %>
<%= link_to category.title, category %>
<% end %>
CATEGORIES SHOW I clicked a category, now I'm here looking at a list of posts
<%= render :partial => #category.posts %>
<% end %>
_POSTS The posts are rendered from this here partial
<%= div_for(post) do %>
<%= link_to post.body, Post %>
Clicking that post link takes me to POSTS INDEX.
I'm not sure if this is a desirable flow of a Rails app. It seems odd
to go from Categories, to Posts, to Comments using Categories_Index,
Categories_Show, and Posts_Index, respectively. I don't know how to display or submit comments from this POSTS INDEX. #comments.each do |comments| provides an error and so does the render: partial method. I can not use the same methods for Comments that I used for Categories and Posts.
MODELS Models are complete with has_many, belongs_to, etc.
CATEGORIES CONTROLLER
def index
#categories = Category.all
end
def create
#category = current_user.categories.build(categories_params)
end
POSTS CONTROLLER
def create
#category = Category.find(params[:category_id])
#post = #category.posts.new(post_params)
COMMENTS CONTROLLER
def index
#subcomments = Subcomment.all
end
def create
#subcomment = current_user.subcomments.build(subcomment_params)
end
ROUTES
Rails.application.routes.draw do
resources :comments
resources :posts
devise_for :users
resources :categories do
resources :posts do
end
resources :comments
end
root "categories#index"
I successfully added posts to categories. How can I add comments to posts? Is my approach correct?
I assumed you have the following Model Relationships:
Model Category
has_many :posts
Model Post
has_many :comments
belongs_to :category
Model Comment
belongs_to :post
You are asking "How can I add comments to posts?"
In the page where you render all POSTS data,
you should USE posts ID as you main parameter.
So, meaning you should have post_id column/field inside Comments Table.
After saving the comments data, usually like [title, message, date ....].
In your Post Controller, you can get comments like:
// multiple Posts data
#posts = Post.all
#post.each do |post|
post.comments
...
end
//single Post
#post = Post.first // or Post.find(:id => params[:post_id])
#post.comments
If you are sending data using form, just put some hidden text field,
setting the name & value:
name="post_id"
// or something like:
name="comment[:post_id]"
//depends on how you constract the form.
Then set the value:
value="<%= params[:post_id ]%>"
Finnally, you can get the value like getting the other comments_field names.
Usually you should have this in in config/routes.rb,
resources :commets
Then your FORM path is like:
<%= form_for #comment, :url => #comments_path %>
Your Comments Controller should have like:
def index
...
end
def show
...
end
def edit
...
end
def new
#comment = Comment.new
end
def create
#comment = Comment.create(comment_params)
if #comment.save
....
redirect_to comments_path
else
.....
end
end
# For params permit in Rails 4 ^
def comment_params
params.require(:comment).permit!
end
Rails 3 ruby 1.9
I am trying to pass a "products" id to a "Details" page and get error "Couldn't find Product without an ID"
This is the link in my browser address bar:
http://localhost:3000/performance_details?product_id=8
My Controller
class ProductsController < ApplicationController
def performance_details
#title = "Performance Details"
#products = Product.find(params[:id])
end
The view that's passing the object ID
<%=link_to 'Details', details_path(product_id: product) %>
The view receiving the object ID
<%#products.each do |product| %>
Do some stuff with products.....%>
<%end%>
Routes File
match 'details' => "products#details"
Your parameter name is product_id, not just id. Here is how your controller should look like:
class ProductsController < ApplicationController
def performance_details
#title = "Performance Details"
#products = Product.find(params[:product_id])
end
That's probably how you should do it:
# routes
resources :products do
member do
get :performance_details
end
end
-
# view
# your url will be /products/:id/performance_details
<%=link_to 'Details', performance_details_product_path(product) %>
-
# controller
class ProductsController < ApplicationController
def performance_details
#title = "Performance Details"
#product = Product.find(params[:id])
end
end
Change the #product line in your products controller to the following:
#product = Product.find(params[:product_id])
From your comment below, you're only finding one product (note the change from plural #products to singular #product, so you don't want to use each. Change this:
<%#products.each do |product| %>
Do some stuff with products.....%>
<%end%>
To just do things with #product, rather than product. So get rid of the outer block, and only use #product. I'd overall recommend the refactoring given in Robin's answer.
You don't have id in your params. According to your URL /performance_details?product_id=8, your id is in a variable called product_id.
I have a page listing many products, at taxons#show. Inside of taxons#show I'm rendering the partial _products.html.erb to display the products, images, variants, etc. By default, when you click an individual product on taxons#show rails redirects you to the products#show page where the partial _cart_form.html.erb is rendered which displays add to cart options.
However, I'm trying to render _cart_form.html.erb inside a lightbox in _products.html.erb, which is inside of taxons#show. My problem is that _products.html.erb is using
<% products.each do |product| %>
to display each individual product. And _cart_form.html.erb is using #product to display all of its product info. If I keep it this way I get a NoMethod error for nilClass because #product isn't defined.
Then I tried:
<% #product = product %>
<%= render 'spree/shared/cart_form' %>
But because this is above the code that outputs all of the products on taxons#show it changes every product inside _product.html.erb to the same product, the first one listed.
How can I render _cart_form.html.erb inside of a lightbox for each individual product?
Here's taxons_controller.rb:
def show
#taxon = Taxon.find_by_permalink(params[:id])
return unless #taxon
#taxon_id = params[:id].split('/').first
if #taxon_id
instance_variable_set "#enable_#{#taxon_id}", true #big lettered taxonomy heading
end
#product_type = params[:id].split('/').last
#featured = #taxon_id + '/' + #product_type #featured image
#searcher = Spree::Config.searcher_class.new(params.merge(:taxon => #taxon.id))
#searcher.current_user = try_spree_current_user
#searcher.current_currency = current_currency
#products = #searcher.retrieve_products
#related_products = #taxon.products.offset(rand(Spree::Product.count - 7)).limit(7)
respond_with(#taxon)
And products_controller.rb:
def show
return unless #product
#variants = #product.variants_including_master.active(current_currency).includes([:option_values, :images])
#product_properties = #product.product_properties.includes(:property)
referer = request.env['HTTP_REFERER']
if referer
begin
referer_path = URI.parse(request.env['HTTP_REFERER']).path
# Fix for #2249
rescue URI::InvalidURIError
# Do nothing
else
if referer_path && referer_path.match(/\/t\/(.*)/)
#taxon = Taxon.find_by_permalink($1)
end
end
end
respond_with(#product)
end