overriding a value to true and setting the rest to false in rails
this is a really stupid question but I have a deadline and I'm very nervous and I've tried everything. In fact it even worked for a second but I must have broken something.
I have a default featured item that I want to be overridden any time I try to feature another item. I had it give an error before but I don't want it to error, I just want it to set everything to false and this app to true.
I've tried everything, before save, after save/update named scopes, mapping each one to false and then saving, checking for whether the feature has changed...I think I have all the right parts but I can't put them together. Please please help :(
Maybe there's even a quick validation for this, I'm not sure
I can't elaborate with code because I've tried a million different things.
There is a boolean setting on an item that is called is_featured.
When you create the item, you can set it to be featured or not.
In the database, if other items are featured, these should be zeroed out, and the item that was just updated or created to be featured should be true.
I have tried this in the model with before/after/save/update and also the controler on create and update
Fine I will add some of my stupid code which Id on't know why doesn't work
In the controller:
if params[:app][:is_on_front_page] == true
App.all.map{|m|( m != @app ) ? m.is_on_front_page = true : m.is_on_front_page = false}
end
or
named_scope :is_on_front_page, :conditions => { :is_on_front_page => true }
after_update do
if self.is_on_front_page.changed? and App.is_on_front_page.count >= 1
开发者_运维问答App.all.map{|m| m.is_on_front_page = false;m.save}
end
is_on_front_page = true
save!
end
but it won't let me save or gets into an infinite loop or yells at me because of the named scope
In a transaction just set all to false and then update the record you want to true (featured). This is similar to how sometimes its easier to delete records then find them and update them. That is, its easier to just do something like:
tranasction do SomeModel.delete_all items.each { |i| SomeModel.create(i) } end
Which can be easier then looping over SomeModel doing a find() and then updating certain properties.
In your case you just want to mark ALL records a NOT-featured and then just update the one you want as featured, rather than toggling records by hand.
Try something like this:
after_create :set_as_featured
def set_as_featured
self.class.transaction do
self.connection.execute("UPDATE foo SET featured=0")
self.update_attribute(:featured, true)
end
end
if params[:id] # or however you're setting the overridden featured item
@feature = Feature.find(params[:id])
else
@feature = Feature.default # make a self.default method that returns the default
end
Is that what you need? To pick a featured item?
I'm not sure exactly what you need. Validations would be for saving something, so I'm not sure what would be 'featured' there. A comment for clarification would help.
A before_create or before_update hook would be where you would set defaults if something wasn't provided, but beyond that I'd need a little guidance as to your specifics.
Okay, I'm adding a separate answer because I think I get what you're saying.
You have a list of Items and you want one of them featured. Someone can pick one of those to be featured, but if not, there's a fallback item that gets featured by default.
If you have Store has_many :items, you could put an attribute for "featured_item_id" on the store and store the featured_id. If you need to set the default, add "default_item_id" and put the default one in there.
Add relationships for them on the Store:
belongs_to :featured_item, :class => Item, :foreign_key => 'featured_item_id'
belongs_to :default_item, :class => Item, :foreign_key => 'default_item_id'
Then, make a method that test and returns the correct one:
def featured
if self.featured_item_id
self.featured_item
else
self.default_item
end
end
If you set an item as the featured item, you get that one. If not, you get the default. You'd probably also want:
validates_presence_of :default_item_id
... to ensure there's always a default so you don't get a nil item problem.
精彩评论