Now, I am facing the problem of creating an instance method.
Item has multiple images in active storage.
I created a class method something like below.
def self.get_url(item)
item.images.map do |image|
Rails.application.routes.url_helpers.url_for(image)
end
end
this class method worked completely fine.
But I want to change this to instance method so that I use this other place without an argument item.
So I want it to be something like this.
def get_url
item.images.map do |image|
Rails.application.routes.url_helpers.url_for(image)
end
end
But I can't do this, because nothing like item is defined.
And I want to use it like this.
item.get_url
If you could help me I would really appreciate it.
Thank you.
In def self.get_url(item), I'll assume item is an instance of the class, so if you want to create an instance method, simply drop the item part from item.images:
def get_url
images.map do |image|
Rails.application.routes.url_helpers.url_for(image)
end
end
Related
I would like to do something like:
class TestController < InheritedResources::Base
def test_method
self.var1 + self.var2
end
private
def test_params
params.require(:test).permit(:var1, :var2)
end
end
Where in the view I could call from the built in controller index:
test.test_method
I've tried adding a create method to the controller as follows:
def create
Test.create!(require(:test).permit(:var1, :var2, :test_method))
end
I've also tried updating the params directly:
private
def test_params
params.require(:test).permit(:var1, :var2, :test_method)
end
I've also tried making a helper method, but I knew that was doomed to fail because it wouldn't have access to var1 and var2.
I guess I just don't understand two things: one how to make my var1 and var2 white-listed so I can use them, and more importantly how to add a method to my model using strong parameters, because attr_accessible doesn't work in my models anymore.
EDIT:
Let me rephrase a little, maybe it will help. I can get access to individual Test objects in my view with a simple call to tests.each |test| in the view. I just want to make methods that act on my already defined active record variables for that object, hence var1 and var2. The problem is when I define a new method in my controller it is private to the object and I won't have access to it with a call from an instance of the object. Better yet, I would like to just be able to define a new variable, local to the object, that is created after it has propagated its other fields from the db.
EDIT2: I'm aware I'm probably missing the design pattern here. It can be hard to describe that I want X, when really I need Z. Thanks for the patience.
Thanks for the help.
There's no reason for white-listing parameters that you'll directly use.
White-listing with strong parameters is useful only when you call function like ActiveRecord#update that simply take every key from the dictionary, so you can control with key you want to allow and which not.
In this case, just do:
class TestController < InheritedResources::Base
def test_method
#result = params[:var1] + params[:var2]
end
end
And in your view, just print the #result variable wherever you want
<%= #result %>
This is the Rails way. You can of course call the variable as you want.
Helper methods are useful only for more complex cases.
I'd like to return a random webpage that I can display as a link in a view but I can't get the method to work properly:
Error:
NoMethodError: undefined method `randomize_webpages' for #<ActiveRecord::Relation::ActiveRecord_Relation_Webpage:0x00000101d84e68>
Webpage Model
def randomize_webpages
shuffle.first
end
WebpagesController
def index
#webpages = Webpage.all
end
CSV seeder for Webpage
link
http://www.buzzfeed.com
http://www.reddit.com
http://boston.com
http://phys.org
http://www.popsci.com
http://www.technologyreview.com
http://techcrunch.com
View Index.html.erb
<%= link_to 'Take Me Anywhere But Here', #random_page %>
You need to define the method as a class method of the model
class Webpage
def self.randomize_webpages
shuffle.first
end
end
instead of
class Webpage
def randomize_webpages
shuffle.first
end
end
Please note that the method is very inefficient. You are loading all the records and then selecting one. There are more efficient ways.
One possible improvement is to select only the ID, then query for that ID. Another alternative is to delegate to the underlying driver, assuming it supports the query.
Aren't you calling randomize_webpages on #webpages, are you? This is a collection, so you have to do something like #webpages.first.randomize_webpages or iterate over them (you didn't include relevant code so I can't tell what you want to do) to get this working.
It needs to be a class method, then you could use sample:
def self.randomize_webpages
all.sample
end
You could add a class method to your model
class WebPage < ActiveRecord::Base
def self.random
order('RAND()').first
end
....
end
Then you can call it from as WebPage.random in your controller, save to an instance variable, and use that instance variable in your view.
Please: note that 'RAND()' is MySQL specific. If you do not use MySql, search for the correct syntax (if any)
I have created a module with a method
module Adding_preferences
def desired_preferences
#preference = %w(motabilitySpecialist newCars bodyshop filter8 filter7).each do |selection|
#browser.label(:for, selection ).click
end
end
end
I have included this module into a class:
class Pages
include Adding_preferences
attr_accessor :browser, :preference
def initialize
#browser = Watir::Browser.new :ff
end
end
World do
Pages.new
end
I am calling this method in a Cucumber scenario
When /^I select a desired preference$/ do
desired_preferences
end
But at runtime I receive an error, "NameError: undefined local variable or method `desired_preferences'". Where am i going wrong?
When you include a module to a class you can use this method in the instance methods of this class. You cant call the included method in a View that displays the data from the model that includes the module. For me it looks like you just dont use the desired_preferences method in an instance method.
Please show us the peace of code you try to call the method if this still doesnt help you out.
// The naming of the Module is not conventional. You should call it module AddingPreferences isntead ofmodule Adding_preferences and the file should be named adding_preferences.rb then try to include AddingPreferences
It's a good idea for you to spend some time getting more familiar with Ruby's Class/Module/Object/Method inheritance model, because the way you're structuring your code there is a little bit messy.
However, a simple thing to try (and I'm not going to guarantee that it will work flawlessly) is the following modifications:
Assign your instantiated Pages class to a class instance variable:
World do
#page = Pages.new
end
...and then use that instance variable in your step definition...
When /^I select a desired preference$/ do
#page.desired_preferences
end
I hope that helps!
Ive made a nice editor in jQuery and i want to add it as a form helper method.
how would i go about making a new form helper method?
ideally id like to be able to call:
f.nice_editor :field
Part of the question is: where do you put the nice_editor code? I don't think it is a good idea to directly edit class ActionView::Helpers::FormBuilder in your installation. Instead, put your code in one of the files in app/helpers. There are several ways to add extension methods to FormBuilder.
For instance, suppose you have a helper file items_helper.rb:
module ItemsHelper
# this is one way to define new instance methods
ActionView::Helpers::FormBuilder.class_eval do
def nice_editor(conf,*opts)
...
end
end
end
Also, see this good discussion, which shows how to use self.included() to extend FormBuilder.
The object yielded to form_for is an instance of ActionView::Helpers::FormBuilder. So all you have to do is to add instance methods there.
class ActionView::Helpers::FormBuilder
def custom_field(...)
...
end
end
after some research i found that this works:
class ActionView::Helpers::FormBuilder
def nice_editor(conf)
#stuff to draw the editor
end
end
"conf" would have all the symbol options passed to it from the view. it works fine with f.
My rails model has code that is attempting to define_method(method_name) inside the model.
I keep getting:
NoMethodError: undefined method `define_method'
What am I doing wrong? Am I doing this in the wrong place. I need this method attached to this model. Where else can I define this method?
EDIT:
For those asking to see the code:
for field in rdev_fields
next if self.attributes.include?(field)
count = count + 1
rdev_hash[field.to_sym] = self.attributes["attribute#{count}"]
if !self.respond_to?(field) then
define_method("#{field}") do
self.send("attribute#{count}".to_sym)
end
end
end
There's nothing magical or about a rails model, it's just a normal class with a bunch of pre-existing methods,
So, the question is "can I define_method in a class"?
Part 1: Yes you can.
The important distinction is than you can define method in a class not in an instance method
For example:
class Cow
define_method "speak" do
"MOOOO"
end
end
Cow.new.speak
=> "MOOOO"
This should work fine. Note you're defining it on the class Cow, so any other Cows that you already have will automatically get that method added.
Part 2: What do you do if you want to define a method from within an instance method?
You can't define methods from an instance method, so you have to grab the class, and use that to define the method. Like this:
class Cow
def add_speak
self.class.send(:define_method, :speak) do
"MOOOO added"
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c48530>
Cow.new.add_speak
Cow.new.speak
=> "MOOOO added"
Problem solved. Astute readers will note that in this example I'm using send(:define_method) - this is needed because define_method is private, and private methods are only accessible to the thing they're in. In this case, define_method is in the class, we are in the instance, so we can't directly access it.
As above though, we're adding the method directly to the class, so all other Cows which already exist will automatically also get the speak method added.
Part 3: What do you do if you want to define a method for only 1 object, not all objects of that class?
Example:
class Cow
def add_speak_just_me
class << self
define_method "speak" do
"MOOOO added for just me"
end
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c72b78>
c = Cow.new
c.add_speak_just_me
c.speak
=> "MOOOO added for just me" # it works, hooray
Cow.new.speak # this new cow doesn't have the method, it hasn't been automatically added
NoMethodError: undefined method `speak' for #<Cow:0xb7c65b1c>
How does this work? Down the rabbithole you go!
Read this: http://dannytatom.me/metaid/ and good luck. It helps when you realise that 'adding a method' to an instance isn't actually adding it to the instance at all :-)
If you came here searching for how to dynamically define a CLASS method, because define_method wasn't working (because it defines INSTANCE methods), here is your answer:
Use define_singleton_method :)
was able to cobble this together. Very little understanding of what's actually going on though.
My instance method foo is opening the class and defining bar on it so that I can then call that on my instance. More experienced folks will let us know if this is opening a can of worms at the same time.
Would be useful to know your specific use for this though.
class User < ActiveRecord::Base
def foo
(class << self; self; end).class_eval do
define_method(:bar) {puts "bar"}
end
end
end
u = User.first
u.foo
u.bar #=> "bar"
The answer to your question is "yes, you can". As for why it's not working for you - it's impossible to say for sure why, if you don't provide some context for the code.