I am trying to build a very simple rails application.
When user submits a form I process some files on the server and display the results.
Clearly, I do not need a database for this. However, I created a model so that I can put all my processing logic in it.
In in the controller, I call the process function in the model. for example
# action in controller
def my_action
MyModel.process(params)
end
However, when I run the server and submit the form, rails says MyModel is uninitialized
uninitialized constant MyController::MyModel
What am I doing wrong?
Where do you define MyModel? Is it in app/models/my_model.rb as Rails (to put it simply) expects it to be?
Related
I am using Rails 4 w/ the impressionist and resque gem.
I am using impressionist to log unique session hits on my article show page. Due to performance issues and no need to display hits to users (it is for admins only), I would like to move logging impressions off into the background.
Normally I would log an impression using impressionist(#article, unique: [:session_hash]) but to move it off into the bg via resque I am now doing something like this...
articles_controller:
def show
.
.
.
Resque.enqueue(ImpressionLogger, #article.id)
end
app/workers/impression_logger.rb:
class ImpressionLogger
#queue = :impression_queue
def self.perform(article_id)
article = Article.find(article_id)
impressionist(article, unique: [:session_hash])
end
end
When I set it up like this, when resque tries to process the job, it is returning undefined method "impressionist" for ImpressionLogger:Class. What do you guys think the best way to go about this is? I am not sure how to include impressionist methods inside of my resque worker.
The issue
Your problem stems from the fact that it looks like Impressionist works on the controller level due to including a module with the impressionist method in an engine initializer on any instances of ActionController:
https://github.com/charlotte-ruby/impressionist/blob/master/lib/impressionist/engine.rb#L11
You're trying to call the impressionist method from a regular class being invoked in a Resque job, so it's not going to have that method defined.
Solution
It's kind of gross, but if you really want to use impressionist, we can delve into this... Looking at the actual implementation of the impressionist method found here, we see the following:
def impressionist(obj,message=nil,opts={})
if should_count_impression?(opts)
if obj.respond_to?("impressionable?")
if unique_instance?(obj, opts[:unique])
obj.impressions.create(associative_create_statement({:message => message}))
end
else
# we could create an impression anyway. for classes, too. why not?
raise "#{obj.class.to_s} is not impressionable!"
end
end
end
Assuming that you'd be calling something like this manually (as you want to from a resque job) the key are these three lines:
if unique_instance?(obj, opts[:unique])
obj.impressions.create(associative_create_statement({:message => message}))
end
The if wrapper only seems to be important if you want to implement this functionality. Which it looks like you do. The call to associative_create_statement seems to be pulling parameters based off of the controller name as well as parameters passed from Rack such as the useragent string and ip address (here). So, you'll have to resolve these values prior to invoking the Resque job.
What I would suggest at this point is implementing a Resque class that takes in two parameters, an article_id and the impression parameters that you want. The resque class would then just directly create the impression on the impressionable object. Your Resque class would become:
class ImpressionLogger
#queue = :impression_queue
def self.perform(article_id, impression_params = {})
article = Article.find(article_id)
article.impressions.create(impression_params)
end
end
And your controller method would look something like this:
def show
.
.
.
Resque.enqueue(ImpressionLogger, #article.id, associative_create_statement({message: nil})) if unique_instance?(#article, [:session_hash])
end
Disclaimer
There's a fairly big disclaimer that comes with doing it this way though... the method associative_create_statement is marked protected and unique_instance? is marked private... so neither of these is part of the impressionist gem's public API, so this code might break between versions of the gem.
Is impressionist installed properly with bundler? If so Rails should be loading it into your environment. I would check whether you can access impressionist functionality elsewhere in your Rails code (i.e. without going through Resque) as the first step to debugging this.
How are you starting your resque workers? If you need your Rails environment loaded, try rake environment resque:work.
https://github.com/resque/resque/wiki/FAQ#how-do-i-ensure-my-rails-classesenvironment-is-loaded
I am studying Ruby On Rails and complete novice at it. I find that it is a bit difficult to trace the process order of a functionality (e.g.: user clicks a button in the form).
I wonder if there is any tool or way to know the process (ie: What method in a controller is called, corresponding model method,....). I would like to trace the order of regarding process and it helps me much in debugging.
You can use byebug or other debugging tools. Example and other ways of debugging can be found at rails website: http://edgeguides.rubyonrails.org/debugging_rails_applications.html
For example if you choose byebug and decide to put it in a controller:
class PeopleController < ApplicationController
def new
byebug
#person = Person.new
end
end
When your code reaches byebug line of your controller it will pause and wait for your command at your rails server command terminal. You can give various commands at this point,
for example,
if you type next it will move to next line.
if you type instance_variables to see all the variable values.
If you type thread list for list all threads and their statuses.
I have a Post Mode ,and a controller called happy_robot_controller,which will periodically crawl certain web sites , gather the data I am interested in , and then save to the Post Model.
skeleton of happy_robot_controller.rb:
craw the web site and get the interested data, save to title and content variables
#save to the Model
Post.new(:title=>title, :content=>content).save
Executing ruby happy_robot_controller.rb :
root#pierr-desktop:/work/web/yy/app/controllers# ruby happy_robot_controller.rb
happy_robot_controller.rb:54: uninitialized constant Post (NameError)
How should I be able to access the Post class? Should happy_robot_controller inherits ApplicationController like PostController do?
OR, should I put happy_robot in the models/post.rb?
It sounds like this "crawler" code should go into a rake task.
Start by creating the file RAILS_ROOT/lib/tasks/happy_robot.rake and put in the following:
namespace :happy_robot do
task :crawl => :environment do
# crawling code goes here
Post.new(:title=>title, :content=>content).save
end
end
You can then run this code by executing rake happy_robot:crawl from the command line (within your project directory of course).
Here is a nice rake tutorial: http://jasonseifer.com/2010/04/06/rake-tutorial
Trying to integrate some friendly_id gem functionality on a controller method.
Essentially, I have a Market object, which has its URL created based on a custom method. Since it's based on a custom method, friendly_id won't update the URL when the Market object gets updated. Friendly_id does offer a redo_slugs rake task, but when I call it from within my controller, it tells me that it can't build the task. Running the command outside works just fine.
The code for my controller looks like this:
require 'rake'
require 'friendly_id'
class Admin::MarketsController < ApplicationController
def update
if #market.update_attributes(params[:market])
rake_market_slugs
end
end
protected
def rake_market_slugs
Rake::Task["friendly_id:redo_slugs MODEL=Market"].invoke
end
end
Am I missing something? Or can I just not do this inside my controller?
Thank you.
Calling a rake task from a controller to update a model object is terrible. Looking at the code for that rake task, you can see that redo_slugs is simply running the delete_slugs and make_slugs tasks. So there's another reason not to do this. You'll be generating slugs for every Market in your table, instead of just the one that you need.
If you look at the code for make_slugs you can see that there's no magic there. All it does is load your model objects in blocks of 100 and then save them.
So, that would be the first thing I would try. Simply reload and save your model. After that, I'd need to see some logs to dig deeper.
def rake_market_slugs
MODEL="Market"
Rake::Task["friendly_id:redo_slugs"].invoke(MODEL)
end
Try it...
NameError in GenresController#index
uninitialized constant GenresController
RAILS_ROOT: C:/Users/Will/Desktop/INSTAN~1/rails_apps/talewiki
I've created a table called Genres and when I try to connect to it via local host I get the above error.
Any ideas?
With all the questions you're asking I believe you're an absolute beginner regarding ROR. Perhaps you should visit some tutorials to learn rails.
I don't know what your genre model describes, but I think it will have a name.
Basic steps for a basic genre model:
Delete the table for your genres if created manually (with SQL code)
DROP TABLE genres;
generate a complete scaffolding for genres:
$ ruby script/generate genre name:string
$ rake db:migrate
Now you have a complete controller for all CRUD actions for a simple genre model
If I were you I would read some tutorial about RoR, because you make the impression that you don't understand RoR or the MVC principle behind it. A good start would be: http://storecrowd.com/blog/top-50-ruby-on-rails-tutorials/
You need to generate a controller to handle the index action when your browse your application on localhost
ruby script/generate controller genres index
run that from your console within your application and it will generate the GenresController with the action index (it will be an empty action but you shouldn't see an error when browsing http://localhost:3000/genres/)
file
C:/Users/Will/Desktop/INSTAN~1/rails_apps/talewiki/app/controllers/genres_controller.rb
must be present