I have methods generated for a list of symbols. One of the methods includes a question mark in its definition. I want to invoke such a method with a variable holding that symbol.
Suppose we generate a method for :check_element symbol and the corresponding method signature would look like.
class A
def check_element?
end
end
Now I have a variable flag = :check_element and I'm unable to call the method like A.send(flag)
but A.send((flag.to_s + '?').to_sym) works.
I'm thinking if there is a better way to achieve this.
There is no need to translate the method name argument to a symbol because send accepts a string too. That allows simplifying your example to
A.send(flag.to_s + '?')
Which can be simplified using string interpolation to
A.send("#{flag}?")
Related
Either this doesn't exist or i am looking at this the wrong way.
In rspec, I want to stub a method/attribute of all the instances of a class but only if that instance follows a certain condition, for example:
the following code will stub all posts with given comments:
Post.any_instance.stub(:comments).and_return([comment1, comment2])
but I only want to stub comments if the post is published, otherwise i want a blank comments array.
Is there any way I can do something like this:
Post.any_instance.stub(:comments) do |post|
post.published ? [comment1,comment2] : []
end
I have seen solutions where you send an argument to the stubbed method and based on argument value you can return different values, but that's not the case here.
The code you've included should work fine. Stubbing with a block is documented in https://relishapp.com/rspec/rspec-mocks/v/3-3/docs/old-syntax/any-instance#block-implementation-is-passed-the-receiver-as-first-arg, although it's deprecated now in favor of the new methods described at https://relishapp.com/rspec/rspec-mocks/v/3-3/docs/working-with-legacy-code/any-instance
In the Rails documentation, the following example is given as a way to display what the server receives from a POST request:
def create
render plain: params[:article].inspect
end
In the subsequent description, the text states
The params method is the object which represents the parameters (or fields) coming in from the form. The params method returns an ActiveSupport::HashWithIndifferentAccess object.
While I understand that all methods are objects, I don't understand how it's correct to refer to the params object as a method. Specifically, the phrase "returns an ActiveSupport::HashWithIndifferentAccess object" suggests to me that there are two calls going on--what in python might look like:
params().__getitem__('article')
but I don't think that's what's actually going on.
The conversation around those lines also refers to params as a method, so I'm starting to think I must be missing something.
I'm new to Ruby, and while I understand that all methods are objects,
No, they aren't. Methods belong to objects (more precisely: methods are defined in modules, and executed in the context of objects), but they are not, by themselves, objects. (It is, however, possible to obtain a reflective proxy which represents the concept of a method by calling the method method, which returns a Method object.)
I don't understand how it's correct to refer to the params object as a method.
Because it is a method. Not an object.
What else would it be? Syntactically, it's obvious that it can only be one of three things: a keyword, a variable, or a method call.
It can't be a keyword, because Rails is just a Ruby library, and Ruby libraries can't change the syntax of the language (e.g. add or remove keywords). It can't be a variable, because in order for it to be parsed as a variable, the parser would need to have seen an assignment to it within the same block.
Ergo, the only thing it can possibly be, is a method call. You don't even need to know anything about Rails to know this. It's just basic Ruby syntax 101.
Specifically, the phrase "returns an ActiveSupport::HashWithIndifferentAccess object" suggests to me that there are two calls going on--what in python might look like:
params().__getitem__('article')
but I don't think that's what's actually going on.
That is exactly what is going on. You call the method params and then you call the method [] on the object that is returned by calling the method params.
This is in no way different from foo.bar: you call foo, then call bar on the return value of foo.
The params method is a method, returns a hash (which holds some details about parameters send to the app). Simplified it looks like this:
def fake_params
{ :controller => 'foo', :action => 'bar' }
end
You can call another method directly on the returned hash like this:
fake_params[:action] #=> 'bar'
params is a method defined in ActionController::Metal which returns the request.parameters object.
https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal.rb#L140
Taking the below method as an example:
-(void)myMethodName:(int)xCoordinate yCoordinate:(int)yCoordinate
When I write the method in my code [self etc...], Xcode does its auto complete which tells me what the second value is for but never the first (see pic).
Is there any way I can also include the 'description' for the first value of a method?
This is just a matter of how you name your method. It autocompletes the entire method name. If the method name is descriptive of its parameters, then you'll see it in the autocomplete.
Are you trying to get something like this?
-(void)myMethodNameWithXCoordinate:(int)xCoordinate yCoordinate:(int)yCoordinate
This is how the methods are usually defined in objective C
- (int)addX:(int)x toY:(int)y {
int sum = x + y;
return sum;
}
Like others have said rename your method this way and it will make things clearer
-(void)moveStuffFromXCoordinate:(int)xCoordinate toYCoordinate:(int)yCoordinate
Based on the Apple Documentation on coding guidelines for cocoa when naming methods with parameters the word before the argument should describe the argument.
Make the word before the argument describe the argument.
Right - (id)viewWithTag:(NSInteger)aTag;
The above is right because it describes the argument as a Tag where as the below doesn't describe the argument as anything.
Wrong - (id)taggedView:(int)aTag;
So in your case
Wrong -(void)myMethodName:(int)xCoordinate yCoordinate:(int)yCoordinate;
it should be
Right -(void)myMethodNameForXCoordinates:(int)xCoordinate andYCoordinate:(int)yCoordinate;
I was looking through the docs for instance_variable_set and saw that the sample code given does this:
obj.instance_variable_set(:#instnc_var, "value for the instance variable")
which then allows you to access the variable as #instnc_var in any of the class's instance methods.
I'm wondering why there needs to be a colon : before the #instnc_var. What does the colon do?
My first instinct is to tell you not to use instance_variable_set unless you really know what you are using it for. It's essentially a tool for metaprogramming or a hack to bypass visibility of the instance variable.
That is, if there is no setter for that variable, you can use instance_variable_set to set it anyway. It's far better if you control the code to just create a setter.
Try looking at accessors for the vast majority of your instance variable setting needs. They are an idiomatic way to have getters and setters for your instance variables "for free" without you having to write those functions.
If you really do need instance_variable_set, it allows the first argument to be a symbol which is the name of the instance variable to set. A colon is part of the Ruby language that is like a "symbol literal": when you type :foo, you've created a symbol with value foo, just like when you type "bar" directly into your code, you create a string literal with value "bar".
Since Squeak is purely Object Oriented I'm fairly certain that you should be able to pass functions as parameters to other functions, but when I was researching on this I couldn't find any information about this. Is my intuition correct? And if so, how is it done and how do I invoke them afterwards?
Longer answer.
To pass a piece of executable code to a method, use a block.
The method definition is
method: aBlock
aBlock value
and you execute it as follows
object method: [ Transcript show: 'hello' ].
if you want to pass a parameter to the piece of code, use a block with an argument.
The method definition is
method: aBlock
aBlock value: 'parameter'
and you execute it as follows
object method: [ :arg | Transcript show: arg ].
the same can be done with 2 or unlimited parameters, using the methods value:value: and valueWithArguments: of the block.
If you pass in a symbol, you can also use value: to execute it. A symbol is actually equivalent to a block of the form [ :arg | arg symbol ].
You're confusing two different things. The only real "functions" you pass around in Smalltalk are blocks, which you pass just by writing a block as an argument (like you do with every ifTrue:). If you want to send a message to an object but have the message be determined dynamically, you can pass the message name as a symbol (e.g. #value) and send it to some object (e.g. with perform:). You don't pass instance methods themselves. Either pass a selector symbol or pass a block that sends a message to call the method.