Check if record exists in Rails controller - ruby-on-rails

I want to check if the entry with the id 2 exists in the settings table and if not i want that the user gets redirected to the setting_new_path. My code looks like this:
def index
if Setting.find(2).present?
#patients = Patient.all
#patients_drucken = Patient.drucken
#anrede = Setting.find(1).anrede
respond_to do |format|
format.html # index.html.erb
format.json { render json: #patients }
end
else
redirect_to new_setting_path
end
end
But somehow i get the error:
Couldn't find Setting with id=2
I dont get why this is displayed as an error! I mean in the case its not defined i worte , redirect to new_setting_path! What made i wrong?

Use exists? to check for record presence:
if Setting.exists?(2)

#find will throws an exception if the record is not found.
You should use #where and #any? instead :
if Setting.where( id: 2 ).any?

It means you don't have any record with id = 2 in Settings table. Just check it once.

Related

Insert another field into GET response JSON

I have the following code that responds to GET /something.json:
def index
#something = Something.all
respond_to do |format|
format.json { render json: #something }
end
end
That runs a SELECT * FROM something in the database, formats the result into a JSON, and responds with it.
The request might ask for another field through a query parameter, which is in a different table than something. I managed to retrieve the desired field doing this:
def index
#something = Something.all
if params[:get_field_from_some_other_table] == "true"
#something.each do |i|
some_other_table = SomeOtherTable.find(i.some_other_table_id)
the_field_i_want = some_other_table.the_field
end
end
respond_to do |format|
format.json { render json: #something }
end
end
But I haven't found a way to add the field to the JSON string. How can I do that? Or is there a better way to retrieve the field with the contents of the something table through a JOIN or something like that?
something and other_table should be related at active_record somehow... maybe a has_one?
Try that and then just use #something.all.includes(:other_table_attribute)
Apart from that, please post your code properly with some readable examples, that helps a lot and will give you faster responses :)

linking to the product from the index in rails

When I save a PayerContract in the create form, it saves the PayerContract and creates a "success you have created PayerContract {X}" where {X} is the PayerContract name and redirects the user back to the index. I want to allow the user to click the {X} to go to the edit page for that PayerContract.
In my index page I have:
= link_to t('payer_contracts.edit'), edit_payer_contract_path())
I need to give the PayerContract.id to the edit_payer_contract_path function. So, it would look something like edit_payer_contract_path(330)
The warning message I have displayed in my controller is this:
def create
payer_contract_params = PayerContract.assign_params_to_payer_contract(params)
#payer_contract = PayerContract.new(payer_contract_params)
respond_to do |format|
begin
if #payer_contract.save
format.html { redirect_to payer_contracts_path, notice: t('common.successfully_created', entity: #payer_contract.description) }
end
end
end
end
I found out that when I do something like:
edit_payer_contract_path(PayerContract.find()) it returns all the PayerContract that looks like: expected an attributes Hash, got [{"id"=>224, "name" ="hello", "id"=> 332, "name" = "hello2", "id"=>555, "name" = "sup" }] etc.
How can I correctly link the user to the PayerContract they just created?
you can have it two ways. Either pass parameter along your redirect_to method. obviously, pass the id of newly created PayerContract. This way you will have the id in params and you can use it in your link_to method.
If you don't want to pass the parameter, try storing the newly created PayerContract in session after successfully creating PayerContract. This way after redirect you will still have access to the saved value from the session
something like below
def create
#foo = Foo.new(foo_params)
if foo.save
session[:foo_id] = #foo.id
redirect_to foo_path
end
end
As beniutek said you can pass parameter in redirect_to. But when user first visit index page id is not defined so you can check in view if it is define set the id to link_to as below.
def create
payer_contract_params = PayerContract.assign_params_to_payer_contract(params)
#payer_contract = PayerContract.new(payer_contract_params)
respond_to do |format|
begin
if #payer_contract.save
format.html { redirect_to payer_contracts_path(id: #payer_contract.id), notice: t('common.successfully_created', entity: #payer_contract.description) }
end
end
end
end
In view
if params[:id].present?
= link_to t('payer_contracts.edit'), edit_payer_contract_path(params[:id].to_i))

Call Rails Model function from Controller

I'm new to Rails, and am trying to make a pet app. It has 3 attributes: name, hungry, and mood. I generated a scaffold and wrote a feed method into the model:
def feed
self.hungry==false;
save!
end
I want feed to be something a user can do in the edit view, so I created a checkbox to indicate feeding vs. not feeding. My plan was to call the feed function from the controller in the update function. Right now, it looks like this:
def update
respond_to do |format|
if #pet.update(pet_params)
format.html { redirect_to #pet, notice: 'Pet was successfully updated. #{params[:feed]}' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #pet.errors, status: :unprocessable_entity }
end
end
if #pet.update_attributes(params[:feed])
#pet.feed
end
end
I have an odd sense that I'm mixing metaphors here, but am not sure of the right course of action. I'm trying to call a function from my update function, and that doesn't seem to be working. It might have to do with the fact that "feed" isn't listed in my model's parameters, but I don't need it to be. I just need it to call a function. Help!
Your method definition is wrong. Instead of assigning a value, you are comparing equality.
def feed
self.hungry == false; # only one = should be used.
save!
end
There is a better way to do this, however:
class Pet
attr_accessor :feed_me
before_save :feed
def feed
hungry = false if feed_me
end
end
You should not need the controller check:
if #pet.update_attributes(params[:feed])
#pet.feed
end
Which is wrong, by the way. You need to check if the param[:feed] exists, not if the pet objet has updated correctly.
For this solution to work, you would need to add an attribute to your form:
= f.check_box :feed_me
Another way to do this would be to map the hungry attribute to the checkbox and just name the label feed:
= f.label :hungry, "Feed"
= f.checkbox :hungry
You could then go ahead and just remove the before_save, the attr_accessor, and the method self.feed.

Update if exists, else do nothing?

I'm trying to update a value of a model if and only if the model exists. If it doesn't, I do nothing. Searching only seems to return update or create questions/answers, but I do not want to create.
I know I can do it with a simple:
found = Model.find_by_id(id)
if found
update stuff
end
However, I feel like there is a way to do this in one call, without assigning any temporary local values or doing an if.
How would I write a rails call to update a record without noisy errors if it doesnt exist?
Latest Rails 3.x
You can use try method of Rails before calling update_attributes on result of find_by_id or where.
try will return nil silently without raising exception if the record does not exist. If the record exists, it will update it.
found = Model.find_by_id(id).try(:update_attributes, {key: value})
You can use first_or_initialize combined with new_record? as following:
client = Client.where(first_name: 'Nick').first_or_initialize(locked: false)
client.save unless client.new_record?
Assuming your model is called 'Event' and you search by id, you could do:
e = Event.where(:id => id)
if !e.empty?
e.first.value = new_value
e.first.save!
end
In Rails 4, this is probably the simplest solution I found:
# POST /users
# POST /users.json
def create
#user = User.find_or_initialize_by(fbid: user_params[:fbid])
#user.assign_attributes(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
If the user with FBID exists, then the record will be updated; otherwise, a new one will be created. You can update the record to match whatever column you want to keep unique. Probably indexing the column would help the search & retrieval etc.
Hope this helps!

Rails: best_in_place collection issue

My app runs on two different database, and I use the application logic to work on them.
I have the User model on an external db and I only records the id on my default_role class.
So in the index template I fetch the accounts from remote, and for each of them I have to query my table to print some immutable information and I want to give the possibility to change role in my table
Index information = remote tables information (name surname ecc) + my table information (role)
Using best_in_place to edit the role_id field of my users.
The problem is my index cycle #operators which comes from outside buy I need to change role which is on my side!
- #operators.each do |ope| #cycle users
%tr
%td
- user = User.find_by_bay_id(ope.account_id)
- df = DefaultRole.find_by_operator_id(user.id)
= best_in_place [:admin, df], :role_id, :type => :select, :collection => [[1, 'admin'], [2, 'coordinator'], [3, 'operator'], [4, 'base']]
and my update in controller:
respond_to :html, :json
def index
#operators = some logic from model where I get all the users
end
def update
#df = DefaultRole.find(params[:id])
#df.update_attributes(params[:default_role])
respond_with [:admin, #df]
end
But it didn't even call my update method in the controller.
It normally checks the collection tag, allows me to change it but it doesn't allow me to submit.
What am I doing wrong?
EDIT
My browser doesn't catch any request.
Best_in_place gem uses JSON calls to update the content . In this case you should have respond_to json statement in your controller , something like this :
def update
#df = DefaultRole.find(params[:id])
respond_to do |format|
if #df.update_attributes(params[:default_role])
format.html { redirect_to root_path, notice: 'Role was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #df.errors, status: :unprocessable_entity }
end
end
I find it strange to include variable specifications in your view , they belong to the controller (- user = User.find_by_bay_id(ope.account_id)
- df = DefaultRole.find_by_operator_id(user.id) .
I finally found the error.
https://github.com/bernat/best_in_place/issues/217
It was a Jquery issue on that version of best_in_place. Running:
bundle update
and restarting the server solve the problem, thanks everyone

Resources