Rails find or create based on two fields - ruby-on-rails

I have a venue model and i want to do this
Venue.find_or_create_by_
but i only want a new venue to be created if one with the same name and date do not already exist
For example
=> Venue(id: integer, location: string, showdate: datetime, created_at: datetime, updated_at: datetime)
A venue is unique and needs to be created if the location and the showdate are not present in the db

You can chain columns together by using _and_. This should do the trick:
Venue.find_or_create_by_location_and_showdate(location, showdate)

In rails 4 you would do:
Venue.find_or_create_by(location: location, showdate: showdate)
Much prettier, if you ask me!

my_class = ClassName.find_or_initialize_by_showdate_and_location(showdate,location)
my_class.update_attributes!
find_or_initialize method find by name and location in database. If record doesn't exist than it initialize new record with showdate and location.
http://api.rubyonrails.org/classes/ActiveRecord/Base.html This link will help you to figure out find_or_initialize and find_or_create.

Related

How to implement autocomplete search from google in rails ?

I am newbie in rails ,i don't know how implement this feature in application . please suggest me any basic idea.
if any user create a book ->
1) Book name should be auto suggested like Google search(if user enter a name , it should be automatically search correct name from Google and suggest to user ).
2) Author name also be auto suggested like Google Search(if user enter a name , it should be automatically search correct name from Google and suggest to user ).
Book Model has following attributes .
> Book.new
=>Book(id: integer, user_id: integer, author: string, name: string, published_at: datetime)

Rails: Assigning Variables to Associated models

Hey I am trying to assign my currentslide that is part of my courses model and is associated to my user model.
I have 3 models:
- Users
- Courses (title: ,currentprogress: )
- UserCourseAssignment. (association table)
I can get the courses that a user has been assigned by typing User.courses however it won't let me update variables
#<Course id: 6, title: "beginnerscourse", created_at: "2016-03-20 12:42:44",
updated_at: "2016-03-20 12:42:44", reward1: nil, reward2: nil, reward3: nil,
reward4: nil, reward5: nil, currentslide: 0, totalslides: nil>]>
User = active_user
User.courses.find(6).currentslide = 1
User.save
Sorry if I wasnt clear, Updated question
You shouldn't assign a class name (User) as a variable. In your scenario, you can just use active_user.
active_user.courses.find(6).update_attributes(current_slide: 1)
As I was writing a better explanation as to why, #max answered as well with a great explanation as to what is going on here. Please refer to his answer for a great explanation.
He is also correct in reference to just using Course.find, if you already know the course ID. There is no need to load all of the current_user's courses from the DB if you already know the ID. You'll get better performance just using Course.find(id).update_attributes...
User = active_user
User.courses.find(6).currentslide = 1
User.save
There are quite a few things going wrong here. User declares a constant which will mask your User class! In Ruby any identifier which starts with an uppercase letter is a constant.
Watch this example:
User = active_user
# somewhere else in the code
User.find(5) # NoMethodError wtf!?
Also if you know the id of the course there is no need to go through the user in the first place:
course = Course.find(6)
course.update_attributes(currentslide: 1)
If you want to scope the query to the current user as poor mans version of access controller you would do it like so:
course = Course.where(user: current_user).find(6)

Rails 4 how to know if update has been executed

