Is it best practice to use update_attribute action in Rails CRUD Show - ruby-on-rails

I can use it but I am sure if it is a good practice to use update_attribute action in Show action in Rails. If its a bad practice please suggest for the best alternatives since I need to update a column of row on every show action.
My code
def show
#package = Package.friendly.find(params[:id])
#pack = Package.where(:category_id => #package.category_id).sample(4)
#setting = Setting.find(1)
counter = #package.counter
count = counter+1
#package.update_attributes(:counter => count)
end

In Rails CRUD convention "show" should route from an HTTP GET. In general, it's best to avoid modifying any state of the database from a GET action. So, to answer your question, no, it's not a best practice to use update_attribute in a show action.

This is really a odd processing to obtain a count and then increment it by values then update it to table
It's make slower into that
For Best Practices You can implement like this
item = Item.find(1)
item.foo_count # => 0
Item.increment_counter(:foo_count, 1)
item.foo_count # => 0
item.reload
item.foo_count # => 1
item.increment(:foo_count)
item.foo_count # => 2
As per your logic the code will be
Package.increment_counter(:counter, 1)
#package.increment(:counter)

Related

How to set an expiry on a cached Ruby search?

I have a function, which returns a list of ID's, in the Rails caching guide I can see that an expiration can be set on the cached results, but I have implemented my caching somewhat differently.
def provide_book_ids(search_param)
#returned_ids ||= begin
search = client.search(query: search_param, :reload => true)
search.fetch
search.options[:query] = search_str
search.fetch(true)
search.map(&:id)
end
end
What is the recomennded way to set a 10 minute cache expiry, when written as above?
def provide_book_ids(search_param)
#returned_ids = Rails.cache.fetch("zendesk_ids", expires_in: 10.minutes) do
search = client.search(query: search_param, :reload => true)
search.fetch
search.options[:query] = search_str
search.fetch(true)
search.map(&:id)
end
end
I am assuming this code is part of some request-response cycle and not something else (for example a long running worker or some class that is initialized once in your app. In such a case you wouldn't want to use #returned_ids directly but instead call provide_book_ids to get the value, but from I understand that's not your scenario so provided approach above should work.

Rails - submitting JSONs to database from controller

I am working on a Rails app, and I am attempting to insert attributes from JSONs as database entries. I'm running into a problem, though, and would appreciate some guidance.
I've been able to jam a few things together and come up with something that sort of works...
def create
#report_group = Array.new
#report_group.push({location:"home", comments:"Hello, database!"}, {location:"away", comments:"Goodbye, database!"})
#report_group.each do |x|
#new_report = Report.new(x)
#new_report.user_id = current_user.id
#new_report.save
end
end
private
def report_params(params)
params.permit(:user_id,:location,:comments)
end
This is a good first step - this commits two entries to my database, one for each of the hashes pushed into #report_group, but it is suffering from a problem - the create action does not reference the report_params whitelist.
I have built several Rails apps where entries are submitted one at a time via the standard Rails form helpers, but I have never done it with multiple JSONs like this before. Trying out the syntax I'd use in a typical form helper situation
#new_report = Report.new(report_params(x))
throws the expectable error undefined method permit' for #<Hash:0x007f966b35e270> but I am not sure what else to do here.
EDIT TO SHOW SOLUTION
Big thanks to #oreoluwa for pointing me in the right direction. Here's the solution that I came up with.
def create
#report_group = Array.new
#report_group.push({location:"home", comments:"Hello, database!"}, {location:"away", comments:"Goodbye, database!"})
#report_group.each do |x|
hash = ActionController::Parameters.new(x)
#new_report = Report.new(report_params(hash))
#new_report.user_id = current_user.id
#new_report.save
end
end
private
def report_params(params)
params.permit(:user_id,:location,:comments)
end
You're getting the error because a Hash is not the same as an ActionController::Parameters. In order to use the permit method with your Hash you may need to first convert it to ActionController::Parameters, as such:
hash = {location:"home", comments:"Hello, database!"}
parameter = ActionController::Parameters.new(hash)
parameter.permit(:user_id,:location,:comments)
I don't know if that is what you're looking for, but I thought to point you in the right direction.

How to update an active record in ruby

I want to update status to 1, when user views a message.
i need an active record, to change status to 1 ,where status is 0 and id is current id
Any help is appreciated.
i want to change this query to active record.
UPDATE 'course_queries SET status = '1' WHERE course_queries.id =41 and status=0;
As Nithin mentioned, ActiveRecord is a rails feature. Thus, the following wouldn't work unless you're using the Ruby on Rails framework.
With that said, you could also try:
#course = CourseQuery.where(id: params[:id], status: 0).each do |q|
q.update(status: 1)
end
If you need it all in one line, you could use:
#course = CourseQuery.where(id: params[:id], status: 0).update_all(status: 1)
You can then change the id or status here dynamically. :)
Since these examples use the update and update_all methods, I'd recommend you read up about them. Here's a great article I've found on the differences: Difference between active record methods – update, update_all, update_attribute, update_attributes
Something like this
Using ActiveRecord.
#course_query = CourseQuery.find(params[:id]) #id is 41 from your comment
if #course_query.status == 0
#course_query.status = 1
#course_query.save
end

