I'm quite new in RoR and right now I'm facing a problem. I'm implementing an Attendance system and I have Event resource in the application. What I want to do is the possibility to call event.color (on an instance of Event) and get back classic css color string (like #2EAC6A). I don't want to create new column or table in the database if it's possible. That means that it would be best if this color variable is handled by ruby itself.
I want to set the color of event after it's creation dependant on it's type. What I was thinking of is something like this to set the color:
class Event < ActiveRecord::Base
after_create :set_color
...
def set_color
case self.type
when type1
#Here I want to set the color for event of type1
when type2
#Here I want to set the color for event of type2
when ....
.
.
end
end
This is just for setting the color (and still I'm not sure it's functional...) but I have no idea how to keep color variable for each event without the database and how to make Event.color method call possible.
I'm using RoR v 3.2.14
Please, I would be glad for any help.
Thank you and have a nice day!
J.S.
If your colors never change - or every type1 always has the same color as another type1 you could use different CONSTANTS in your model or a bitmask.
example for using constants:
class Event < ActiveRecord::Base
COLOR_TYPE1 = "#2EAC6A"
COLOR_TYPE2 = "#000000"
COLOR_TYPE3 = "#ffffff"
def color
case self.type
when type1
COLOR_TYPE1
when type2
COLOR_TYPE2
when type3
COLOR_TYPE3
else
raise "for this type is no color defined!"
end
end
end
You won´t need to set the color - because you do not have an attribute color. Simple use a normal method which returns the correct color for an instance, dependent on the type of the instance.
Another option without constants: (this approach is better than the above one, in my opinion :-) )
class Event < ActiveRecord::Base
def color
case self.type
when type1
"#2EAC6A"
when type2
"#000000"
when type3
"#ffffff"
else
raise "for this type is no color defined!"
end
end
end
If you have different classes for each instance, you must not use the constants, you just can define the colors directly:
class Type1 < Event
def color
"#2EAC6A"
end
end
def Type2 < Event
def color
"#000000"
end
end
def Type3 < Event
def color
"#ffffff"
end
end
Different classes have the advantage, that you can handle all your stuff which depends on the type directly in a subclass of your parent class "Event". Do you get the idea?
Related
I had an idea to use custom attributes on the properties in a class for databinding purposes in a winforms interface. For example, setting and changing the backcolor, forecolor, and tooltip on a textbox with invalid data. I find that I can bind up the control properties of txtTest for backcolor, etc., to a custom attribute such as BackColorAttr decorating a property in the class such as Name, with no problem. The property value itself is bound to the Text of the textbox, two-way binding of that works just fine, and the initial backcolor, forecolor, etc., are set from the initial values of the custom attributes just the way I had hoped. I'm doing all this through a BindingHelper class that reduces all the coding to a couple of generic methods.
Where I'm stumped is manipulating the values of the custom attributes at a later time. Changing the backcolor to red, for example. Nothing I've tried seems to work. Has anybody tried something like this, or have some guidance as to how I might proceed?
I dont quite follow the first part or what binding has to do with colors or Attributes, but thats not how Attributes work. They are not Property wrappers and Properties, Methods and Types have no idea of the Attributes associated with them (and vice-versa). They are meta data compiled into the assembly. As such, you cant change the value in any meaningful way.
Test class and test Attribute:
Public Class BarState
Inherits Attribute
Public Property State As String
Public Sub New(t As String)
State = t
End Sub
End Class
Public Class Foo
<BarState("red")>
Public Property Name As String
End Class
Since State is a property, test if we can set it:
Dim f As New Foo
' get props for the Type
Dim pi As PropertyInfo = f.GetType.GetProperty("Name")
Dim attr = pi.GetCustomAttributes(GetType(BarState), False)
If attr.Length > 0 Then
' get prop info for the State property on the Attr Type
Dim pa As PropertyInfo = attr(0).GetType.GetProperty("State")
' change it
CType(attr(0), BarState).State = "GREEN"
' or
'pa.SetValue(attr(0), "GREEN", Nothing)
' print it (prints "GREEN" but it does not persist)
Console.WriteLine(CType(attr(0), BarState).State)
End If
'get the attr again as you might do next time thru
attr = pi.GetCustomAttributes(GetType(BarState), False)
' print the value (Print "red")
Console.WriteLine(CType(attr(0), BarState).State)
The first print will be "GREEN" but that is only for this instance - it does not persist. The next time you get it, it reverts to "red". Since an Attribute is a Type, we can try to Reflection to change the value using pa.SetValue(attr(0), "GREEN", Nothing) which is commented out. It still wont persist because "red" is compiled into the assembly which is what your starting point will always be.
It might seem like you could keep a Dictionary or collection of the attribute instances for all the properties on all the types. That could work except, they all look alike, so you would have to create a hash to track which Attribute instance goes with what Property on what Type.
And you'd have to keep that collection in sync with the underlying instance objects. The Attribute instance wont know the instance it came from is gone and so the state setting should revert, so your Attribute manager would need to handle that.
You might look into "weavers" which use attributes to tag things (like a value range) then rewrite the assembly to weave in range checks for the tagged properties. Sort of sounds like what you are after I dont know what else they might do along the lines of what you describe.
I have been searching for quite a while today for an answer to my question but without success. I don't even know if its possible but I'll try my luck here.
Lets say i have this function somewhere in a class:
Public Sub sub1(i as Integer, uc as UserControl)
...
End Sub
And somewhwere else, in an other method i have this call:
sub1(46, new UserControl())
The problem is that i want to pass a UserControl with, lets say, a background colored in blue but it must be defined inside the method call. In other words, i want to pass an object with some properties that are modifed outside the constructor and everything must be done inside the method call. I'm thinking of something like that:
sub1(9387, {Dim uc as new UserControl()
uc.BackColor = Color.Blue
return uc} )
I understand that i could define a UserControl and modify it before the method call but my real situation is way more complex than that. Anyway I just want to know if it is currently possible and if yes show me some examples. In my research i found that i could do some delegate or use some "lambda" expression but I didn't find a solution that perfectly solve my question. And again, I must not write a single character of code outside the method call.
Thanks in advance!
Like this:
sub1(9387, New UserControl With {.BackColor = Color.Blue})
Immediately-invoked functions are possible in VB.NET:
Dim result As Integer = (Function() As Integer
Return 1
End Function)()
Or in your example:
sub1(9387, (Function()
Dim uc As New UserControl()
uc.BackColor = Color.Blue
Return uc
End Function)())
If I'm understanding your question, you can simply use property initializers:
sub1(9387, New UserControl With { .BackColor = Color.Blue })
I'm using acts-as-taggable-on 2.0.6 for tagging in a Rails 3.0.9 app. I've successfully added db-backed attributes to the Tag model, for example each tag has an RSS feed so I can call #post.tags.first.feed_url to grab the feedburner URL from my database.
But while I can add attributes to the Tag model, it seems I can't add instance methods. I created the instance method:
class Tag < ActiveRecord::Base
...
def subscribable?
!feed_url.blank?
end
...
end
But when I call #post.tags.first.subscribable? I get the error:
NoMethodError: undefined method `subscribable?' for #<ActsAsTaggableOn::Tag:0x00000100d32290>
Is there a way to tell ActsAsTaggableOn::Tag objects to inherit model methods from the Tag model?
You need to add this /config/initializers/tag_monkey_patch.rb
class ActsAsTaggableOn::Tag
def subscribable?
!feed_url.blank?
end
end
I'm wondering the exact same thing. As far as i've tried, it isn't working for me..
class Tag < ActsAsTaggableOn::Tag
def total_count
...
end
end
When I call it in a dirty chained form example, like so:
my_model.my_instance.tag_counts_on(:tags).first.total_count
I get a
undefined method `total_count' for #<ActsAsTaggableOn::Tag id: 1, name: "first">
From what I understand, you shouldn't be declaring a new "Tag" model like this, but should should be overriding the class like this:
class ActsAsTaggableOn::Tag
def total_count
...
end
end
I'm trying to take advantage of the ruby methods kind_of? and is_a?. As I understand it they are synonyms of one another.
I have an object of class Child. A call to Child.ancestors gives back an array list this [Child, #<Module>, Parent, ...]. However a call to Child.new.is_a?(Parent) or Child.new.kind_of?(Parent) returns false.
Calling Child.ancestors[2].new.is_a?(Parent) also returns false. I can't seem to figure out why this would be considering calling Parent.new.is_a?(Parent) returns true as it clearly should.
These classes all eventually descend from ActiveResource::Base if that has anything to do with it.
class Parent < ActiveRecord::Base
include MyModule
def self.my_method(obj)
if obj.is_a?(Parent)
puts 'Hello'
end
end
end
class Child < Parent
def my_method
self.class.my_method(self)
end
end
a = Child.new
a.my_method
class Parent
def self.my_method(obj)
if obj.is_a?(Parent)
puts 'IS A PARENT'
else
puts 'IS NOT A PARENT'
end
end
end
class Child < Parent
def my_method
self.class.my_method(self)
end
end
a = Child.new
a.my_method
Note I dropped the AR and included module, but the above prints out "IS A PARENT" for me. Ruby 1.8.7 on osx.
I have an abstract user control(baseModule) that has a property that I plan on using a bitwise comparison on to determine what export types are supported by that module. In the designer of a module derived from baseModule, I am presented with a combobox with the ability to just select a single value (Html, Xml, etc.) I would like to be presented with a drop-down checked listbox so I could select which values I want.
How can I accomplish this inside of VS2008? I've seen other properties support this. Please refer to the code below for a better explanation of what I mean in the poorly asked question above.
Public Class ExportTypes
Public Enum ExportType
Html = 1
Xml = 2
Xls = 4
Txt = 8
Pdf = 16
Rtf = 32
End Enum
End Class
Public Class baseModule
Private _SupportedExportTypes As ExportType = 0
Public Property SupportedExportTypes() As ExportType
Get
Return _SupportedExportTypes
End Get
Set(ByVal Value As ExportType)
_SupportedExportTypes = Value
End Set
End Property
End Class
You will probably want to implement a UITypeEditor. Check this walkthrough, and exchange the created control in the custom type editor (in the EditValue method override) to a CheckedListBox, and handle assigning and retrieving the enum values to and from the listbox. Then decorate the property in your user control with an EditorAttribute point out your type editor, and you should be good to go.