Rails How to pass params in cross model system - ruby-on-rails

I am unable to figure out the method to pass params to a link tag. What I want to do is When someone clicks on the Join Group link, the Membership model shall have a new row with group_id as the current group id and the user id as the current user id. The Membership model currently consists of two columns : user_id and group_id that maps users to groups. Can anyone help me with the mistake I am making.
Here is the code
Groups : show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= #group.title %>
</p>
<p>
<strong>Desc:</strong>
<%= #group.desc %>
</p>
<p>
<strong>Creator:</strong>
<%= #creator.first_name %>
</p>
<%= link_to 'Join Group', memberships_path(:group_id => #group.id, :user_id => current_user.id ), method: :post %>
<%= link_to 'Edit', edit_group_path(#group) %> |
<%= link_to 'Back', groups_path %>
and here is the Memberships controller
class MembershipsController < ApplicationController
before_action :set_membership, only: [:show, :edit, :update, :destroy]
# GET /memberships
# GET /memberships.json
def index
#memberships = Membership.all
end
# GET /memberships/1
# GET /memberships/1.json
def show
#membership = Membership.find(params[:id])
#user = User.find(#membership.user_id)
#group = Group.find(#membership.group_id)
end
# GET /memberships/new
def new
#membership = Membership.new
end
# GET /memberships/1/edit
def edit
end
# POST /memberships
# POST /memberships.json
def create
#membership = Membership.new(membership_params)
respond_to do |format|
if #membership.save
format.html { redirect_to #membership, notice: 'Membership was successfully created.' }
format.json { render :show, status: :created, location: #membership }
else
format.html { render :new }
format.json { render json: #membership.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /memberships/1
# PATCH/PUT /memberships/1.json
def update
respond_to do |format|
if #membership.update(membership_params)
format.html { redirect_to #membership, notice: 'Membership was successfully updated.' }
format.json { render :show, status: :ok, location: #membership }
else
format.html { render :edit }
format.json { render json: #membership.errors, status: :unprocessable_entity }
end
end
end
# DELETE /memberships/1
# DELETE /memberships/1.json
def destroy
#membership.destroy
respond_to do |format|
format.html { redirect_to memberships_url, notice: 'Membership was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_membership
#membership = Membership.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def membership_params
params.require(:membership).permit(:user_id, :group_id)
end
end

You should have a method in your controller that handles adding a user to a group, something like:
class MembershipsController < ApplicationController
...
def join_group
#user = User.find(params[:user]
#user.group_id = params[:group_id].to_i
end
...
end
Then routes.rb needs a path to that controller method:
get 'memberships/join_group' => 'memberships#join_group'
which will result in a path like memberships_join_group_path that you will use in your link_to:
<%= link_to 'Join Group', memberships_join_group_path(:group_id => #group.id, :user_id => current_user.id ) %>
The path you're currently using is sending params to your index method.

try
def create
#member = current_user.members.build(:group_id => params[:group_id])
if #member.save
flash[:notice] = "You have joined this group."
redirect_to members_path
else
flash[:error] = "Unable to join."
redirect_to members_path
end
end
and use memberships instead of members

Related

Simple search in the database

I have a problem with a simple browser in my application.
I have already looked for solutions but still displays the following error:
param is missing or the value is empty: expense.
Please help.
Index:
<%= form_tag expenses_path :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search" , name: nil %>
Controller:
class ExpensesController < ApplicationController
before_action :set_expense, only: [:show, :edit, :update, :destroy]
# GET /expense expense
# GET /expense.json
def index
#expenses = Expense.search(params[:search])
end
# GET /expense/1
# GET /expense/1.json
def show
end
# GET /expense/new
def new
#expense = Expense.new
end
# GET /expense/1/edit
def edit
end
# POST /expense
# POST /expense.json
def create
#expense = Expense.new(expense_params)
respond_to do |format|
if #expense.save
format.html { redirect_to #expense, notice: 'zostały zapisane.' }
format.json { render :show, status: :created, location: #expense }
else
format.html { render :new }
format.json { render json: #expense.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /expense/1
# PATCH/PUT /expense/1.json
def update
respond_to do |format|
if #expense.update(expense_params)
format.html { redirect_to #expense, notice: 'expense was successfully updated.' }
format.json { render :show, status: :ok, location: #expense }
else
format.html { render :edit }
format.json { render json: #expense.errors, status: :unprocessable_entity }
end
end
end
# DELETE /expense/1
# DELETE /expense/1.json
def destroy
#expense.destroy
respond_to do |format|
format.html { redirect_to #expense, notice: 'Zakupy zostały usunięte.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_expense
#expense = Expense.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def expense_params
params.require(:expense).permit(:date, :price, :category, :where)
end
Expense.rb:
class Expense < ApplicationRecord
def self.search(search)
if search
where (['where LIKE ?',"%#{search}%"])
else
all
end
end
permit the search in your params
def expense_params
params.require(:expense).permit(:date, :price, :category, :where, :search)
end
please correct the form_tag syntax
<%= form_tag(expenses_path,method: :get) do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search" , name: nil %>
<% end %>
The error message you report is most likely coming from your expense_params method:
params.require(:expense) means you expect the parameters to be of the form params[:expense][:date], params[:expense][:price], etc.
My best guess is that your form is not actually submitting a GET request and so it's going to the create method rather than the index method.
I think this may be occurring because you are missing a comma between expenses_path and :method => 'get' in your form_tag. It should be:
<%= form_tag expenses_path, :method => 'get' do %>

How to update created_by field in scaffolding generated code?

I use devise gem for authentication. I generated a scaffold for model M. I would like to update the created_by field with the user id from the login page. How do I achieve this?
I have 2 fields in the model F1 and F2.
The form that scaffold creates shows input for users to enter values for F1 and F2. How do I update the value for created_by field using the current_user from devise? Because the create action seems to be entering only the fields from the form.
<%= form_with(model: M, local: true) do |form| %>
<% if M.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(M.errors.count, "error") %> prohibited this movie from being saved:</h2>
<ul>
<% M.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :F1 %>
<%= form.text_field :F1 %>
</div>
<div class="field">
<%= form.label :F2 %>
<%= form.text_field :F2 %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
How to I update the model with current_user value in the above form without exposing that field to the user?
This is my controller:
class MsController < ApplicationController
before_action :set_M, only: [:show, :edit, :update, :destroy]
# GET /Ms
# GET /Ms.json
def index
#Ms = M.all
#categories = #Ms.uniq.pluck(:category)
#Ms_by_category = Hash.new
#categories.each do |category|
#Ms_by_category[category] = M.where(:category => category)
end
end
# GET /Ms/1
# GET /Ms/1.json
def show
end
# GET /Ms/new
def new
#M = M.new
end
# GET /Ms/1/edit
def edit
end
# POST /Ms
# POST /Ms.json
def create
#M = M.new(M_params)
respond_to do |format|
if #M.save
format.html { redirect_to #M, notice: 'M was successfully created.' }
format.json { render :show, status: :created, location: #M }
else
format.html { render :new }
format.json { render json: #M.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /Ms/1
# PATCH/PUT /Ms/1.json
def update
respond_to do |format|
if #M.update(M_params)
format.html { redirect_to #M, notice: 'M was successfully updated.' }
format.json { render :show, status: :ok, location: #M }
else
format.html { render :edit }
format.json { render json: #M.errors, status: :unprocessable_entity }
end
end
end
# DELETE /Ms/1
# DELETE /Ms/1.json
def destroy
#M.destroy
respond_to do |format|
format.html { redirect_to Ms_url, notice: 'M was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_M
#M = M.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def M_params
params.require(:M).permit(:title, :category, :rating)
end
end
So simple in creating action change your method, for example, you just need to create the client
before_action :authenticate_user!
def create
#client = Client.new(name: params[:name], address: params[:address],created_by: current_user.email )
if #client.save
redirect_to #client
else
render 'new'
end
end
There should be a field like created_by exist in the table.
You need to add users reference to M model and add associations. created_by is not the best name for it. Let imagine that M is abbreviation for Music. In this case you need to create a migration
add_reference :musics, :user
Add to the Music model
belongs_to :user
And to the User model
has_many :musics
And change in the controller
def new
#music = current_user.musics.new
end
def create
#music = current_user.musics.new(M_params)
respond_to do |format|
if #music.save
format.html { redirect_to #music, notice: 'Music was successfully created.' }
format.json { render :show, status: :created, location: #music }
else
format.html { render :new }
format.json { render json: #music.errors, status: :unprocessable_entity }
end
end
end

Rails model form f.select do not assign selected value to model key

sorry for this question but I'm struggling with this issue for hours now and can't find the answer anywhere.
Here is the thing, I have a rails app with "Reservation" and "Space" models with the following relations:
class Reservation < ActiveRecord::Base
belongs_to :space
belongs_to :user
end
class Space < ActiveRecord::Base
belongs_to :condo
has_many :reservations
end
When the user creates a new Reservation, in the form he gets to choose from a dropdown (f.select) the spaces available for him. The f.select in the form look like this:
<div class="field">
<%= #user_spaces = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user_spaces, :id, :name), :prompt => "Select space"
%>
</div>
That select it supose to assign a value to the key "space_id" in the Reservation that is being created (column's table is created). But when I check the last reservation in Rails console, space_id value is "nil". What am I doing wrong?
Thank you very much for your help
Reservation controller file:
class ReservationsController < ApplicationController
before_action :set_reservation, only: [:show, :edit, :update, :destroy]
# GET /reservations
# GET /reservations.json
def index
#reservations = Reservation.all
end
# GET /reservations/1
# GET /reservations/1.json
def show
end
# GET /reservations/new
def new
#reservation = Reservation.new
end
# GET /reservations/1/edit
def edit
end
# POST /reservations
# POST /reservations.json
def create
#reservation = Reservation.new(reservation_params)
#user = current_user.id
#reservation.user_id = #user
respond_to do |format|
if #reservation.save
format.html { redirect_to #reservation, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
else
format.html { render :new }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reservations/1
# PATCH/PUT /reservations/1.json
def update
respond_to do |format|
if #reservation.update(reservation_params)
format.html { redirect_to #reservation, notice: 'Reservation was successfully updated.' }
format.json { render :show, status: :ok, location: #reservation }
else
format.html { render :edit }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reservations/1
# DELETE /reservations/1.json
def destroy
#reservation.destroy
respond_to do |format|
format.html { redirect_to reservations_url, notice: 'Reservation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_reservation
#reservation = Reservation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def reservation_params
params.require(:reservation).permit(:eventdate)
end
end
Space controller file:
class SpacesController < ApplicationController
before_action :set_space, only: [:show, :edit, :update, :destroy]
# GET /spaces
# GET /spaces.json
def index
#spaces = Space.all
end
# GET /spaces/1
# GET /spaces/1.json
def show
end
# GET /spaces/new
def new
#space = Space.new
end
# GET /spaces/1/edit
def edit
end
# POST /spaces
# POST /spaces.json
def create
#space = Space.new(space_params)
respond_to do |format|
if #space.save
format.html { redirect_to #space, notice: 'Space was successfully created.' }
format.json { render :show, status: :created, location: #space }
else
format.html { render :new }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /spaces/1
# PATCH/PUT /spaces/1.json
def update
respond_to do |format|
if #space.update(space_params)
format.html { redirect_to #space, notice: 'Space was successfully updated.' }
format.json { render :show, status: :ok, location: #space }
else
format.html { render :edit }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# DELETE /spaces/1
# DELETE /spaces/1.json
def destroy
#space.destroy
respond_to do |format|
format.html { redirect_to spaces_url, notice: 'Space was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_space
#space = Space.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def space_params
params.require(:space).permit(:name)
end
end
And full Reservation Form:
<%= form_for(#reservation) do |f| %>
<% if #reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reservation.errors.count, "error") %> prohibited this reservation from being saved:</h2>
<ul>
<% #reservation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :eventdate %><br>
<%= f.date_select :eventdate %>
</div>
<div class="field">
<%= #user = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user, :id, :name), :prompt => "Select space"
%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
pretty sure you need to permit the space_id attribute in your strong params.
def reservation_params
params.require(:reservation).permit(:eventdate, :space_id)
end
whats happening is that when you go to create a reservation, youre passing in set of params, that is the output of reservation_params
#reservation = Reservation.new(reservation_params)
if space_id is not being permitted in your strong params, then it will be nil when created.
if this is not the issue, can you post what params are getting to the server, and what the output of reservation_params are.

Rails 4: Unable to create checkout

I'm having a hard time implementing a checkout process where once at the cart, user can checkout and have order shipped. Maybe I need an order model and transaction controller?
I'm just not sure how to set those up. Currently the cart works and can be cleared as well as have items be added, its just I'm not sure how to implement a checkout and order system.
Idea is: User at cart clicks the checkout button, then is taken to checkout where he/she can input payment information, then taken back to products page. Issue is I'm not sure again how to connect the cart to the checkout and payment process into one simple easy system.
Any help would be appreciated, I'm still very new at this. Thank you.
class CartController < ApplicationController
before_action :authenticate_user!, except: [:index]
def add
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
flash[:notice] = 'added to cart'
end
def clearCart
session[:cart] = nil
redirect_to :action => :index
flash[:notice] = 'cart cleared'
end
def index
if session[:cart] then
#cart = session[:cart]
else
#cart = {}
end
end
end
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
def index
#products = Product.all
end
def show
end
def new
#product = Product.new
end
def edit
end
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_product
#product = Product.find(params[:id])
end
def product_params
params.require(:product).permit(:title, :description, :price, :category, :subcategory)
end
end
class Product < ActiveRecord::Base
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
views/cart/index.html.erb
<h1>Your Cart</h1>
<% if #cart.empty? %>
<p> Your cart is currently empty</p>
<% else %>
<%= link_to 'Empty your Cart', cart_clear_path %>
<br><br>
<% end %>
<% total = 0 %>
<ul>
<% #cart.each do | id, quantity | %>
<% product = Product.find_by_id(id) %>
<li>
<%= link_to product.title, product %>
<p><%= product.description %></p>
<p><%= number_to_currency product.price %></p>
<p>Quantity: <%= quantity %></p>
</li>
<% total += quantity * product.price %>
<% end %>
<p><b><%= number_to_currency total, :unit => '$' %> </b></p>
</ul>
What I've tried below
order.rb
class Order < ActiveRecord::Base
belongs_to :cart
end
cart.rb
class Cart < ActiveRecord::Base
has_many :line_items
has_one :order
end
Orders_Controller.rb
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
# GET /orders
# GET /orders.json
def index
#orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
#order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
#order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:new, :cart_id, :ip_address, :first_name, :last_name, :user_id)
end
end
added Checkout to views/cart/index.html.erb
<%= link_to "Checkout", new_order_path, class: "btn btn-primary" %>
What do I do after this?
you've used a local variable product, not the controller attribute #product. (just add the '#' sign)
my advise to you is to use a gem like shoppe,
you can see example here (demo)
you can also navigate through the models of the gem to see how they did it, maybe it will give you a clear perspective of writing an e-commerce solution.

before_filter for nested resource

I have nested resources - users have_many manufacturers and manufacturers have_many lines. I wrote a before_filter to load the #manufacturer so it could go through the rest of the functions in the lines_controller. Problem is, I'm running into issues when I click edit on the lines/show view.
Error: Couldn't find Manufacturer with id=manufacturer_id
77 def load_manufacturer
78 #manufacturer = Manufacturer.find(params[:manufacturer_id])
79 end
So here's what I'm working with:
app/views/lines/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #line.name %>
</p>
<p>
<strong>Manufacturer:</strong>
<%= #line.manufacturer_id %>
</p>
<%= link_to 'Edit', edit_manufacturer_line_path(:manufacturer_id,#line) %> |
<%= link_to 'Back', manufacturer_lines_path(#line.manufacturer_id) %>
lines_controller.rb
class LinesController < ApplicationController
before_action :set_line, only: [:show, :edit, :update, :destroy]
before_filter :load_manufacturer
# GET /lines
# GET /lines.json
def index
#lines = Line.all
end
# GET /lines/1
# GET /lines/1.json
def show
end
# GET /lines/new
def new
#manufacturer = Manufacturer.find(params[:manufacturer_id])
#line = #manufacturer.lines.build
end
# GET /lines/1/edit
def edit
end
# POST /lines
# POST /lines.json
def create
#line = #manufacturer.lines.build(line_params)
respond_to do |format|
if #line.save
format.html { redirect_to manufacturer_line_path(#manufacturer, #line), notice: 'Line was successfully created.' }
format.json { render action: 'show', status: :created, location: #line }
else
format.html { render action: 'new' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /lines/1
# PATCH/PUT /lines/1.json
def update
respond_to do |format|
if #line.update(line_params)
format.html { redirect_to manufacturer_line_path(#manufacturer, #line), notice: 'Line was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# DELETE /lines/1
# DELETE /lines/1.json
def destroy
#line.destroy
respond_to do |format|
format.html { redirect_to manufacturer_lines_url(#manufacturer) }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line
#line = Line.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_params
params.require(:line).permit(:name, :manufacturer_id)
end
def load_manufacturer
#manufacturer = Manufacturer.find(params[:manufacturer_id])
end
end
This:
<%= link_to 'Edit', edit_manufacturer_line_path(:manufacturer_id,#line) %>
Should be
<%= link_to 'Edit', edit_manufacturer_line_path(#manufacturer,#line) %>
What is happening is it is changing the symbol :manufacturer_id to a string and passing it to the route so your route looks like
`/manufacturers/manufacturer_id/lines/###/edit`
when you want
/manufacturers/###/lines/###/edit

Resources