Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails 4 find object by id

I have the following show-view, where i display basic information about Product and display other User's Products.

<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 Offer between two Products. I created Offer model and methods for making Offers:

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 offers is working, because I checked it in Console. My problem is in OffersController:

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

Problem is with a following line (using link in show-page for products with different id's than 1 works):

@prod = current_user.products.find(1)

But I don't know how to find object in Db for actual product which my show-page shows. Not only for id = 1.

like image 972
Przemek903 Avatar asked Mar 19 '23 20:03

Przemek903


1 Answers

I don't know how to find this object in database.

I don't know the specific answer to your question, but perhaps if I explain what you need to look at, your solution will arise:


Find

Rails isn't magic - it uses ActiveRecord (which is an ORM - Object-Relation Mapper), which means every time you fire a query (through find), your ORM (ActiveRecord) will search the relevant database data for you

The problem you have is that although you're using the correct syntax for your lookup, you may not have a record with an id of 1 in your db.

current_user.products.find(1) tells ActiveRecord to scope the query around the current user, and their products. So you'll get something like like this:

SELECT * FROM 'products' WHERE user_id = '15' AND id = '1'


Objects

Further, you have to remember that Ruby (and Rails by virtue of being built on Ruby) is an object orientated language. This means that everything you load / interact with in the language should be based on an object

The problem you have is you're not associating 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 associate your objects with each other, allowing you to call the various products you need from your offer

This is a simplistic way of looking at it, of course. You'll want to look at this diagram to see how it works:

enter image description here

Bottom line - try treating your application like a series of objects, rather than a logical flow. This will help you appreciate the various associations etc that you need to get it moving forward


Resources

You mention you can't show the product on your show page for an id other than one. I think the problem is really about how to get your show action to work.

If this is the case, let me explain...

Rails is resource-based, meaning that everything you do / create needs to be centred around a resource (object) of some sort. The problem is many people don't know this, and consequently complicate their controller structure for no reason:

enter image description here

Above is the typical "CRUD" routing structure for Rails-based resources. This should demonstrate the way that Rails will typically be constructed -- around resources

--

Further, Rails is built on the MVC programming pattern - meaning you need to use your controller to populate a series of data objects for use in your application.

To this end, if you load a resource, and want to populate it with resourceful information of another object - you need to make sure you have set up the data objects in a way to ensure you can look them up correctly, which either means passing the data through your routes or using a persistent data-type, such as cookies or sessions


The problem you have is you need to pass the product id to your controller somehow. How I'd do that is as follows (using nested resources):

#config/routes.rb
resources :offers do
   resources :products #-> domain.com/offers/2/products
end

This will give you the ability to load the products controller with the 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
like image 58
Richard Peck Avatar answered Mar 24 '23 01:03

Richard Peck