building an order from a cart - ruby-on-rails

i've been having issues trying to build a Cart + Cart/OrderItem + Order combination simple enough yet effective. I've looked around online but i couldn't find anything that fit, so i tried something but .. i'm a bit blocked atm, i don't see how to continue with this. The problem is that i don't know how to get the items in the order and start the cart from scratch (btw it's kind of messy). Also a nice simple tutorial on this would be appreciated as well. Do note i already went through agile web's book example, but for some reason i didn't follow it, it didn't seem to be what i was looking for.
controllers - cart + order
class CartsController < ApplicationController before_filter :initialize_cart
def add
#cart.add_item params[:id]
session["cart"] = #cart.serialize
product = Product.find(params[:id])
redirect_to :back, notice: "Added #{product.name} to cart." end
def show end
def checkout
#order = Order.new user: User.new end end
class OrdersController < ApplicationController
def index
#orders = Order.order('created_at desc').page(params[:page])
end
def show
end
def new
#order = Order.new
end
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to root_path, notice:
'Thank you for your order' }
format.json { render action: 'show', status: :created,
location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors,
status: :unprocessable_entity }
end
end
end
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:pay_type, :user_id)
end
end
now the models
class Order < ActiveRecord::Base
belongs_to :user
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
validates :pay_type, inclusion: PAYMENT_TYPES
end
class CartItem
attr_reader :product_id, :quantity
def initialize product_id, quantity = 1
#product_id = product_id
#quantity = quantity
end
def product
Product.find product_id
end
def total_price
product.price * quantity
end
end
class Cart
attr_reader :items
def self.build_from_hash hash
items = if hash["cart"] then
hash["cart"]["items"].map do |item_data|
CartItem.new item_data["product_id"], item_data["quantity"]
end
else
[]
end
new items
end
def initialize items = []
#items = items
end
def add_item product_id
item = #items.find { |item| item.product_id == product_id }
if item
item+=1
else
#items << CartItem.new(product_id)
end
end
def empty?
#items.empty?
end
def count
#items.length
end
def serialize
items = #items.map do |item|
{
"product_id" => item.product_id,
"quantity" => item.quantity
}
end
{
"items" => items
}
end
def total_price
#items.inject(0) { |sum, item| sum + item.total_price }
end
end
Thank you.

Related

Rails pundit gem, permit view to non signed-in users

