I need a little help with state machine because I'm working with rails 4 I have a initial state called in_analysis and other states called approved and reject and the states approved and reject works fine I don't have problem for pass through to the states, but I can't back to the initial state called in_analysis, here is my code:
app/models/profile.rb
state_machine :state, :initial => :in_analysis do
state :in_analysis, :approved, :rejected
state :approved do
validates :name, presence: true
end
event :approved do
transition in_analysis: :approved
end
event :reject do
transition in_analysis: :rejected
transition approved: :rejected
end
end
and in my controller I have this:
def update
#profile.state = :in_analysis
#profile = current_user.profile
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to edit_profile_path(#profile), notice: t(:update, scope: [:messages, :controllers, :profiles, :successfully]) }
format.json { render :show, status: :ok, location: edit_profile_path(#profile) }
else
format.html { render :edit }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
so my goal is when the profile is updated the state back to the initial "in_analysis" but I don't know why doesn't work because the another state works well.
Thanks for the time ! regards !
Assuming that your state_machine is correct, the only place that you might be doing wrong is
#profile.state = :in_analysis
#profile = current_user.profile
You assign the state to :in_analysis then you actually assign #profile to old current_user.profile which is fetched from database thus your assignment to :in_analysis is discarded.
You can try to swap the two line:
#profile = current_user.profile
#profile.state = :in_analysis
Related
I have a controller​ action which requires to find data from existing database. I am still learning rails and recently came to know about active record queries.
But I am not sure how to use it to fetch record from database in a controller action.
Can anybody please explain this with some example?
Thanks in advance
I found the answer. We can use active record queries to fetch the record from the database in the controller. Example is as follow:
Consider a database 'Dress' which has color attribute. Now I want to fetch all the 'dresses' which have orange color. So the query will be as:
#dresses = Dress.where(color: 'orange')
This will fetch all the record of dresses which have color = orange.
Yes you can used active record query inside controller. But better to put active record query logic inside model only. Because rails follow MVC Architecture
MVC stands for Model, View and Controller. MVC separates application into three components - Model, View and Controller.
Model: Model represents shape of the data and business logic. It maintains the data of the application. Model objects retrieve and store model state in a database. Model is a data and business logic.
View: View is a user interface. View display data using model to the user and also enables them to modify the data.
Controller: Controller handles the user request. Typically, user interact with View, which in-turn raises appropriate URL request, this request will be handled by a controller. The controller renders the appropriate view with the model data as a response.
Example:-
class RoomsController < ApplicationController
before_action :set_room, only: [:show, :edit, :update, :destroy]
# GET /rooms
# GET /rooms.json
def index
#rooms = Room.all
end
# GET /rooms/1
# GET /rooms/1.json
def show
end
# GET /rooms/new
def new
#room = Room.new
end
# GET /rooms/1/edit
def edit
end
# POST /rooms
# POST /rooms.json
def create
#room = Room.new(room_params)
respond_to do |format|
if #room.save
format.html { redirect_to #room, notice: 'Room was successfully created.' }
format.json { render :show, status: :created, location: #room }
else
format.html { render :new }
format.json { render json: #room.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /rooms/1
# PATCH/PUT /rooms/1.json
def update
respond_to do |format|
if #room.update(room_params)
format.html { redirect_to #room, notice: 'Room was successfully updated.' }
format.json { render :show, status: :ok, location: #room }
else
format.html { render :edit }
format.json { render json: #room.errors, status: :unprocessable_entity }
end
end
end
# DELETE /rooms/1
# DELETE /rooms/1.json
def destroy
#room.destroy
respond_to do |format|
format.html { redirect_to rooms_url, notice: 'Room was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_room
#room = Room.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def room_params
params.require(:room).permit(:name, :type, :user_id)
end
end
I used this page to help me validate if adding a new entry (add a new exercise in my case) which worked great Check if record exists from controller in Rails
But I can't quite seem to get it to work if I'm updating/editing an exercise.
In plain English I'm trying to:
Get current exercise record the user wants to edit(done), user updates the values(done), submits(done), the controller checks the user's input against the db to see if a record already exists with the same name, if it exists error, if not, update.
Thanks.
Here's the part of my controller that I can't quite get going for update:
class ExercisesController < ApplicationController
before_action :authenticate_user!, :except => [:index, :show]
before_filter :set_exercise, only: [:show, :edit, :update, :destroy, :upvote, :downvote]
def new
#exercise = Exercise.new
end
def create
#exercise = current_user.exercises.build(exercise_params)
if Exercise.exists?(name: #exercise.name)
flash.now[:danger] = "Exercise has not been created, duplicate entry"
render :new
elsif #exercise.save
flash[:success] = "Exercise has been created"
redirect_to exercises_path
else
flash.now[:danger] = "Exercise has not been created"
render :new
end
end
def edit
if !current_user.admin?
flash[:danger] = "You are not an admin"
redirect_to root_path
end
end
def update
if !current_user.admin?
flash[:danger] = "You are not an admin"
redirect_to root_path
else
if Exercise.where(:name => #exercise.name).any?
flash.now[:danger] = "Exercise has not been updated, duplicate entry"
render :edit
elsif #exercise.update(exercise_params)
flash[:success] = "Exercise has been updated"
redirect_to #exercise
else
flash.now[:danger] = "Exercise has not been updated"
render :edit
end
end
end
private
def exercise_params
params.require(:exercise).permit(:name, :description, :summary)
end
def set_exercise
#exercise=Exercise.find(params[:id])
end
Found an easier way to make this work. In the model you can specify uniqueness.
class Exercise < ActiveRecord::Base
validates :name, presence: true, :uniqueness => true
so my model looks like this for update:
def update
if !current_user.admin?
flash[:danger] = "You are not an admin"
redirect_to root_path
else
if #exercise.update(exercise_params)
flash[:success] = "Exercise has been updated"
redirect_to #exercise
else
flash.now[:danger] = "Exercise has not been updated"
render :edit
end
end
end
I think my error is kind of silly, but it's keeping me stuck. I'm following the Agile Web Development with Rails 4 and developing the app Depot from it. I'm getting a
undefined method `add_product' for #<Cart:0x007f2ee4cfb8f8>
error. My code is as follows,
class LineItemsController < ApplicationController
def create
find_cart
product = Product.find(params[:product_id])
byebug
#line_item = #cart.add_product(product.id) // line with error
#line_item.product = product
respond_to do |format|
if #line_item.save
format.html {redirect_to #line_item.cart,
notice: 'Line Item was succesfully created'}
format.json {render json: #line_item,
status: :created, location: #line_item}
else
format.html {render action: "new"}
format.json {render json: #line_item.errors,
status: "Unprocessable Entry"}
end
end
end
end
Cart.rb
class Cart < ActiveRecord::Base
has_many :line_items, dependent: :destroy
def add_products(product_id)
current_item = line_items.find_by_product_id(product_id)
if current_item
current_item.qunatity += 1
else
current_item = line_items.build(product_id: product_id)
end
current_item
end
end
Also, I want to know, how can a method from different model be directly called into a separate controller ?
The object cart has value, I have debugged to make sure, as well as the error line also has the object present.
Thanks for your help.
I found the mistake, it was a typo I made in Cart.rb. I had named the method add_product's' and was calling add_product in the controller.
I have created an app that splits up a Student's Information into multiple forms.
Everything works fine, but when I try to render Form_One after a Validation Error, it does not render the appropriate URL/Page.
EX.
adults/1/students/2/form_one
turns into
adults/1/students/2
I need to render the same url so I can proceed to form_2.
MODELS
class Adult < ActiveRecord::Base
has_many :students
end
class Student < ActiveRecord::Base
belongs_to :adult
validates :firstName, :presence => true,
length: { maximum: 50 }
validates :lastName, :presence => true,
length: { maximum: 50 }
end
CONTROLLER
def update
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
if #student.update_attributes(student_params)
###IF PASS REDIRECT TO THE NEXT FORM
if URI(request.referer).path == form_one_adult_student_path(#adult, #student)
redirect_to form_two_adult_student_path(#adult, #student)
elsif URI(request.referer).path == form_two_adult_student_path(#adult, #student)
redirect_to form_three_adult_student_path(#adult, #student)
else
redirect_to adult_path(#district, #adult)
end
else
error_messages = #student.errors.messages
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
#student.errors.messages.merge!(error_messages)
###IF ERROR AND ON FORM_ONE RENDER FORM_ONE
if URI(request.referer).path == form_one_adult_student_path(#adult, #student)
###FOR SOME REASON THIS RENDERS adults/1/students/2
###BUT I NEED IT TO RENDER adults/1/students/2/form_one
render 'form_one'
end
end
end
def form_one
#title = "Student Information"
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
end
def form_two
#title = "Parent Information"
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
end
ROUTES
resources :adults do
resources :students do
member do
get :form_one, :form_two
end
end
end
###FOR SOME REASON THIS RENDERS adults/1/students/2
###BUT I NEED IT TO RENDER adults/1/students/2/form_one
render 'form_one'
Try redirect_to instead of render.
Keep in mind the difference between rendering a template, and making an HTTP request. Try pretending you are an HTTP client and think about the requests and responses. Sometimes it helps to look through your server log to see which controller actions happen, in which order. Look for lines like Processing students#update or Redirecting to ....
In the future, you may want to try resourceful routes like #show instead.
Problem solved thanks to #skipchris (https://twitter.com/skipchris) Using debugger we found a spelling mistake. The error report didn't make much sense but i learned plenty investigating the problem!
I've spent last night and this morning trying to find a solution but i'm new to rails. From what i've read so far it think the problem is to do with association. I created a Pin without a User (association error?) and so there is an error with routing i.e something to do with Devise?
When i try to create a new Pin i get this error in browser on my local server-
NoMethodError in PinsController#create
pp/controllers/pins_controller.rb:48:in block in create'
app/controllers/pins_controller.rb:47:increate'
pins_controller.rb
def create
#pin = current_user.pins.new(params[:pin])
respond_to do |format|
if #pin.save
format.html { redirect_to #pin, notice: 'Pin was successfully created.' }
format.json { render json: #pin, status: :created, location: #pin }
else
format.html { render action: "new" }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
User Model (user.rb)
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, #:recoverable,
:rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation,
:remember_me, :name
has_many :pins
end
Yeah, I would definitely make a user model since you are trying to access current_user.pins in the methods. also do you have
resources :pins
or something similar in your routes?