How to count records in Ruby on Rails App? - ruby-on-rails

I want to to display all distinct records in a view. I have the following in my accounts_controler.rb file #account = Account.count("created_at", :distinct => true) or should I use Account.distinct.count('date')? If I read correctly rails 4 :distinct => true is now deprecated
I'm not sure if that is correct. Here is the entire controller file:
class AccountsController < ApplicationController
before_action :authenticate_user!
before_action :set_account, only: [:show, :edit, :update, :destroy]
respond_to :html
def search
if params[:search].present?
#account = Account.search(params[:search])
else
#account = Account.all
end
end
def index
#account = Account.all.order("created_at DESC").page(params[:page]).per(10)
#account = Account.count("created_at", :distinct => true)
end
end
def show
#notes = Note.where(account_id: #account.id) #Where a note belong to the current account
end
def new
#account = Account.new
respond_with(#account)
end
def edit
end
def create
#account = Account.new(account_params)
#account.save
respond_with(#account)
end
def update
#account.update(account_params)
respond_with(#account)
end
def destroy
#account.destroy
respond_with(#account)
end
private
def set_account
#account = Account.find(params[:id])
end
def account_params
params.require(:account).permit(:first_name, :last_name, :return_client, :program_id, :insurance_id, :address, :phone)
end
I beleive there should be a ruby tag include in the index.html.erb file but I'm not sure of the syntax.

You are right.
Rails 3:
Account.count(:created_at, distinct: true)
Rails 4:
Account.distinct.count('date')

You can use the uniq keyword to return all distinct records as follow:
def index
#accounts = Account.uniq.order("created_at DESC").page(params[:page]).per(10)
#accounts_count = Account.uniq.count
end
and then you will have access to the instance variable #accounts in your index.html.erb file.

Related

How to fix this error with impressionist gem rails

Hi i got error with impressionist gem. i use Rails 5.2.4.4
i did these steps :
gem 'impressionist'
then bundle install
then rails g impressionist and bundle install
Then next step :
in my blogs_controllers
class BlogsController < ApplicationController
before_action :authorize_admin, only: [:new, :edit, :create, :update]
before_action :set_blog, only: [:show, :edit, :update, :destroy]
impressionist :actions => [:show, :index]
def index
#categories = Category.all
cate = params[:cate]
if !cate.nil?
#blogs = Blog.where(:category_id => cate)
else
#blogs = Blog.all
end
end
def show
impressionist(#blog)
end
def new
#blog = Blog.new
end
def create
#blog = Blog.new(blog_params)
if #blog.save
redirect_to blog_path(#blog), notice: "Successfully Created"
else
render :new
end
end
def edit
end
def update
#blog.slug = nil
if #blog.update(blog_params)
redirect_to blog_path(#blog), notice: "Successfully Update"
else
render 'edit'
end
end
def destroy
#blog.destroy
redirect_to blogs_path
end
private
def set_blog
#blog = Blog.find(params[:id])
end
def blog_params
params.require(:blog).permit(:title, :body, :image, :category_id)
end
def authorize_admin
return unless !current_user.admin?
redirect_to root_path
end
end
in blog model
is_impressionable
in blog show
<%= #blog.impressionist_count(:filter=>:ip_address) %>
And i got this error :
NameError in BlogsController#show
uninitialized constant ActiveSupport::ParameterFilter
Extracted source (around line #80):
# If the constant was actually loaded, something else went wrong?
raise(e) if from_mod.const_defined?(const_name)
CoreExt::ActiveSupport.without_bootsnap_cache { super }
end
# Signature has changed a few times over the years; easiest to not

why does my routes give me wrong direction

I'm having a association between user, store and item like this:
user has one store
store has many items
item belongs to store
So when I create item it must belongs to the current user's store
Now, I logged in as user_1 , I want to search for user_2's item. But if I didn't create user_1's store, It keep redirecting me to localhost:3000/stores
in items_controller.rb:
class ItemsController < ApplicationController
before_action :find_item, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:new, :edit]
def index
if params[:category].blank?
#items = Item.all.order("created_at DESC")
end
if params[:category]
#category_id = Category.find_by(name: params[:category]).id
#items = Item.where(category_id: #category_id).order("created_at DESC")
end
end
def show
end
def new
#store = current_user.store
#item = #store.items.build
#categories = Category.all.map{ |c| [c.name, c.id] }
end
def update
#item.category_id = params[:category_id]
if #item.update(item_params)
redirect_to item_path(#item)
else
render 'edit'
end
end
def create
#store = current_user.store
#item = #store.items.build(item_params)
#item.category_id = params[:category_id]
if #item.save
flash[:success] = "Creating item success"
redirect_to #item
else
render 'new'
end
end
private
def item_params
params.require(:item).permit(:code, :name, :description, :producer, :item_img, :store_id,
:category_id )
end
def find_item
#item = Item.find(params[:id])
end
def find_user
#user = User.find_by(params[:user_id])
end
end
in stores_controller.rb:
class StoresController < ApplicationController
before_action :find_store, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :find_user
def show
if current_user.store.blank?
redirect_to new
else
#items = Item.where(store_id: #store.id)
end
end
def index
#stores = Store.all.order("created at DESC")
end
def new
#store = current_user.build_store
end
def create
#store = current_user.build_store(store_params)
if #store.save
session[:store_id] = #store.id
flash[:success] = "Creating item success"
redirect_to #store, notice: 'success'
else
render 'new'
end
end
private
def store_params
params.require(:store).permit( :name , :user_id)
end
def find_store
#store = Store.find(params[:id])
end
def find_user
#user = Store.find_by(params[:user_id])
end
end
The error raised whenever I click on the button in items/show.html.erb.
In items/show.html.erb:
<button>see more item from:<%= link_to #item.store.name, store_path(#item.store.id)%></button>
in routes.rb:
devise_for :users
resources :items
resources :stores
In the show method for stores_controller, I still want to load the current_user's store in navbar section to make sure he can add more items to his store when he logged in.
I'm still a newbie in rails and I'm looking for solutions to solve this problem :-)
If a store requires a user_id then you don't need before_action :find_user because you can get the store's user just by calling store.user
It looks like you require the current_user to have a store but what if they are not logged in? Shouldn't it be this?
def show
if current_user && current_user.store.blank?
redirect_to new
else
#items = Item.where(store_id: #store.id)
end
end

Rails throwing error instead validating

I am building a fairly straightforward Rails 5 application. You create "Movies," and then can create "Reviews" for those movies. Rails is doing something odd. I have my application set up so instead of a "new" action and a corresponding view, I have the form to create new movies in a modal contained in the application.html.erb file. I then provide #newmovie = Movie.new in the controller for all the movie views, so the data is available everywhere.
I have validations for the movie object setup like this:
class Movie < ApplicationRecord
has_many :reviews
validates :title, :director, :poster, :synopsis, presence: true
end
When I fill out the form to create a new movie in the modal on my index view and intentionally leave fields blank (to trigger the validation), I get this:
instead of the form simply not accepting the input. What's going on here? I can't have this error happening like this. Previously, I had a "new" view. This did not happen in the previous setup. Help!
Here is my entire movies controller:
class MoviesController < ApplicationController
before_action :find_movie, only: [:show, :edit, :update, :destroy ]
before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
before_action :find_newmovie, only: [:show, :index, :new, :edit]
def show
#reviews = #movie.reviews.all.order(created_at: :desc).paginate(:page => params[:page], :per_page => 3)
#review = Review.new
if #movie.reviews.blank?
#average_review = 0
else
#average_review = #movie.reviews.average(:rating).round(2)
end
end
def index
#movies = Movie.all.order(title: :asc).paginate(:page => params[:page], :per_page => 3)
#newmovie = Movie.new
end
def new
#movie = Movie.new
end
def create
#movie = Movie.create(movie_params)
#movie.user_id = current_user.id
if #movie.save
flash[:success] = "Your movie was created!"
redirect_to root_path
else
flash[:danger] = "There was a problem with your request"
render :new
end
end
def edit
end
def update
if #movie.update(movie_params)
flash[:success] = "Your movie was updated"
redirect_to movie_path
else
flash[:danger] = "There was a problem with your request"
end
end
def destroy
if #movie.destroy
flash[:success] = "Your movie was removed"
redirect_to movies_path
else
flash[:danger] = "There was a problem with your request"
render :index
end
end
private
def movie_params
params.require(:movie).permit(:title, :director, :poster, :synopsis, :user_id)
end
def find_movie
#movie = Movie.find(params[:id])
end
def find_newmovie
#newmovie = Movie.new
end
end
In new action of movies_controller, you missed to initalize the instance variable #newmovie.
add below code in movies_controller:
class MoviesController < ApplicationController
def new
#newmovie = Movie.new
end
...
end

How To Have A Blog Where Users Can Only Edit Posts For A Limited Time in Ruby on Rails

I've made a very simple blog where users can Create, Edit and Delete posts however I want to add functionality where users can only Edit for a limited time (say 3 days). My understanding of Ruby is not strong enough to know how to do this so any help is appreciated.
This is my Notes (my name for Posts) controller
class NotesController < ApplicationController
before_action :find_note, only: [:show, :edit, :update, :destroy]
def index
#notes = Note.where(user_id: current_user)
end
def show
end
def new
#note = current_user.notes.build
end
def create
#note = current_user.notes.build(note_params)
if #note.save
redirect_to #note
else
render 'new'
end
end
def edit
end
def update
if #note.update(note_params)
redirect_to #note
else
render 'edit'
end
end
def destroy
#note.destroy
redirect_to notes_path
end
private
def find_note
#note = Note.find(params[:id])
end
def note_params
params.require(:note).permit(:title, :content)
end
end
I assume somewhere in the edit method I need to write a rule for restricting the ability to edit posts to only 3 days, using the created_at function somehow? I'm just at a loss as to exactly how to do this.
Any help is appreciated.
Perfect solution for that is :before_filter
class NotesController < ApplicationController
before_filter :check_time!, only: [:edit, :update]
def edit
end
def create
end
private
def check_time!
if Time.now() > #note.created_at + 3.days
flash[:danger] = 'Out of 3 days'
redirect_to note_path(#note)
end
end
end

Best way to avoid duplication of related objects in the actions new and create

To create an user in the example bellow I have to load #projects and #companies as they are mandatory for creating user.
class UsersController < ApplicationController
def new
#user = User.new
# duplication here
#projects = Project.all
#companies = Company.all
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
# and here
#projects = Project.all
#companies = Company.all
render :action => "new"
end
end
end
I have to load these dependencies in both (duplication) cases, for the new and create action when the user is invalid.
I can refactor by encapsulating these dependencies in a method load_user_dependencies.
class UsersController < ApplicationController
def new
#user = User.new
load_user_dependencies
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
load_user_dependencies
render :action => "new"
end
end
private
def load_user_dependencies
#projects = Project.all
#companies = Company.all
end
end
Or by adding them as a helper_methods.
class UsersController < ApplicationController
helper_method :projects, :companies
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
def projects
#projects ||= Project.all
end
def companies
#companies ||= Company.all
end
end
I can also create a View Object
class UserView
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = User.new
#user_view = UserView.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
#user_view = UserView.new
render :action => "new"
end
end
end
Other option is to use a Presenter
class UserPresenter < SimpleDelegator
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = UserPresenter.new User.new
end
def create
#user = UserPresenter.new User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
end
How do you guys usually deal with scenario?
It's a bit of a personal taste issue, but in our projects if it's suitable we do it in the view, and if it's complex we do it in a before_filter.
View - suitable if it's something that doesn't have any logic, no need to create a variable for this. Super useful if your form is contained in a partial as it's only done once so easily maintained.
<%= form.select :project_id, Project.all, :id, :name %>
If it's something that can change depending on any factors then a before_filter in controller:
MyController
before_filter :find_projects, :except => [:destroy, :some_method] # Will load the values but not for the destroy or some_method actions
def find_projects
#projects = Project.where(:some conditions => true)
end

Resources