I'm using the pundit gem in order to give permissions to three different users(Admin, seller, viewer). Currently I got everything working, admin has access to everything, seller to his own products and viewer can just view the products.
The only glitch I'm having is that I would like the non signed_up/signed_in users to be able to view the products via search results. Right now non sign_up/signed_in users can see the search results but don't have access to the show view.
Here is the setup I have:
class ItemPolicy < ApplicationPolicy
attr_reader :item
def initialize(user, record)
super(user, record)
#user = user
#item = record
end
def update?
#user.is_a?(Admin) ? item.all : #user.items
end
def index?
#user.is_a?(Admin) ? item.all : #user.items
end
def show?
#user.is_a?(Admin) ? item.all : #user.items
end
def create?
#user.is_a?(Admin) ? item.all : #user.items
end
def new?
#user.is_a?(Admin) ? item.all : #user.items
end
def edit?
#user.is_a?(Admin) ? item.all : #user.items
end
def destroy?
#user.is_a?(Admin) ? item.all : #user.items
end
class Scope < Struct.new(:user, :scope)
def resolve
if user.is_a?(Admin)
scope.where(:parent_id => nil)
elsif user.is_a?(Seller)
scope.where(:id => user.items)
end
end
def show?
return true if user.is_a?(Admin)
return true if user.seller_id == seller.id && user.is_a?(Seller)
false
end
end
end
the controller:
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update, :destroy]
def index
authorize Item
#items = policy_scope(Item)
end
def search
if params[:term]
#items = Item.search(params[:term]).order("created_at DESC")
else
#items = []
end
end
def show
#comments = Comment.where(item_id: #item).order("created_at DESC")
#items = policy_scope(Item).find(params[:id])
authorize #item
end
def new
#item = Item.new
authorize #item
#categories = Category.order(:name)
end
def edit
authorize #item
#categories = Category.order(:name)
end
def create
#item = Item.new(item_params)
authorize #item
respond_to do |format|
if #item.save
format.html { redirect_to #item, notice: 'Item was successfully created.' }
format.json { render :show, status: :created, location: #item }
else
format.html { render :new }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
def update
authorize #item
respond_to do |format|
if #item.update(item_params)
format.html { redirect_to #item, notice: 'Item was successfully updated.' }
format.json { render :show, status: :ok, location: #item }
else
format.html { render :edit }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
def destroy
authorize #item
#item.destroy
respond_to do |format|
format.html { redirect_to items_url, notice: 'Item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_item
#item = Item.find(params[:id])
authorize #item
end
def item_params
params.require(:item).permit(:title, :description, :image, :price, :category_id)
end
end
application_contoller.rb
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery prepend: true
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
def pundit_user
current_seller || current_admin || current_viewer
end
private
def user_not_authorized(exception)
policy_name = exception.policy.class.to_s.underscore
flash[:warning] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
redirect_to(request.referrer || root_path)
end
end
Update 1
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
raise Pundit::NotAuthorizedError, "must be logged in" unless user
#user = user
#record = record
end
def index?
true # anybody can view
end
def show?
true # anybody can view
end
def search?
index?
end
def new?
create?
end
def edit?
update?
end
def destroy?
update?
end
private
# don't repeat yourself
def admin?
user.is_a?(Admin)
end
def seller?
user.is_a?(Seller)
end
end
class ItemPolicy < ApplicationPolicy
attr_reader :item
class Scope < Struct.new(:user, :scope)
def resolve
if admin?
scope.where(parent_id: nil)
elsif seller?
# avoids a query for user.items
scope.where(seller: user)
end
end
end
def initialize(user, record)
super(user, record)
#user = user
#item = record
end
def update?
admin? || is_owner?
end
def create?
# just guessing here
admin? || seller?
end
private
def is_owner?
# or whatever the association between the item and its owner is
item.seller == user
end
end
You are confusing scopes and the authorization methods in Pundit. The new?, show? etc. methods should return a boolean indicating if the user is allowed to perform the action at all.
To allow unauthorized users to perform an action you simply return true.
Scopes are used to narrow down which records the user has access to. They only have a resolve method.
class ApplicationPolicy
# ...
private
# don't repeat yourself
def admin?
user.is_a?(Admin)
end
def seller?
user.is_a?(Seller)
end
end
class ItemPolicy < ApplicationPolicy
attr_reader :item
class Scope < Struct.new(:user, :scope)
def resolve
if admin?
scope.where(parent_id: nil)
elsif seller?
# avoids a query for user.items
scope.where(seller: user)
end
end
end
def initialize(user, record)
super(user, record)
#user = user
#item = record
end
def update?
admin? || is_owner?
end
def index?
true # anybody can view
end
def show?
true # anybody can view
end
def search?
index?
end
def create?
# just guessing here
admin? || seller?
end
def new?
create?
end
def edit?
update?
end
def destroy?
update?
end
private
def is_owner?
# or whatever the association between the item and its owner is
item.seller == user
end
end
Instead of repeating yourself (the conditions) you can shortcut many of the actions since the permissions for editing for example is the same as updating. You can even do this in the ApplicationPolicy so that you don't have to repeat it in each policy class:
class ApplicationPolicy
# ...
def index?
true # anybody can view
end
def show?
true # anybody can view
end
def search?
index?
end
def new?
create?
end
def edit?
update?
end
def destroy?
update?
end
private
# don't repeat yourself
def admin?
user.is_a?(Admin)
end
def seller?
user.is_a?(Seller)
end
end
class ItemPolicy < ApplicationPolicy
attr_reader :item
class Scope < Struct.new(:user, :scope)
def resolve
if admin?
scope.where(parent_id: nil)
elsif seller?
# avoids a query for user.items
scope.where(seller: user)
end
end
end
def initialize(user, record)
super(user, record)
#user = user
#item = record
end
def update?
admin? || is_owner?
end
def create?
# just guessing here
admin? || seller?
end
private
def is_owner?
# or whatever the association between the item and its owner is
item.seller == user
end
end
You are also authorizing the user twice at many places in your controller as it is as already performed by the set_item callback:
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update, :destroy]
def index
authorize Item
#items = policy_scope(Item)
end
def search
if params[:term]
#items = Item.search(params[:term]).order("created_at DESC")
else
#items = Item.none # Don't use [] as #items.none? for example would blow up.
end
end
def show
#comments = Comment.where(item_id: #item).order("created_at DESC")
authorize #item
end
def new
#item = authorize(Item.new)
#categories = Category.order(:name)
end
def edit
#categories = Category.order(:name)
end
def create
#item = authorize(Item.new(item_params))
respond_to do |format|
if #item.save
format.html { redirect_to #item, notice: 'Item was successfully created.' }
format.json { render :show, status: :created, location: #item }
else
format.html { render :new }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #item.update(item_params)
format.html { redirect_to #item, notice: 'Item was successfully updated.' }
format.json { render :show, status: :ok, location: #item }
else
format.html { render :edit }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
def destroy
#item.destroy
respond_to do |format|
format.html { redirect_to items_url, notice: 'Item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_item
#item = authorize( Item.find(params[:id]) )
end
def item_params
params.require(:item).permit(:title, :description, :image, :price, :category_id)
end
end

Consider a hash which can be accessed and updated anywhere in a rails application without a database

An application which performs CRUD operations without the database accessing data via csv file .I wanna store the data from csv file into the hash . I have considered this method but end up errors .
employee.rb
class Employee
include ActiveModel::Serializers::JSON
include ActiveModel::Validations
include ActiveModel::Model
include ActiveModel::Dirty
attr_accessor :id, :name , :email , :number , :salary
define_attribute_methods :id, :name , :email , :number , :salary
validates :name, presence: true, length: { maximum: 100 }
def attributes
{'id' => nil , 'name' => nil , 'email' => nil , 'number' => nil , 'salary' => nil }
end
def self.find(id)
p ' fof fof fof fof o'
p #employees
raw = Parse.get("employee", id.to_s)
employee = Employee.new
employee.id = raw["id"]
employee.name = raw["name"]
employee.email = raw["email"]
employee.number = raw["number"]
employee.salary = raw["salary"]
# etc for the others
p employee # Return the newly-created instance
end
def capitalized_name
name.capitalize
end
def self.all
ObjectSpace.each_object(self).to_a
end
end
employee_controller.rb
class EmployeesController < ApplicationController
require 'csv'
def index
CSV.foreach('data.csv') do |row|
#Employee.create!(row.to_hash)
a = []
a = row.inspect
p a
a = a.gsub(/(\[\"|\"\])/, '').split('", "')
p a
e = Employee.new
e.id = a[0]
e.name = a[1]
e.email = a[2]
e.number = a[3]
e.salary = a[4]
#m = e.serializable_hash
# m = m.keys.zip(a).to_h
employee_values = e.instance_values
all = Data.instance
all.add("e.i = employee_values" )
end
#employees = ::Employee.all
p #employees
p "blah blah blah"
p all.keys
end
def new
#employee = Employee.new
end
def edit
#employee = Employee.find(params[:id])
end
def create
#employee = Employee.new(employee_params)
respond_to do |format|
if #employee.save
format.html { redirect_to #employee, notice: 'Employee was successfully created.' }
format.json { render :show, status: :created, location: #employee }
else
format.html { render :new }
format.json { render json: #employee.errors, status: :unprocessable_entity }
end
end
end
def destroy
#employee.destroy
respond_to do |format|
format.html { redirect_to employees_url, notice: 'Employee was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_employee
#employee = Employee.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def employee_params
params.require(:employee).permit(:id ,:name, :hiredate, :salary)
end
end
Then created a subclass for Hash to be accessed anywhere and saved it in initializers as creatting a global variable is bad practice
require 'singleton'
class Data < Hash
include Singleton
def initialize
super([])
end
def add src
src.to_s.split(";").each do |item|
splitted = item.split("=")
self[splitted[0]] = splitted[1]
end
end
end

Updating in stock quantity based on shopping cart quantity in rails app?

I'm working on a E Commerce app and I can´t figure out how I can update the product stock quantity when the user adds product to the cart.
I followed a tutorial for most of this app since I'm a total newbie. But the tutorial doesn't go into how to update the product stock quantity when the user adds product to the cart.
so far I've added this method to the cart.rbmodel
def upd_quantity
if cart.purchased_at
product.decrement!(quantity: params[:stock_quantity])
end
end
But I´m really stuck and don't know what I'm doing
It would be great if someone could take a look at this and advise me how to implement this function to the app.
here is a link to the github repo https://github.com/DadiHall/brainstore
this what I have at the moment.
cart_item.rb model
class CartItem
attr_reader :product_id, :quantity
def initialize product_id, quantity = 1
#product_id = product_id
#quantity = quantity
end
def increment
#quantity = #quantity + 1
end
def product
Product.find product_id
end
def total_price
product.price * quantity
end
def upd_quantity
if cart.purchased_at
product.decrement!(quantity: params[:stock_quantity])
end
end
end
cart.rbmodel
class Cart
attr_reader :items
def self.build_from_hash hash
items = if hash ["cart"] then
hash["cart"] ["items"].map do |item_data|
CartItem.new item_data["product_id"], item_data["quantity"]
end
else
[]
end
new items
end
def initialize items = []
#items = items
end
def add_item product_id
item = #items.find { |item| item.product_id == product_id }
if item
item.increment
else
#items << CartItem.new(product_id)
end
end
def empty?
#items.empty?
end
def count
#items.length
end
def serialize
items = #items.map do |item|
{
"product_id" => item.product_id,
"quantity" => item.quantity
}
end
{
"items" => items
}
end
def total_price
#items.inject(0) { |sum, item| sum + item.total_price }
end
end
product.rb model
class Product < ActiveRecord::Base
mount_uploader :image, ImageUploader
validates_presence_of :name, :price, :stock_quantity
validates_numericality_of :price, :stock_quantity
belongs_to :designer
belongs_to :category
belongs_to :page
def self.search(query)
where("name LIKE ? OR description LIKE ?", "%#{query}%", "%#{query}%")
end
end
`cart_controller.rb`
class CartsController < ApplicationController
before_filter :initialize_cart
def add
#cart.add_item params[:id]
session["cart"] = #cart.serialize
product = Product.find params[:id]
redirect_to :back, notice: "Added #{product.name} to cart."
end
def show
end
def checkout
#order_form = OrderForm.new user: User.new
#client_token = Braintree::ClientToken.generate
end
def remove
cart = session['cart']
item = cart['items'].find { |item| item['product_id'] == params[:id] }
if item
cart['items'].delete item
end
redirect_to cart_path
end
end
Does adding this line:
product.update_columns(stock_quantity: product.stock_quantity - 1)
To your add action in the CartsController do the trick?
def add
#cart.add_item params[:id]
session["cart"] = #cart.serialize
product = Product.find params[:id]
product.update_columns(stock_quantity: product.quantity - 1)
redirect_to :back, notice: "Added #{product.name} to cart."
end
Try this for removing the product from cart:
def remove
cart = session['cart']
item = cart['items'].find { |item| item['product_id'] == params[:id] }
product = Product.find(item['product_id'])
product.update_columns(stock_quantity: product.stock_quantity + 1)
if item
cart['items'].delete item
end
redirect_to cart_path
end
Note, this will only work if you are adding and removing 1 item/product at a time. I suggest renaming 'item' to 'product' in your remove action for consistency.

Receiving the error "Couldn't find Product with id=5" when I click on view cart link in my app

I have a "view cart" link which returns the following error when clicked:
Couldn't find Product with id=5
My products_controller.rb file looks like this:
class ProductsController < ApplicationController
# GET /products
# GET /products.json
def index
#products = Product.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #products }
end
end
# GET /products/1
# GET /products/1.json
def show
#product = Product.find(params[:id])
logger.debug("Event code is: #{params[:id]}")
respond_to do |format|
format.html # show.html.erb
format.json { render json: #product }
end
end
# GET /products/new
# GET /products/new.json
def new
#product = Product.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #product }
end
end
# GET /products/1/edit
def edit
#product = Product.find(params[:id])
end
# POST /products
# POST /products.json
def create
#product = Product.new(params[:product])
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render json: #product, status: :created, location: #product }
else
format.html { render action: "new" }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PUT /products/1
# PUT /products/1.json
def update
#product = Product.find(params[:id])
respond_to do |format|
if #product.update_attributes(params[:product])
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product = Product.find(params[:id])
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
def add_to_cart
#products = cookies[:products]
if #products.blank?
#products = cookies[:products] = params[:id]
else
unless #products.include? params[:id]
cookies[:products] = #products + '&&' + params[:id]
end
end
redirect_to products_url
end
def remove_from_cart
#current_products = cookies[:products]
if #current_products.blank?
redirect_to products_url
else
#current_products = #current_products.split("&&")
#current_products.delete(params[:id])
#current_products = #current_products.join("&&")
cookies[:products] = #current_products
redirect_to products_url
end
end
def view_cart
#products = cookies[:products].split("&&").map { |s| s.to_i }
end
end
My view_cart.html.erb file looks like this:
<h1>Your Cart</h1>
<table>
<tr>
<th>Name</th>
<th>Price</th>
<th></th>
<th></th>
<th></th>
</tr>
<% total = 0 %>
<% #products.each do |product| %>
<tr>
<td><%= Product.find(product).name %></td>
<td><%= Product.find(product).price %></td>
<% total += Product.find(product).price %>
</tr>
<% end %>
</table>
Total: <%= total %>
I am a Rails novice and would appreciate some help with this.
You don't need to use find since you already have all #products. You iterate over that collection with each and you can access each element attributes like that:
<% #products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= product.price %></td>
<% total += product.price %>
</tr>
<% end %>
i.e. product in the block is already "found" :)
We've done a cart implementation before (based on this Railscast):
(more explained below)...
Fix
Your error stems from the fact you're trying to find a product which doesn't exist.
There are a lot of problems with your code (for example, using cart methods inside your products controller). The simple fix is as follows:
#app/controllers/products_controller.rb
class ProductsController < ApplicationController
def cart_view
#products = cart_contents
end
private
def cart_contents
##Cart product ID's
products = cookies[:products].split("&&").map { |s| s.to_i }
##Only proceed if user has products in cart
if (products && products != {})
#Determine Quantities (if ID appears 2 times etc)
quantities = Hash[products.uniq.map {|i| [i, products.count(i)]}]
#Get products from DB
products_array = Product.find(products.uniq)
#Create Qty Array with "qty" attached
products_new = {}
products_array.each{
|a| products_new[a] = {"qty" => quantities[a.id.to_s]}
}
#Output appended
return products_new
end
end
end
This is code we use (explained further down page) and will basically give you an ActiveRecord collection for your view.
So you'll be able to use the following:
#app/views/products/view_cart.html.erb
<% #products.each do |product| %>
<%= product.name %>
<% end %>
Structure
As mentioned, we've implemented this before:
#config/routes.rb
resources :cart, only: [:index, :create, :destroy]
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def cart_session
#cart_session ||= CartSession.new(session)
end
helper_method :cart_session
end
#app/controllers/cart_controller.rb
class CartController < ApplicationController
include ApplicationHelper
#Index
def index
#items = cart_session.cart_contents
end
#Add
def create
session[:cart] ||={}
products = session[:cart][:products]
#If exists, add new, else create new variable
if (products && products != {})
session[:cart][:products] << params[:id]
else
session[:cart][:products] = Array(params[:id])
end
#Handle the request
respond_to do |format|
format.json { render json: cart_session.build_json }
format.html { redirect_to cart_index_path }
end
end
#Delete
def destroy
session[:cart] ||={}
products = session[:cart][:products]
id = params[:id]
all = params[:all]
#Is ID present?
unless id.blank?
unless all.blank?
products.delete(params['id'])
else
products.delete_at(products.index(id) || products.length)
end
else
products.delete
end
#Handle the request
respond_to do |format|
format.json { render json: cart_session.build_json }
format.html { redirect_to cart_index_path }
end
end
end
The above gives you a cart_session method, which creates or invokes the CartSession model. This is just a class which puts all the user's "cart items" in a session.
The important thing to note is that because the cart controller is separate to the products controller, it allows you to split your code into a resourceful structure.
It also means you keep your code extremely lean - the only overhead will be a small array of product IDs kept in a session variable. No ActiveRecord or anything...
#app/models/cart_session.rb
class CartSession
#Initalize Cart Session
def initialize(session)
#session = session
#session[:cart] ||= {}
end
#Cart Count
def cart_count
if (#session[:cart][:products] && #session[:cart][:products] != {})
#session[:cart][:products].count
else
0
end
end
#Cart Contents
def cart_contents
products = #session[:cart][:products]
if (products && products != {})
#Determine Quantities
quantities = Hash[products.uniq.map {|i| [i, products.count(i)]}]
#Get products from DB
products_array = Product.find(products.uniq)
#Create Qty Array
products_new = {}
products_array.each{
|a| products_new[a] = {"qty" => quantities[a.id.to_s]}
}
#Output appended
return products_new
end
end
#Qty & Price Count
def subtotal
products = cart_contents
#Get subtotal of the cart items
subtotal = 0
unless products.blank?
products.each do |a|
subtotal += (a[0]["price"].to_f * a[1]["qty"].to_f)
end
end
return subtotal
end
#Build Hash For ActiveMerchant
def build_order
#Take cart objects & add them to items hash
products = cart_contents
#order = []
products.each do |product|
#order << {name: product[0].name, quantity: product[1]["qty"], amount: (product[0].price * 100).to_i }
end
return #order
end
#Build JSON Requests
def build_json
session = #session[:cart][:products]
json = {:subtotal => self.subtotal.to_f.round(2), :qty => self.cart_count, :items => Hash[session.uniq.map {|i| [i, session.count(i)]}]}
return json
end
end
This allows you to use the following:
#app/views/cart/index.html.erb
<% #items.each do |item| %>
<%= item.name %> #=> this will be the ActiveRecord "Product" record
<% end %>
You'll also be able to do the following:
#app/views/products/show.html.erb
<%= link_to "Add To Cart", cart_path(#product.id), method: :post %> #-> adds product to cart
The best thing about this method is that the cart functionality is split into its own controller & model. At the moment, you've broken the resourceful convention by including non-rest methods in your products controller.
You need to keep your cart functionality in its own controller, and products functionality in its own controller. The above achieves this.

Rails 4 : find or create method

I have an association between experience and company where company has_many :experiences and experience belongs_to :company, Now I want to design this: if a user enters a company name that already exist in the company model it will assign to it but if the user put a company name that doesn't already exist in company model - the company must persist but not be created as a new record (I don't want to use find_or_create method and the find_by doesn't seem working for this situation)
Edit
this is my Company controller
def allcompanies
#companies = Company.paginate(page: params[:page], per_page: 10).order("created_at DESC")
end
def show
#company = Company.find_by_slug(params[:id])
if #company
render action: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
end
def index
#companies = Company.limit(19).order("id DESC")
end
def new
#company = Company.new
end
def edit
end
def create
#company = Company.new(company_params)
respond_to do |format|
if #company.save
flash[:notice] = "Entreprise '#{#company.name}' Crée!"
format.html { redirect_to #company}
else
format.html { render action: 'new' }
end
end
end
def update
respond_to do |format|
if #company.update(company_params)
flash[:notice] = "Entreprise '#{#company.name}' à été mis à jour"
format.html { redirect_to #company }
else
format.html { render action: 'edit' }
end
end
end
def destroy
#company.destroy
respond_to do |format|
format.html { redirect_to companies_url }
end
end
private
def set_company
#company = Company.find_by_slug(params[:id])
end
def company_params
params.require(:company).permit(:name, :company_description, :country, :city, :company_status, :company_size, :company_website, :sector_ids, :job_id, :companylogo)
end
and this is my experience model that actually create a new record for each company
belongs_to :profile
belongs_to :company
validates :company_name, presence: true
def company_name
company.try(:name)
end
def company_name=(name)
self.company = Company.find_or_initialize_by(name: name)
end
OK, so you want some companies to be visible and some not.
Then, you can create a corresponding boolean field, like public_visible and set it to false for companies you don't know(ie created by application users).
In your controller do something like this:
#company = Company.find_by_name(params[:company][:name])
if #company.blank?
#company = Company.create(params[:company].merge({ public_visible: false }))
end
#company.experiences.create(...)
it is just an example, since I don't know your real conditions on companies creation, so you need to adjust it according to your needs.

Resources