I have this code in Rails 4:
mmkBase = Mmk::Base.find_or_initialize_by(id: id)
mmkBase.update(name: name, city: city, country: country, address: address, region_ids: regionIds, latitude: latitude,
longitude: longitude)
The code is working ok, but now I would need to gather some statistics, like:
Number of bases.
Number of new bases.
Number of loaded (updated) bases.
Number of bases is not a problem. Number of new bases, I think I could check if the object mmkBase returned by find_or_initialize comes with more attributes than just the id, for example with a name.
However, I don´t know how can I check if the update operation is run.
Is there any way to know this? Is there a better way to achieve this? Maybe, I should use a more traditional way to do it, with a select first?
However, I don´t know how can I check if the update operation is run
You can simply use...
if mmkbase.update mkbase_params
...
else
...
This will invoke the update method, generating a response determined by whether it was successful or not (true = success; false = validation failure)
Number of new bases
As mentioned, the new_record? method is what you need here...
if mmkbase.new_record? #-> mmkbase hasn't been saved to db yet
I'd do this:
mmkBase.find_or_create_by(mmkbase_params) do |base|
#do something if new base
end
private
def mmkbase_params
params.require(:mmkbase).permit(:name, :city, :country, :address, :region_ids, :latitude, :longitude)
end
If you're having to pull this type of data by its primary key (find_or_initialize_by id:), you're in trouble... how do you know if the primary key will remain constant?
Of course, this is not always the case. Changing user details would require you to reference the user id - however that data is rigid. IE a user registered (with name and email), and you're now looking for that user (it can't be created on the fly).
I don't know your schema; anything which can be created like this should be referenced by its core data (name, city, etc)...
mmkbase.find_by(name: ....)
In relational databases, you need to be dealing with the data, not the primary keys. In other types of db, you can deal with indexes, but with this type of setup, it's much better to work with the pure data.
You want to distinguish between an already existing record and a newly created record. On a new record which was only initialized by find_or_initialize_by, new_record? returns true. So for example you could write:
mmkBase = Mmk::Base.find_or_initialize_by(id: id)
new_base = mmkBase.new_record?
if mmkBase.update(name: name, city: city, country: country, address: address, region_ids: regionIds, latitude: latitude,
longitude: longitude)
# update was successful
if new_base
new_bases += 1
else
updated_bases += 1
end
else
# error handling
end
Note that it is probably not a good idea to use find_or_initialize_by with the ID of the record. See Rich Peck's answer.
You could probably check the updated_at timestamp on the object to see if it has been updated recently but the Rails 4 update method doesn't tell you whether an object was updated or not.
http://apidock.com/rails/ActiveRecord/Base/update/class

How to reference a database column in rails active record interface

Really confused.
I've been reading through the rails guide and there seem to be difference ways to reference a column in rails. Sometimes it's as a string eg
Client.select("viewable_by, locked")
and sometimes with a colon at the beginning
Client.select(:name).uniq
When do I decide which to use? Are these interchangeable?
If it is a string, it will be injected into the sql statement, which allows you to do some advanced SQL-y stuff, like
select("count(name) as name_count, nvl(price, 'N/A')")
(this is just an example, mashing some stuff together)
If you want to select some columns, I would always use symbols or an array of symbols, like
Client.select(:viewable_by, :locked)
So in short: yes they are interchangeable, the string will not be parsed, just injected into the SQL statement, which allows you do some more advanced stuff if needed.
Yes, they are interchangeable. They return the same result - i.e an ActiveRecord Relation containing instances of models with only the fields you requested set.
Client.select("viewable_by, locked")
=> [#<Client id: nil, viewable_by: "admin", locked: true>]
Client.select(:viewable_by, :locked)
=> [#<Client id: nil, viewable_by: "admin", locked: true>]
I've made up the responses but you get the idea.
If you simply wanted an array of the names I'd use pluck instead:
Client.pluck(:name).uniq

How to get ar_fixtures to load protected attributes?

I'm using ar_fixtures to seed data in a rails project (the procedure was written before seed arrived in 2.3.4)
It is all working fine, except I find that one column in particular is not getting populated (user_id). user_id is set in the yaml file, for example:
- !ruby/object:Service
attributes:
name: name
updated_at: 2009-10-14 11:50:36
provider_id: "1"
id: "1"
description: ""
user_id: "1"
created_at: 2009-10-14 11:47:01
attributes_cache: {}
But even though the related user object exists when running the import (Service.load_from_file), user_id is nil after import. Other foreign keys (like provider_id in the example above) are loaded correctly.
I am suspecting this is because user_id is protected in the model and this getting blocked during mass assignment.
Does anyone know if this is the case, and if so, how to get around the mass assignment protection? Of course, I want to leave mass assignment protection in place for the application at runtime.
Fixed! Answering my own question..
Simply requires a tweak of the attr_protected / attr_accessible setting prior to loading. e.g.
Service.attr_protected.delete "user_id"
Service.load_from_file
Or if the restriction is based on attr_accessible:
Service.attr_accessible :user_id
Service.load_from_file

Resources