I have a Machine model with a nested resource called Test. The linac has_many tests. The Test model has a boolean attribute called "Baseline". I also have a nested resource called Baselines, which doesn't have a model. It is meant to aggregate all of the most recent tests for that machine for which "Baseline" is set to "True".
In my Machine model, I have a scope called energy_x
class Machine < ActiveRecord::Base
scope :energy_x, lambda { |x| where(:energy => x) }
In my Baseline controller, I can successfully access this named scope:
#energies.each do |energy|
#baseline_tests << machine.baseline_tests.energy_x(energy)
end
But if I try to access this scope in the view,
<%= render :partial => "baseline_test", :collection => #baseline_tests.energy_x(energy) %>
I get a undefined method error:
undefined method `energy_x' for #<Array:0x007f9da7686950>
I've heard that I shouldn't be using a scope in a view anyway, but I need a way to sort the collection #baseline_tests according to a parameter. There are unlimited options for the value of this parameter, so it doesn't make sense to create an instance variable in the controller called #baseline_tests_1 and #baseline_tests_2. I think it has to be done in a loop in the view.
Any suggestions?
Related
is there any way you can load some factories for all controller tests? I've got a few of them which are necessary for all controller tests (menu items) and I don't like putting them all in controllers seperately. Not very DRY :)
Thanks
Maybe you can take a look at rspec's shared context, highlighted here: https://www.relishapp.com/rspec/rspec-core/v/2-11/docs/example-groups/shared-context
Create an RSpec macro.
Using user as the Factory you want to use, here's an example you'd put in spec/support/controller_macros.rb:
module ControllerMacros
let!(:user) { FactoryGirl.create :user }
end
In your spec/spec_helper.rb include the macro for controllers:
RSpec.configure do |config|
config.extend ControllerMacros, :type => :controller
end
The let! is like let as if it was referenced in a before block.
The ControllerMacros is also a handy place to add things like a sign_in method, etc.
You can also put shared examples in spec/support as well.
I'm making an app in Ruby on Rails 3.1.3. I have different types of users (i.e. admin, operator, advertiser, etc...), and each has a different main (or home) page. I want to make a route helper that will give me the respective route for the home page of the current logged in user by using something like home_path. This is mainly for redirecting after certain actions (I want to redirect back to the respective home pages depending on the type of user).
I already have some methods available such as current_user (returns the current logged in user), current_user.admin? (returns true if the current logged in user is admin), current_user.operator?, etc.
Right now I'm using a helper method to do this, but it doesn't seem like a very Rails way to do it. The code follows anyway:
def home_path(params = {})
user = current_user
case user
when user.admin?
params = {:controller => 'administrators', :action => 'index'}.merge(params)
when user.advertiser?
params = {:controller => 'advertisers', :action => 'show', :id => user.advertiser_id}.merge(params)
when user.operator?
params = {:controller => 'callcenter', :action => 'index'}.merge(params)
else
params = {:controller => 'posts', :action => 'home'}.merge(params)
end
url_for(params)
end
I figure this should be done with constrained routes, but I still don't get how it could be done to depend on the .admin?, .operator?, etc. methods. Any help on this would be greatly appreciated.
Using a helper method is fine for this. It should probably end up in your controller, rather than a view helper, though, which gives it access to the current_user. With some cleanup, you can arrive at something that ain't half bad with the same idea you have now.
module DefaultHomeHelper
DEFAULT_PARAMS = { controller: :posts, action: :home }.freeze
ROLE_SPECIFIC_PARAMS = {
admin: { controller: :administrators, action: :index },
advertiser: { controller: :advertisers, action: :show },
operator: { controller: :callcenter, :action: :index }
}.freeze
def home_path(params = {})
url_for params.reverse_merge(ROLE_SPECIFIC_PARAMS[current_user.role] || DEFAULT_PARAMS)
end
end
I've made the assumption you can be more direct and ask your User object to just tell you its role instead of guessing one after the other. You will almost certainly need to tweak the code to accomodate whatever you're calling this on your user. I've also used the newer hash syntax, but if you're running or accommodating Ruby < 1.9 you will need to update. I've used symbols for the actions and controller names, too, because I like referring to objects and methods with symbols instead of strings (and controllers and actions are objects and methods).
You could do a simple include DefaultHomeHelper in your ApplicationController to use this. You can also make it available to your views with helper_method :home_path.
I don't know if I'm being nit-picky with this one but how do you create a :new action member?
When I have
resources :posts, :except => [:show] do
get :another_new, :on => :collection
end
this gives me a plural one (in routes another_new_posts GET /posts/another_new(.:format)).
But when I use member, I do get singular but it wants an :id (in routes another_new_post GET /posts/:id/another_new(.:format)).
How do I create another new which would say in routes as another_new_post with /posts/new?
Place this as a standalone piece outside of your resources block:
match 'posts/another_new' => "posts#new", as: :another_new_post
Study -> has_many Topics -> has_many References
My Model has the following method to access references based on topic ID:
def self.rel_references(topic_id)
Reference.where(:topic_id => topic_id)
end
I am accessing the above in my controller as follows:
#references= Study.rel_references(params[:topic_id])
I need to have a form on the Study model's Show page to access the references based on the topics the user clicks. (A remote form that loads references based on the topic_id). The way I am trying to do this is:
- form_tag rel_references, :id=>"references_form", :method => 'get' do
= text_field_tag :topic_id, params[:topic_id]
= submit_tag "Get references"
However, I am not being able to access the references in my view. Please help me understand what I may be doing wrong here. I am very new to Rails so I might be missing something here. Thanks!
Removing the deprecated Style block helper - and replacing it with = in my form solved this problem for me. My form Now looks like:
= form_tag rel_references, :id=>"references_form", :method => 'get' do
= text_field_tag :topic_id, params[:topic_id]
= submit_tag "Get references"
I'm refactoring some specs, in controller specs I have a before(:each) which sets up things required in the session, wanted to avoid duplication and put the initial setup global for each controller spec
my before filter is...
config.before(:each, :type => :controller) do
#...
session[:current_user] = #user
session[:instance] = #instance
#...
end
#user and #instance are also set in the before(:each)
i've just hidden them for readability here
I get the following error when running the controller tests
undefined method `session' for nil:NilClass
I would expect the global before callbacks to have the same things as the ones in the individual tests but I guess maybe they are loaded before the rails environment has been initialised?
Thanks
Use controller.stub!(:session, { :current_user => #user, :instance => #instance })
I think this is more to do with Ruby and blocks (which are closures).
The block passed to before is bound to the context in which it is created, and session is not available in that context.