add automatically value to column database in rails - ruby-on-rails

notes use rails 5.2 and postgresql
I have Foluser model contains name,email,password,id_watch
I need when admin add new foluser
generate password
when admin create new foluser generate password like Secure Password Generator
get id_watch from admin model and put it to id_watch from Foluser model
Adminwhen register enterusername,email,password,id_watch`
in point 2 need take this id_watch and save it in user model .
admin only create foluser
`
class FolusersController < ApplicationController
before_action :set_foluser, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show, :new , :create, :edit]
# GET /folusers
# GET /folusers.json
def index
#folusers = current_master.foluser.all
#render json: #folusers
end
# GET /folusers/1
# GET /folusers/1.json
def show
##folusers = Foluser.where(master_id: #master.id).order("created_at DESC")
##foluser = Foluser.find(params[:id])
#render json: #foluser
end
# GET /folusers/new
def new
#foluser = current_master.foluser.build
end
# GET /folusers/1/edit
def edit
#render json: #foluser
end
# POST /folusers
# POST /folusers.json
def create
#foluser = current_master.foluser.build(foluser_params)
respond_to do |format|
if #foluser.save
format.html { redirect_to #foluser, notice: 'Foluser was successfully created.' }
format.json { render :show, status: :created, location: #foluser }
else
format.html { render :new }
format.json { render json: #foluser.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /folusers/1
# PATCH/PUT /folusers/1.json
def update
respond_to do |format|
if #foluser.update(foluser_params)
format.html { redirect_to #foluser, notice: 'Foluser was successfully updated.' }
format.json { render :show, status: :ok, location: #foluser }
else
format.html { render :edit }
format.json { render json: #foluser.errors, status: :unprocessable_entity }
end
end
end
# DELETE /folusers/1
# DELETE /folusers/1.json
def destroy
#foluser.destroy
respond_to do |format|
format.html { redirect_to folusers_url, notice: 'Foluser was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_foluser
#foluser = Foluser.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def foluser_params
params.require(:foluser).permit(:name, :email, :numberphone, :password)
end
end
foluser model
class Foluser < ApplicationRecord
belongs_to :admin, :optional => true
end
admin model
class Master < ApplicationRecord
has_many :foluser
end

Using your current code, setting the id_watch can be done here in the controller:
class FolusersController < ApplicationController
def create
#foluser = current_master.folusers.build(foluser_params)
#foluser.id_watch = current_master.id_watch # <-- !!!
respond_to do |format|
if #foluser.save
# ...
end
end
end
end
Despite our extended conversation above, I'm still unclear what you're trying to achieve with the "password generation".
(Should it be generated in the front-end, or the back-end? Should it be stored encrypted, or in plain text? If encrypted, do you need to be able to reverse this encryption? Is it a "permanent" password, or a "temporary" password? ...)
Therefore, the following code should be taken with a big pinch of salt - since I still don't really know what the desired/correct behaviour is.
In the FolusersController, you've defined the following method:
def foluser_params
params.require(:foluser).permit(:name, :email, :numberphone, :password)
end
However, if you want the password to be generated by the server then you shouldn't be allowing the admin to set the password through the controller. Therefore, remove this parameter:
def foluser_params
params.require(:foluser).permit(:name, :email, :numberphone)
end
And then somewhere - perhaps in the controller, or as a hook in the model - set this password to something random:
class FolusersController < ApplicationController
def create
#foluser = current_master.folusers.build(foluser_params)
#foluser.password = SecureRandom.hex(10 + rand(6))
# ...
end
end
# or
class Foluser < ApplicationRecord
after_initialize :default_password
def default_password
self.password ||= SecureRandom.hex(10 + rand(6))
end
end

I think you found the solution, use rails callbacks in your model to extract this kind of logic from the controller.
But I'd rather use after_initialize than before_save so that you won't set a default password before each save(so possibly even update action)
Then use things like SecureRandom (ActiveSupport concern) (already bundled by rails, no requires required)
after_initialize :defaultpassword
...
def default_password
self.password ||= SecureRandom.hex(10 + rand(6))
end
not the best way to do random I know but feel free to customize it.
secure_random output examples:
=>bf8d42b174d297f6460eef
=>efd28869171a1ec89c3438
=>3855c61fb6b90ed549d777

Related

Redirect to a post with specific name from user input in Ruby on Rails?

I am a newbie in RoR, thus sorry for stupid question :(
I have a Game model, with a code string. There is a welcome/index view in my app with a simple form_to input. I wish to redirect user to a Game with a specific code after he submits the form.
I understand that I should somehow combine a .where method and redirect_to in Welcome_controller, but I just can't figure out how...
Welcome_controller.rb:
class WelcomeController < ApplicationController
def index
end
def redirect
redirect_to ?game with a code that equals :param from input?
end
end
Welcome/index:
<h1>Let's join the game!</h1>
<%= form_tag redirect_path do %>
<%= text_field_tag(:param) %>
<%= submit_tag("Search") %>
<% end %>
routes.rb:
Rails.application.routes.draw do
get 'welcome/index'
resources :games
get 'games/index'
root 'welcome#index'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
game.rb:
class Game < ApplicationRecord
validates :name, :presence => true
end
games_controller:
PREFACE = ('A'..'Z').to_a << ?_
SUFFIX = ('0'..'9').to_a
PREFACE_SIZE = 2
SUFFIX_SIZE = 3
class GamesController < ApplicationController
before_action :set_game, only: %i[ show edit update destroy ]
# GET /games or /games.json
def index
#games = Game.all
end
# GET /games/1 or /games/1.json
def show
end
# GET /games/new
def new
#game = Game.new
#game.code = gen_name
end
def gen_name
PREFACE.sample(PREFACE_SIZE).join << SUFFIX.sample(SUFFIX_SIZE).join
end
# GET /games/1/edit
def edit
end
# POST /games or /games.json
def create
#game = Game.new(game_params)
respond_to do |format|
if #game.save
format.html { redirect_to game_url(#game), notice: "Game was successfully created." }
format.json { render :show, status: :created, location: #game }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /games/1 or /games/1.json
def update
respond_to do |format|
if #game.update(game_params)
format.html { redirect_to game_url(#game), notice: "Game was successfully updated." }
format.json { render :show, status: :ok, location: #game }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
end
end
# DELETE /games/1 or /games/1.json
def destroy
#game.destroy
respond_to do |format|
format.html { redirect_to games_url, notice: "Game was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_game
#game = Game.find(params[:id])
end
# Only allow a list of trusted parameters through.
def game_params
params.require(:game).permit(:code, :name)
end
end
In config/routes.rb you have defined resources :games, which creates default paths for CRUD actions. For the show action, which you are trying to get here, it would lead to /games/:id and the helper method would be game_path. You can also check this by running rails routes -c games command in the app directory. It should return all paths for games_controller
In the before_action callback for GamesController#show action, you are finding a Game object using Game.find(params[:id]). :id parameter is what you need to pass to the path helper that I mentioned earlier for the action to fire properly, so the path to a specific game would look like game_path(id: game.id). This will then automatically get converted to params. Alternatively, you can just pass the game object to the path helper and it will do the job for you like this: game_path(game)
Now in the WelcomeController#redirect action, you get the game code in params from the form submit. You need to first find the game for the submitted code like this:
game = Game.find_by(code: params[:param])
This should work if the code is unique for each game. Now that you have the correct game record, all you need is to redirect to the path that I've mentioned eariler:
redirect_to game_path(game)

Basic rails crud in ajax with devise

I have a basic CRUD in rails and ajax, but I need to integrate Devise gem, when adding devise gem to my project and test the CRUD, I get this error:
the controller code in rails 4.2:
class ProductsController < ApplicationController
before_action :authenticate_user!
before_action :product_find, only: [:show, :update, :destroy, :edit]
def index
#products = Product.all.order('created_at DESC')
end
def show
end
def new
#product = Product.new
respond_to do |format|
format.html { render layout: false }
format.json { render json: #product }
format.js
end
end
def create
#product = current_user.products.build(product_params)
respond_to do |format|
if #product.save
format.json { render :show, status: :created, location: #product}
format.js
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
format.js
end
end
end
def edit
end
def update
#product = Product.update(params[:id], product_params)
end
def destroy
#product.destroy
end
private
def product_find
#product = Product.where(id: params[:id]).first
end
def product_params
params.require(:product).permit(:name, :quantity, :price)
end
end
The user can connect without problems, the error occurs when I create a new product with the registered user
what am I doing wrong?
I think the error may be in the CREATE and NEW method
thank!
Have you set up the associations correctly for your models? The error undefined method 'products' for <User> suggests that you haven't.
# user.rb
has_many :products
# product.rb
belongs_to :user
Make sure you also have a user_id field on the Product model.

Devise - How to display user that updated others post

I would like users to be able to create/update my "Person" resource, including overwriting each other. Currently I'm able to capture the user who created the initial "Person" but i can't figure out how to capture and display the user that updated the resource.
For example if user 1 creates an item, then user 2 updates this item, I would like to display that this item was most recently edited by user 2.
Here's my controller, any help would be much appreciated thanks!
class PeopleController < ApplicationController
before_action :set_person, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /people
# GET /people.json
def index
#people = Person.all
end
# GET /people/1
# GET /people/1.json
def show
end
# GET /people/new
def new
#person = current_user.person.build
end
# GET /people/1/edit
def edit
end
# POST /people
# POST /people.json
def create
#person = current_user.person.build(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render action: 'show', status: :created, location: #person }
else
format.html { render action: 'new' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /people/1
# PATCH/PUT /people/1.json
def update
respond_to do |format|
if #person.update(person_params)
format.html { redirect_to #person, notice: 'Person was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# DELETE /people/1
# DELETE /people/1.json
def destroy
#person.destroy
respond_to do |format|
format.html { redirect_to people_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_person
#person = Person.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def person_params
params.require(:person).permit(:name, :twitter, :facebook, :instagram, :vine)
end
end
Simple way for doing it is to maintain the a column called updated_by and store the current user when its updated as #Andrey mentioned in previous comment.
But if your looking for a more extensive for tracking you can use auditable gem
You can check this out :
https://github.com/harley/auditable
Create updated_by column in posts table, and each time user updates the post, update the column updated_by by the value of current_user.

Getting the ID of a Model that Uses Nested Routes and Permalinks in Rails

So I had my app set up with ids like so:
resources :studios do
resources :bookings
end
This gave me the route to the index (which later I'm going to use json for to get calendars for each studio.
studio_bookings GET /studios/:studio_id/bookings(.:format) bookings#index
This is good, but I wanted to get rid of the ID and use a permalink instead, just for a friendlier URL.
Change to:
namespace :studio, :path =>'/:permalink' do
resources :bookings
end
Now I'm getting
studio_bookings GET /:permalink/bookings(.:format) studio/bookings#index
Great! this is how I want my url to look, however, now the :id isn't anywhere in the route so... I get
Couldn't find Booking without an ID
It isn't even being passed. Is there a way to pass the :id in with the url without it being actually USED in the url? Otherwise, do I change the primary key from :id to :permalink in order to fix this?
I tried changing my controller from
#studio = Studio.find(params[:id])
to
#studio = Studio.find(params[:permalink])
but that gives me
Couldn't find Booking with 'id'=40frost
Which tells me what I'm doing isn't really meant to be done? It's trying to put the permalink as the id, so even though I'm telling rails to look for the permalink, it's still seemingly looking it up as an ID.
Hopefully my problem is clear: essentially - how can I pass the id so it knows which studio without displaying it in the URL. If there's some controller magic I can do instead that would be convenient.
Here's my controller for good measure
class Studio::BookingsController < ApplicationController
before_action :set_booking, only: [:show, :edit, :update, :destroy]
# GET /bookings
# GET /bookings.json
def index
#studio = Studio.find(params[:permalink])
#bookings = Booking.where("studio_id => '#studio.id'")
end
# GET /bookings/1
# GET /bookings/1.json
def show
end
# GET /bookings/new
def new
#booking = Booking.new
end
# GET /bookings/1/edit
def edit
end
# POST /bookings
# POST /bookings.json
def create
#booking = Booking.new(booking_params)
respond_to do |format|
if #booking.save
format.html { redirect_to #booking, notice: 'Booking was successfully created.' }
format.json { render action: 'show', status: :created, location: #booking }
else
format.html { render action: 'new' }
format.json { render json: #booking.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /bookings/1
# PATCH/PUT /bookings/1.json
def update
respond_to do |format|
if #booking.update(booking_params)
format.html { redirect_to #booking, notice: 'Booking was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #booking.errors, status: :unprocessable_entity }
end
end
end
# DELETE /bookings/1
# DELETE /bookings/1.json
def destroy
#booking.destroy
respond_to do |format|
format.html { redirect_to bookings_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_booking
#booking = Booking.find(params[:permalink])
end
# Never trust parameters from the scary internet, only allow the white list through.
def booking_params
params.require(:booking).permit(:start_time, :end_time, :studio_id, :engineer_id, :title, :allDay)
end
end
You could just do
self.primary_key = 'permalink'
in your Studio model, or you could do
def index
#studio = Studio.find_by permalink: params[:permalink]
#bookings = Booking.where(studio_id: #studio.id)
end
depends if you just want to locally change the behavior or adress the Studio model by permalink always.
Hope that helps!

How to list only current user orders if not an admin (Ruby on Rails)?

I'm pretty new to rails and I'm just now developing my first rails app, so this might be a dumb question to some. I would like to let the current_user see only their own orders if they are not an admin. I was able to set only admins can see all orders, but I'm having a hard time enabling current user to see, list and delete only their own orders. My app has a :orders model that belongs_to :users and a :users model with has_many :orders.
This is how my orders_controller.rb look like:
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
# GET /orders
# GET /orders.json
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#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 action: 'show', status: :created, location: #order }
else
format.html { render action: '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 { head :no_content }
else
format.html { render action: '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 }
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(:user_id, :drop_address)
end
end
My question is how do I allow only the current user to list and see all orders made by them only?
Thanks
There is gem named cancan for you.
Please read wiki page.
Need more help? let me know :)
define ability
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, Order, :user_id => user.id
end
end
end
from controller query by accessible_by
#orders = Order.accessible_by(current_ability)
you have to do it on two levels. In index you have to fetch orders for the current users so users can only see his orders. the second level is you make sure that the user may enter an order url that doesnt belong to him, so check for that in the other actions(edit,update,delete,show).
Or you can use declarative authorization gem. it is very helpful https://github.com/stffn/declarative_authorization
-hint: for naming conventions change belongs_to :users in order model to belongs_to :user (belongs_to is always singular)
This is how your controller should look like
#this is the filter called before each method to make sure the user is authorized to access the order
before_filter :authorize_user, :only => [:edit,:update,:delete,:show]
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#here fetch the orders of the current user only
#orders = current_user.orders
end
#and then goes all your methods here as normal
private
def authorize_user
unless current_user.eql?(#order.user)
flash[:notice]="You are not authorized to access this order"
redirect_to orders_path
end
end

Resources