I am making a clone of Joe's Goals. I have a very rough version of this that I built with a rails scaffold. The week's table has 7 days and the name of a habit. My problem is how do I increase the number of occurrences (integer representing how often you did that habit) from the index.html.erb view, without entering the edit form.
I looked at a couple of things on S.O. building custom methods in my controller.
How can I make a link_to in my index table field so that it changes the integer.
Here is what my Table looks like. The way its set up is like this:
class CreateWeeks < ActiveRecord::Migration
def change
create_table :weeks do |t|
t.string :habit
t.boolean :gob
t.integer :sunday
t.integer :monday
t.integer :tuesday
t.integer :wednesday
t.integer :thursday
t.integer :friday
t.integer :saturday
t.timestamps null: false
end
end
end
As you can see i've put a couple up/down arrows to show what I am trying to do. Right now they just link to my root path. As I said, I would like them to change the value of the integer in the selected field. I've only put the arrows on monday in this image btw.
in my controller I have:
def increase
#week = Week.find(params[:id])
#week.update_attribute("monday", monday += 1)
#week.save
flash[:notice] = "Habit Increased."
end
I am trying to increase the integer with this link:
<%= link_to "+ 1", :method => :increase, :monday => #increase %>
Are you using AJAX? If you are not, then you should be using AJAX on rails. You can check this documentation and also may be this video will help you in achieving what you need.
Related
I have part of a rails application where a user will create a recipe that will be saved in their "cookbook". Other users will be able to take recipes from other users. So there will be an aspect in the application that shows who created the recipe.
Schema for a Recipe
create_table "recipes", force: :cascade do |t|
t.string "recipe_name"
t.string "description"
t.integer "calories"
t.integer "carbs"
t.integer "fats"
t.integer "protein"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Where I am having trouble is displaying the recipe's creator.
def show
#user = current_user
#recipe = Recipe.find_by(params[:id])
creator = User.find_by(params[#recipe.user_id])
#creator = creator.first_name
end
So for right now I have two user's John (Id: 1) and Alex (Id:2). When I have Alex make a recipe and I put a pry under #recipe I get a user_id of 2 when I call #recipe.user_id.
However, when I put the pry under creator and call creator I get the user_id of 1 and I get John. I believe something is wrong with how I am trying to find the user using the user_id in #recipe. I was wondering if anyone know what I am doing wrong or if I need to add more information. Thanks.
This:
User.find_by(params[#recipe.user_id])
Doesn't make sense for a couple of reasons:
find_by expects a hash-like structure. Something like: User.find_by(id: xxx)
params[#recipe.user_id] doesn't make sense because that's going to be something like: params[1] which is not what you want.
This:
#recipe = Recipe.find_by(params[:id])
Also suffers from the malformed find_by.
So, try something like:
def show
#user = current_user
#recipe = Recipe.find(params[:id])
creator = #recipe.user
#creator = creator.first_name
end
This, naturally, assumes you have your association between Receipt and User set up correctly (i.e., using belongs_to).
So, I'm using Rails 4, and I have an enum column on my "Sales_Opportunity" object called pipeline_status - this enables me to move it through a sales pipeline (e.g. New Lead, Qualified Lead, Closed deal etc). This all works fine. I'm able to find the number of sales_opportunities that a company has by status through using the following:
<%= #company.sales_opportunities.where(pipeline_status: 3).count %>
This all works fine. What I want to do is to find all sales_opportunities that have the pipeline_status of "closed_won" (enum value of 4 in my app) and sum the value of each won deal (so I can represent the total value of the customer based on the deals that are won in the system). A Sales_Opportunity in my model has a sale_value field, so I tried:
<%= #company.sales_opportunities.where(pipeline_status: 4).each.sale_value.sum %>
which returns the following error:
undefined method `sale_value' for #<Enumerator:0x007f9b87a9d128>
This is probably a trivial error but I can't for the life of me figure out what's going on. Is there where statement returning the enumerator or the sales_opportunity objects with that enumerator? Any help would be gratefully appreciated.
If it helps here are the fields in my sales_opportunities table:
create_table "sales_opportunities", force: true do |t|
t.datetime "close_date"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "pipeline_status", default: 0
t.string "opportunity_name"
t.integer "company_id"
t.decimal "sale_value", precision: 15, scale: 2, default: 0.0
end
A Sales_opportunity belongs_to a Company Object and a User Object, if that makes any difference.
use aggregate function sum
<%= #company.sales_opportunities.where(pipeline_status: 4).sum(:sale_value) %>
Other possibility is to use
<%= #company.sales_opportunities.where(pipeline_status: 4).pluck(:sale_value).reduce(0, :+) %>
Let's say we have the following model.
create_table :meetings do |t|
t.datetime :started_at
t.datetime: ended_at
end
class Meeting < ActiveRecord::base
end
How would I order a meetings_result, so that the longest meeting is the first meeting in the collection and the shortest meeting the last.
Something like
Meeting.order(longest(started_at..ended_at))
Obviously that doesn't work.
How would I achieve this, preferably without using raw SQL?
I don't think you can do it without using raw SQL.
Using Raw SQL:
Meeting.order('(ended_at - start_at) DESC')
(works with PostGreSQL)
No SQL? Two options come to mind. Create an array of hashes and sort it there, or add another column in the db and sort on that.
# How many records in the meetings table? This array of hashes could get huge.
meetings_array = []
Meeting.all.each do |meeting|
meetings_array << {id: meeting.id, started_at: meeting.started_at, ended_at: meeting.ended_at , duration: meeting.ended_at - meeting.started_at }
end
meetings_array.sort_by { |hsh| hsh[:duration] }
Or, create another column:
# Is it worth adding another column?
create_table :meetings do |t|
t.datetime :started_at
t.datetime :ended_at
t.datetime :duration
end
Update this column whenever you have both started_at and ended_at. Then you can:
Meeting.order("duration")
I have imported a .csv file of 10,000 locations and I need to loop through the database and geocode_by a few fields rather than the usual "geocode_by :address"
I am using the geocoder gem.
My database scheme looks like this
create_table "locations", :force => true do |t|
t.string "Address"
t.string "City"
t.string "State"
t.string "Zip"
t.float "latitude"
t.float "longitude"
t.datetime "created_at"
t.datetime "updated_at"
end
Can I do this in a controller action rather than on validation?
Should I do something like this:
def index
#locations = Location.all
#locations.each do |l|
new_address = "#{l.Address} #{l.City} #{l.State}"
geocode_by = :new_address
end
end
But yea, any help is greatly appreciated, thank you!
I was able to get things working with this controller code:
def index
if params[:search].present?
#locations = Location.near(params[:search], 20, :order => :distance)
else
#locations = Location.all
#locations.each do |l|
if l.latitude.nil?
new_location = "#{l.HP_Address_1} #{l.HP_City} #{l.HP_State}"
s = Geocoder.search(new_location)
l.latitude = s[0].latitude
l.longitude = s[0].longitude
l.save
end
end
end
end
It loops through every entry in the database, and if the latitude and longitude values have not been encoded it calls the correct geocoder function, and stores the returned lat / long values in the database.
I have 9k entries in my database, so I can only encode 2k per day due to the limit on the google maps api. But for folks used to encoding entries during creating using geocoded_by in their models, this will work in controllers.
This is the kind of thing I'd do with workers (delayed job or resque), since it might take some time to complete. But I'm not sure I understood the question, so this might not be the kind of answer you're expecting.
There is a rake task for this if you want to do every record in a class.
rake geocode:all CLASS=YourModel sleep=0.25
I have strange globalize2 problem. I'm trying to use globalize 2 and acts_as_textiled and acts_as_commentable. For example - lets we have Post model, that acts_as_commentable. From console
p = Post.find 1
c = p.comments.find 1
works fine, but in browser - nothing displayed
Similar, when Post contains
acts_as_textiled :body
from console body is containing correct data, but in browser i see nothing :(
Any ideas how to correct it?
Upd: "nothing displayed" means,
that for code like
class Post < ActiveRecord::Base
translates :title, :body
acts_as_textiled :body
end
on access to Post.body i've got nil, but on disabled globalize2 or
acts_as_textiled body returns his value. I've tried with different
locales - the same result.
Have you performed the necessary migrations? For localised content you should remove the localised fields in the main table (posts) and create a table for the localisations, like this:
create_table "post_translations", :force => true do |t|
t.string "locale"
t.integer "product_id"
t.string "title"
t.text "body"
end
Just guessing here :)