passing named_scope as argument - ruby-on-rails

I am reusing a controller method and I need to change the scope as required.
I have stored the scope name in a session and would like to be able to do the following.
if params[:scope_name]
session[:submission_scope_name] = params[:scope_name]
else
session[:submission_scope_name] = "allSubs"
end
#search = Submission.session[:submission_scope_name].search do
...
end
The code above is giving me the following error message:
undefined method `session' for #<Class:0x00000002ad7df0>
Is there any way of passing a named_scope as an argument?

You probably don't want to do this from a security standpoint: a malicious user could make a poorly-formed submission_scope that you'll just be sending straight to Submission.
That said, you're looking for the method send here. Try this instead:
Submission.send(session[:submission_scope_name].to_sym).search
send will try to call a method on that object named whatever symbol you passed in. You can read more about it in the Ruby core docs, but ultimately doing that would allow you to send whatever named scopes to Submission you want.

Related

How to find and use a helper method from String

I would like to know how to find and use a helper method, when I have the name of the helper in a string format.
I am writing an engine, and in the initializer file, users can specify the current_user_helper as such:
MyEngine.current_user_helper = "current_user"
I would like to do something with this in the controller. For instance, the code below tries to create a Post for the logged in user.
MyEngine.current_user_helper.posts.new(post_params)
Yet, this code does not work because MyEngine.current_user_helper is a string. Apparently, Rails will throw an error when I try:
MyEngine.current_user_helper = current_user
without the quotation marks.
Any suggestions?
You can use send to call a method from a string or symbol. send is available on all descendants of Object.
send(MyEngine.current_user_helper).posts.new

Dynamic method call in routes spec

I am testing simple get requests for my routes using rspec in my Rails 3.2 application. Since all are get requests, and all just have different action names which are similar to the views' names, it would be really repetitive to manually write a different test for each get request.
Instead, I wanted to come up with something like this:
%(action_1 action_2 action_3 action_4).each do |action|
it "routes to the #{action} page" do
get("liver_diseases#{action}_path").should route_to("liver_diseases##{action}")
end
end
It fails at this pseudocode: get("liver_diseases_#{action}_path")
So what I need to do is a dynamic method call - but for what I have found out, that would involve .send(:method_name), for which I need to know the class name. And I couldn't find that.
What do I need to do for this method call to work?
that would involve .send(:method_name), for which I need to know the
class name
When the receiver is missing, it's always self. In the context of a controller example, self should be a controller instance. So you should be able to get that path with:
send "liver_diseases_#{action}_path"
which should be equivalent to:
controller.send "liver_diseases_#{action}_path"

What is the best way to give a model access to params hash in Rails?

This appears to be a violation of MVC, so I'll explain what I am trying to do:
My model makes a call to an API, and the URI of the API depends on the params hash. (The params hash stores the URL of the Rails app).
I created a module to mix into the model (because the model has nothing to do with the API call), but haven't figured out how to get the params into the module.
If possible, I would like to initialize the module with the params hash, but don't know where to do it. before_create on the model would work, but that is in the model.rb file which doesn't know about the params.
Couple ideas, depending on your needs:
Pass the parameters to the model with each call, if they change that much. You could do a class method or instance method -
Model.api_call params[:field]
#model.api_call params[:field]
Save the parameters as class variables in the model:
Model.set_parameters(params)
def self.set_parameters(params)
##params = params
end
# access it in methods with ##params

Can ActiveResource POST a create instead of PUTTing it when an id is specified?

I'm calling a rails app from another using ActiveResource. I need to supply the id of the new object to the first app (yes, controller create in this app knows how to handle receiving an id), so I do something like this:
a = ActiveResourceModel.new(:id => 1231231, :name => "test")
a.save
However, instead of doing POST to create a new resource it PUTs it, causing the receiving app to try to update the resource with id 1231231, which of course doesn't exist (I want to create it!), so I end up receiving a 404 error because of this.
Doing some testing the problem seems to be in ActiveResourceModel.new? which returns false, while ActiveResourceModel.exists? returns false too (Great, two methods which are supposed to be opposite return the same!).
Checking the AResource source and documentation, the new? method checks for the presence of the id and the exists? checks for the remote resource, making both returning the same.
Why exactly you need to pass the id to create a new object? Doesn't make sense.
Anyway, You can try to call create method instead of save.
I have the opposite problem. I EXPECT a PUT when calling AR.create with an id (since it implies the record already exists). However, with Rails 3.1 and up, it seems like the same code in Rails 3.0 that called PUT now in fact calls POST. Can anyone confirm this change? (Since I have control of the receiving server, I simply adjusted the POST code to have the same behavior as my old PUT code).

Is it possible to put validations in controllers in Ruby on Rails?

I have an additional member method (and a corresponding route) called download, for which I'd like to validate the existence of a password field.
Putting :validates_presence_of :password in my download method, I get an error claiming it's an undefined method.
Is this possible?
No, you can add errors to the model but validations live in the model. Check out the errors methods and add_to_base if you need to add errors in the controller for whatever reason.

Resources