How to show search results on rails event_calendar?

I'm new to Rails and I am using rails event_calendar plug-in on my project. I implement it basic CRUD (Create, Read, Update, Delete ) operations on events. But now I need to show my search results on event_calendar. So please can some one give me an idea to implement this on event_calendar ??
From the event_calendar README:
The EventCalendar.new method accepts a hash or block of options, for example:
#event_calendar = EventCalendar.new(2009, 10, :id => 'calendar', :events => Event.all)
#event_calendar = EventCalendar.new(2009, 10) do |c|
c.id = 'calendar'
c.events = Event.all
end
So, instead of Event.all, just use whatever code you're using to get your filtered results.

In Rails, what is the best way to update a record or create a new one if it doesn't exist?

I have a create statement for some models, but it’s creating a record within a join table regardless of whether the record already exists.
Here is what my code looks like:
#user = User.find(current_user)
#event = Event.find(params[:id])
for interest in #event.interests
#user.choices.create(:interest => interest, :score => 4)
end
The problem is that it creates records no matter what. I would like it to create a record only if no record already exists; if a record does exist, I would like it to take the attribute of the found record and add or subtract 1.
I’ve been looking around have seen something called find_or_create_by. What does this do when it finds a record? I would like it to take the current :score attribute and add 1.
Is it possible to find or create by id? I’m not sure what attribute I would find by, since the model I’m looking at is a join model which only has id foreign keys and the score attribute.
I tried
#user.choices.find_or_create_by_user(:user => #user.id, :interest => interest, :score => 4)
but got
undefined method find_by_user
What should I do?
my_class = ClassName.find_or_initialize_by_name(name)
my_class.update_attributes({
:street_address => self.street_address,
:city_name => self.city_name,
:zip_code => self.zip_code
})
Assuming that the Choice model has a user_id (to associate with a user) and an interest_id (to associate with an interest), something like this should do the trick:
#user = User.find(current_user)
#event = Event.find(params[:id])
#event.interests.each do |interest|
choice = #user.choices.find_or_initialize_by_interest_id(interest.id) do |c|
c.score = 0 # Or whatever you want the initial value to be - 1
end
choice.score += 1
choice.save!
end
Some notes:
You don't need to include the user_id column in the find_or_*_by_*, as you've already instructed Rails to only fetch choices belonging to #user.
I'm using find_or_initialize_by_*, which is essentially the same as find_or_create_by_*, with the one key difference being that initialize doesn't actually create the record. This would be similar to Model.new as opposed to Model.create.
The block that sets c.score = 0 is only executed if the record does not exist.
choice.score += 1 will update the score value for the record, regardless if it exists or not. Hence, the default score c.score = 0 should be the initial value minus one.
Finally, choice.save! will either update the record (if it already existed) or create the initiated record (if it didn't).
find_or_create_by_user_id sounds better
Also, in Rails 3 you can do:
#user.choices.where(:user => #user.id, :interest => interest, :score => 4).first_or_create
If you're using rails 4 I don't think it creates the finder methods like it used to, so find_or_create_by_user isn't created for you. Instead you'd do it like this:
#user = User.find(current_user)
#event = Event.find(params[:id])
for interest in #event.interests
#user.choices.find_or_create_by(:interest => interest) do |c|
c.score ||= 0
c.score += 1
end
end
In Rails 4
You can use find_or_create_by to get an object(if not exist,it will create), then use update to save or update the record, the update method will persist record if it is not exist, otherwise update record.
For example
#edu = current_user.member_edu_basics.find_or_create_by(params.require(:member).permit(:school))
if #edu.update(params.require(:member).permit(:school, :majoy, :started, :ended))

Resources