I understand that the application_controller will produce variable values for an entire application but have never applied that knowledge. There is a variable that comes up in most of my controllers... #qs for the number of questions. The following code is not working.
application_controller:
def qs
if current_user.sec_paid and current_user.min_paid
#qs = 36
elsif current_user.sec_paid
#qs = 25
else
#qs = 5
end
end
applets_controller:
#strengths = Strength.where("position <= ?", #qs).order("position")
applet1.html.erb:
<%=#qs.to_i%>
The output to a view file is just a way to test for the value of the variable and will be removed. Currently it produces a zero.
Any help is appreciated. Specific changes to my code is most appreciated.
Use before_filter :qs in your ApplicationControler (or in those controllers it is needed) to invoke the qs method on every call. In this way the #qs variable will be initialized.
Related
Im current working on a small project and I want to seed my database faster. I migrated a new column called "grand_total_points" to my table of users. So originally I was using this code.
user = User.all
user.each do |x|
x.grand_total_points = x.total_points
x.save!
end
This takes me ages, because I have to update a million record.
Total_points have already been defined in my user model where it calculates all the users points that have been submitted. Forgive me for my explanation. Is there a way to use update_all method but with each included in it?
Yep, possible:
User.update_all('grand_total_points = total_points')
It will generate the following SQL query:
UPDATE "users" SET "grand_total_points" = 'total_points'
If total_points is not a column but an instance method, move the logic into update_all query.
User.update_all("grand_total_points = #{total_points calculation translated into SQL terms}")
I found something that could work. So basically i combine a ruby code with an execute SQL statement, and I put it in a migration file. Here's how the code works. I hope this helps. Make sure you follow the query according to your data.
class ChangeStuff < ActiveRecord::Migration
def change
points = Point.select('user_id, SUM(value) AS value').group(:user_id)
points.each do |point|
execute "UPDATE users SET grand_total_points = #{point.value} WHERE users.id = #{point.user_id}"
end
end
end
You should run bundle exec rake db:migrate after that. The normal way takes me 2-3hours. This only took me 2minutes.
This should be fairly simply...
I have Recommendations has_many Assets.
I want to limit the user to adding 3 Assets per Recommendation, and I can do this simply by limiting the number of fields show.
In my new action in the controller I am doing a very simple:
3.times {#recommendation.assets.build}
In my edit action I am trying to build the logic to decide how many fields to show:
#assets = #recommendation.assets.all
if #assets.empty?
3.times {#recommendation.assets.build}
else
asset_loop = #assets.count - 3
asset_loop.times {#recommendation.assets.build}
end
The if works but the else does not. How can I make this work?
If I understand your goal, you just need to change
asset_loop = #assets.count - 3
to
asset_loop = 3 - #assets.count
Do make sure to validate the incoming data if you want to truly enforce the limit. Otherwise you're at the mercy of anyone with a web console and curl.
I have a query that goes something like this (in song.rb):
def self.new_songs
Song.where(id: Song.grouped_order_published).select_important_stuff
end
Later on in my app, it is then passed the limit and offset, lets say in the controller:
#songs = Song.new_songs.limit(10).offset(10)
The way my app is structured, I'd like to keep this method of setting things, but unfortunately it is really slow as it is limiting the outer query rather than the subquery.
Is there a way I can expose the subquery such that it receives the limit and offset rather than the outer query?
Edit: I should add I am using postgres 9.2.
Edit 2: The reason why I want to do it in this fashion is I am doing pagination and I need to get the "count" of the total number of rows. So I do something like this:
#songs = Song.new_songs
...
#pages = #songs.count / 10
...
render #songs.limit(params[:page]).offset(0)
If I were to change it somehow, I'd have to redo this entirely (which is in a ton of places). By not limiting it until it's actually called, I can do the count in between and then get just the page at the end. I guess I'm looking more for advice on how this can be done with the inner query, without becoming horribly slow as the database grows.
I could not try the solution and I am not a ruby expert either, but as far as I understand the problem you would need an object that passes all method-calls but limit and offset onto the full query and store the limited sub_query in the meantime.
It could probably look like this:
class LimitedSubquery < Object
# sub_query has to be stored so we can limit/offset it
def initialize(sub_query)
#sub_query = sub_query
end
# Make sure everybody knows we can be used like a query
def self.respond_to?(symbol, include_private=false)
super || full_query.respond_to?(symbol, include_private)
end
# Missing methods are probably meant to be called on the whole query
def self.method_missing(method_sym, *arguments, &block)
if full_query.respond_to?(method_sym)
full_query.send(method_sym, *arguments, &block)
else
super
end
end
# Generate the query for execution
def self.full_query
Song.where(id: #sub_query).select_important_stuff
end
# Apply limit to sub_query
def self.limit(*number)
LimitedSubquery.new(#sub_query.limit(*number))
end
# Apply offset to sub_query
def self.offset(*number)
LimitedSubquery.new(#sub_query.offset(*number))
end
end
And than call it like
def new_songs
LimitedSubquery.new(Song.grouped_order_published)
end
Please edit me if I got something wrong!
Regards
TC
You should consider using the will_paginate gem. This keeps you away form the hazzle to calculate all this by hand ;-)
I have a query written in Mongoid
#result = User.find(:name=>"xxxxx").limit(5)
and I return the data in json as
render :json =>#result.to_json()
Now I want add the total number of user whose names are xxxxx into the #result variable. I have tried few thing but nothing worked ex
#new_result ={:result =>#result, :count=>#result.length}
and
render :json =>#new_result.to_json()
the output is
[{new_result:null,count:25}]
Basically I am able to get the count but I am not able to add that count to my #result. Is there a way to get this working.
A gentle reminder:
All queries in Mongoid are Criteria, which is a chainable and lazily evaluated wrapper to a MongoDB dynamic query.
See: http://mongoid.org/en/mongoid/docs/querying.html#query_plus
Make sure to understand that Mongoid Criteria are lazily evaluated, otherwise it will cause you confusion
and cost you time, and more time ...
When I run your #result = User.find(:name=>"xxxxx").limit(5), I get a Mongoid::Errors::DocumentNotFound exception,
this is with Mongoid 2.4.10. Are you sure that your question is accurate?
I've changed it to User.where, and #result = User.find(:name=>"xxxxx").limit(5) is a Criteria,
not (yet) a User instance read from MongoDB.
The following test should help to make clear that due to lazy evaluation,
the DB query only occurs when it is needed, e.g., after method to_json and method length.
Also, tail your log, and note that each use of #result with a to_json or length method
results in a repeated DB query which is inefficient and probably not what you intended.
You can force an evaluation and fetch by using methods like Enumerable#to_a or Enumerable#each.
test/unit/user_test.db
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
User.delete_all
end
test "mongoid lazy eval" do
User.create(name: 'xxxxx')
assert_equal(1, User.count)
puts "User.all.to_a: #{User.all.to_a.inspect}"
assert_raises Mongoid::Errors::DocumentNotFound do
#result = User.find(:name=>"xxxxx").limit(5)
end
puts "#result = User.find(:name=>\"xxxxx\").limit(5); #result: #{#result.inspect}"
#result = User.where(:name=>"xxxxx").limit(5)
puts "#result = User.where(:name=>\"xxxxx\").limit(5); #result.class: #{#result.class}"
puts "#result.to_json: #{#result.to_json}"
puts "#result.length: #{#result.length}"
#new_result ={:result =>#result, :count=>#result.length}
puts "#new_result: #{#new_result.inspect}"
puts "#new_result.to_json: #{#new_result.to_json}"
end
end
test output
Run options: --name=test_mongoid_lazy_eval
# Running tests:
User.all.to_a: [#<User _id: 4fca03e7e4d30b1e42000001, _type: nil, name: "xxxxx">]
#result = User.find(:name=>"xxxxx").limit(5); #result: nil
#result = User.where(:name=>"xxxxx").limit(5); #result.class: Mongoid::Criteria
#result.to_json: [{"_id":"4fca03e7e4d30b1e42000001","name":"xxxxx"}]
#result.length: 1
#new_result: {:result=>#<Mongoid::Criteria
selector: {:name=>"xxxxx"},
options: {:limit=>5},
class: User,
embedded: false>
, :count=>1}
#new_result.to_json: {"result":[{"_id":"4fca03e7e4d30b1e42000001","name":"xxxxx"}],"count":1}
.
Finished tests in 0.038161s, 26.2048 tests/s, 52.4095 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
Newbie here. I am trying to store the result of my search onto a variable.
#answer = q.answers.select(:name) which runs
"SELECT name FROM "answers" WHERE "answers"."question_id" = 1;" and returns
"t" for true.
It runs fine on the command line and shows the right result. But I want to compare that result to another variable.
How do i extract that result? #answer[0], or #answer, or answer_var = #answer[0]
i.e.
if #answer == some_other_variable OR
if #answer[0] == some_other_variable OR
if answer_var == some_other_variable
what value do #answer[0] and #answer[0] hold and how can I print the value to the log file? not the web page. I know it must be simple, but I can't get my head around it.
Thanks.
It's not really an answer to your question but...
If you want to follow "the rails way", you should better use Models and not deal with SQL at all.
E.g. :
#answer = q.answers.first # answers is an array, take the first
if #answer.name == ...
For the logging, I suggest you that : http://guides.rubyonrails.org/debugging_rails_applications.html#the-logger