Ruby on Rails 4 find object by id
I have the following show-view where I display basic product information and display other products to users.
<h1>Book <%= @product.name %></h1>
<% @products.each do |product| %>
<ul>
<%= product.name %>
<%= link_to "Make offer", {controller: "offers", :action => 'create', id: product.id } %>
</ul>
controller
def show
@product = current_user.products.find(params[:id])
@products = Product.all
end
My goal is to make an Offer between two Products. I created a proposal model and methods for creating a proposal:
class Offer < ActiveRecord::Base
belongs_to :product
belongs_to :exchanger, class_name: "Product", foreign_key: "exchanger_id"
validates :product_id, :exchanger_id, presence: true
def self.request(product, exchanger)
unless product == exchanger or Offer.exists?(product, exchanger)
transaction do
create(product: product, exchanger: exchanger, status: "oczekujace")
create(product: exchanger, exchanger: product, status: "oferta")
end
end
#other methods
end
Making suggestions works because I checked it in the console. My problem is OfferController:
class OffersController < ApplicationController
before_filter :setup_products
def create
Offer.request(@prod, @exchanger)
redirect_to root_path
end
private
def setup_products
@prod = current_user.products.find(1)
@exchanger = Product.find_by_id(params[:id])
end
end
The problem is with the following line (using the link on the show page for products with a different id than 1 job):
@prod = current_user.products.find(1)
But I don't know how to find the object in Db for the actual product that my show page is showing. Not only for id = 1.
source to share
I don't know how to find this object in the database.
I don't know a specific answer to your question, but maybe if I explain what you need to look at your solution will arise:
To find
Rails is not magic - it uses ActiveRecord (which is ORM - Object-Relation Mapper
), which means every time you run a query (via find
), your ORM (ActiveRecord) will look for the corresponding database data for you
The problem is that while you are using the correct syntax to search for, you might not be recording id
of 1
your db.
current_user.products.find(1)
tells ActiveRecord about the reach of the request around the current user and their products. So you end up with something like this:
SELECT * FROM 'products' WHERE user_id = '15' AND id = '1'
Objects
Also, you have to remember that Ruby (and Rails due to the fact that it is built in Ruby) is a language object orientated
. This means that whatever you load / interact with in the language must be object based
The problem is that you are not binding your object to your Rails framework correctly. What I mean here is described below, but essentially if you build your Rails framework correctly it will give you the ability to link your objects to each other, allowing you to call the various products
you need fromoffer
This is an easy way to look at it, of course. You want to look at this diagram to see how it works:
Bottom line - try treating your application as a series of objects rather than a logical flow. This will help you appreciate the various associations, etc., that you need to move forward.
Resources
You mentioned that you cannot show a product on your page for id
but one. I think the problem is how to get your action show
to work.
If so, let me explain ...
Rails is resource based , which means that everything you do / create should be centered around some resource (object). The problem is that a lot of people are unaware of this and hence obscure the structure of the controller for no reason:
Above is a typical "CRUD" routing structure for Rails based resources. This should demonstrate how Rails would normally be built - around resources.
-
Plus, Rails is built on MVC programming pattern
- which means you need to use your controller to populate a series of data objects for use in your application.
To this end, if you are loading a resource and want to fill it with resourceful information of another object - you need to make sure that you set up the data objects so that you can view them correctly, which either means passing data through your routes or using a persistent data type. for example cookies
or sessions
You have a problem to pass the product id to your controller somehow . How I would do it: nested resources ):
#config/routes.rb
resources :offers do
resources :products #-> domain.com/offers/2/products
end
This will give you the ability to load a controller products
with variables params[:id]
for the product, and params[:offer_id]
for your offer
made available:
#app/controllers/products_controller.rb
Class ProductsController < ApplicationController
def show
@offer = Offer.find params[:offer_id]
@product = Product.find params[:id]
end
end
source to share