Inherited Resources and optional belongs_to: How to scope collection in parent resource, but not in nested resource? - inherited-resources

I have the following routes:
resources :boilerplates
resources :projects do
resources :boilerplates
end
The Boilerplate model looks like this:
class Boilerplate < ActiveRecord::Base
scope :originals, -> { where(prototype_id: nil) }
end
My controller looks like this:
class BoilerplatesController < InheritedResources::Base
load_and_authorize_resource
belongs_to :project, optional: true
end
When the URL /boilerplates is opened, I want to display all boilerplates with the originals scope.
When the URL /projects/123/boilerplates is opened, I want the originals scope not to be active.
How can this be achieved?

I just found a way to do this myself. In BoilerplatesController:
protected
def collection
if #project
super
else
super.originals
end
end

Related

What does the "self" keyword references in this Ruby case?

I would like some help understanding what does self refers to in this case. I understand that self refers to the class, module, etc that "owns" the code currently executing. In my example, my_each is an instance method for the Enumerable module. I'd like to know how does the self keyword works so that when I pass it to my example array it references it.
module Enumerable
def my_each
i = 0
while i < self.size
yield(self[i])
i += 1
end
self
end
end
[2,4,5].my_each { |i|
puts i
}
=> 2
=> 4
=> 5
What self refers to depends on the context. In your case, in an instance method, self refers to the object receiver of your instance method, so in your case the array [2, 4, 5].
But self can refer to other objects too. For example,
class Foo
puts self
end
prints Foo because in that context self refers to the class object. And that's why the two following definitions are the same thing
class Foo
def Foo.m
end
end
class Foo
def self.m
end
end
In Ruby it's all about self and every method is always executed against a particular self.
In your example instance method my_each self will refer to an instance which is using the method.
As you said self can also refer to a class, module..
It is a very powerfull ruby keyword since it can be used to create metaclasses.
If you are interested in understanding more I suggest you read chapter 5 in The Well Grounded Rubyist
self is a special variable that points to the object that "owns" the currently executing code. Ruby uses self everywhere:
For instance variables: #myvar
For method and constant lookup
When defining methods, classes and modules.
Inside of an instance method
In the code below, reflect is an instance method. It belongs to the object we created via Event.new. So self points to that object.
class Event
def reflect
self
end
end
g = Event.new
g.reflect == g # => true
Inside of a class method
For this example, reflect is a class method of Ghost. With class methods, the class itself "owns" the method. self points to the class.
class Event
def self.reflect
self
end
end
Event.reflect == Event # => true
It works the same with "class" methods inside of modules. For example:
module Event
def self.reflect
self
end
end
Event.reflect == Event # => true
Remember, classes and modules are treated as objects in Ruby. So this behavior isn't that different from the instance method behavior we saw in the first example.
Inside of a class or module definition
One feature of Ruby that makes it such a good fit for frameworks like Rails is that you can execute arbitrary code inside class and module definitions. When you put code inside of a class/module definition, it runs just like any other Ruby code. The only real difference is the value of self.
As you can see below, self points to the class or module that's in the process of being defined.
class Event
self == Event # => true
end
module Join
self == Join # => true
end
Inside mixin methods
Mixed-in methods behave just like "normal" instance or class methods when it comes to self. This makes sense. Otherwise the mixin wouldn't be able to interact with the class you mixed it into.
Instance methods
Even though the reflect method as defined in the module, its self is the instance of the class it was mixed into.
module Reflection
def reflect
self
end
end
class Event
include Reflection
end
g = Event.new
g.reflect == g # => true
Class methods
When we extend a class to mix in class methods, self behaves exactly like it does in normal class methods.
module Reflection
def reflect
self
end
end
class Event
extend Reflection
end
Event.reflect == Event # => true
Inside the metaclass
Chances are you've seen this popular shortcut for defining lots of class methods at once.
class Event
class << self
def method1
end
def method2
end
end
end
The class << foo syntax is actually pretty interesting. It lets you access an object's metaclass - which is also called the "singleton class" or "eigenclass." I plan on covering metaclasses more deeply in a future post. But for now, you just need to know that the metaclass is where Ruby stores methods that are unique to a specific object.
If you access self from inside the class << foo block, you get the metaclass.
class << "test"
puts self.inspect
end
# => #<Class:#<String:0x007f8de283bd88>
Outside of any class
If you're running code outside of any class, Ruby still provides self. It points to "main", which is an instance of Object:
puts self.inspect # => main

Simple PUT not modifying the model

The route is shown below and I can confirm the request is hitting the route, however, the model parameter is the currently saved model, when I'd expect it to be the model with updated properties.
#Page.method(request_fields=('id',),
path='page/{id}', http_method='PUT', name='page.udpate')
def PageUpdate(self, model):
if not model.from_datastore:
raise endpoints.NotFoundException('MyModel not found.')
model.put()
return model
The request_fields field specifies what comes in the request, so you'll want to include a lot more. The _message_fields_schema property (discussed in simple_get example) is best to use.
class Page(EndpointsModel):
_message_fields_schema = ('id', ... other properties)
and then just let the default be used:
#Page.method(path='page/{id}', http_method='PUT', name='page.update')
def PageUpdate(self, page):
if not page.from_datastore:
raise endpoints.NotFoundException('Page not found.')
page.put()
return page
NOTE: I also changed the spelling of 'page.udpate' and the text in the error message.

Only persist document if it has embedded documents with Mongoid?

I have a 2 level nested form (much like this) with the following classes. The problem I have is that when I don't add any intervals (the deepest embedded document) I don't want the second deepest document to be persisted either. In the owner I added a reject statement to check if there's any intervals being passed down, this works.
However, when the schedule originally had intervals but they where destroyed in the form (by passing _destroy: true) the schedule also needs to be destroyed. What would be the best way to do this? I would like to avoid a callback on the schedule that destroys the document after it is persisted.
class Owner
include Mongoid::Document
embeds_many :schedules
attr_accessible :schedules_attributes
accepts_nested_attributes_for :schedules, allow_destroy: true, reject_if: :no_intervals?
def no_intervals?(attributes)
attributes['intervals_attributes'].nil?
end
end
class Schedule
include Mongoid::Document
embeds_many :intervals
embedded_in :owner
attr_accessible :days, :intervals_attributes
accepts_nested_attributes_for :intervals,
allow_destroy: true,
reject_if: :all_blank
end
class Interval
include Mongoid::Document
embedded_in :schedule
end
Update: Maybe this is best done in the form itself? If all intervals is marked with _destroy: true, also mark the schedule with _destroy: true. But Ideally the solution would be client agnostic.
How about adding this to the Owner class:
before_update do
schedules.each |schedule|
schedule.destroy if schedule.intervals.empty?
end
end

what's the best way to set computed property of app engine model in appengine after fetch from datastore?

I have my own User model in app engine, which should have a property of his gravatar url. However, since this can be very quickly computed using his email address, it doesn't make sense to store it. Is there a way to just automatically initialize this property when it s loaded from the datastore?
I could just add a method called get_avatar_url(), but you can't call an object's methods (as far as I know), from within a jinja2 template, and I don't want to post all these values individually to the template.
You can define a method, as you describe, or you can define a property, like this:
class MyModel(db.Model):
email = db.StringProperty(required=True)
#property
def avatar_url(self):
return "http://gravatar.com/avatar/%s" % (hashlib.md5(self.email).hexdigest(),)
You can then refer to this as instance.avatar_url (or in a template, {{instance.avatar_url}}).
Either will work fine in a jinja2 template, but using a property is slightly neater if you need to request it elsewhere. Since only datastore property instances result in storing data in the datastore, your property will not be stored in the datastore.
It's ok to call them from a template. All you need to do is to declare this model's method as classmethod or property
Here's a quick example:
# sample model
class UserProfile(db.Model):
...
email = db.EmailProperty()
...
#property
def id(self):
return self.key().id()
#classmethod
def get_avatar_url(self):
# whatever you need to call gravatar url
return self.email
# sample view
def show_user(user_id):
user = User.all().filter("user = ", user_id).get()
flowers = Flower.all().filter("user = ", user)
return render_template('index.html', u=user, f=flowers)
# sample template
<div class="user">user id: {{ u.id }}, and gravatar: {{ u.get_gravatar_url() }}<div>
HTH.
You most certainly can call methods within a template. That is the best way to do it.

MVVM Light, Windows Phone, View & ViewModel navigation between pages

I have a page where you basically select a set of options (configuration), and then you go to a next page, where you do some stuff
Using the MVVM Light toolkit, I have a viewmodel that binds to the view of the first page. when the user hits a button, it redirects to another view, which would be the 2nd page
i.e.:
Page2Command = new DelegateCommand((obj) =>
Messenger.Default.Send<Uri>(new Uri("/DoStuffView.xaml", UriKind.Relative),
Common.CommonResources.GoToDoStuffRequest)) });
The problem is, the viewmodel for the 2nd view (the way that I see it) has a couple of parameters in the constructor, which are basically the dependencies on the configuration that was set on the first page.
i.e. :
public DoStuffViewModel(ICollection<Note> availableNotes, SoundMappers soundType)
{
}
The problem lies here.. How can I instantiate the viewmodel with this data that was dynamically selected by the user on the 1st page?.
I can't use the ViewModelLocator pattern that MVVM light provides, since those viewmodels don't have any dependencies, they are just by themselves (or they can retrieve data from a db, file or whatever, but they don't have any dynamic input data). I could do it through the view's constructor, instantiate there the viewmodel, and assign to the view's DataSource the newly created viewmodel, but I think that's not very nice to do.
suggestions?
As I see you send messsage using Messenger class so you are familiar with messaging in MVVM light. You have to define your own message type that should accept your parameters from page 1:
public class Page2ViewModelCreateMessage : MessageBase
{
public ICollection<Note> AvailableNotes{get;set;}
public SoundMappers SoundType{get;set;}
public Page2ViewModelCreateMessage ()
{
}
public Page2ViewModelCreateMessage(ICollection<Note> availableNotes, SoundMappers soundType)
{
this.AvailableNotes = availableNotes;
this.SoundType = soundType;
}
}
You have to send an Page2ViewModelCreateMessage instance with you parameters and send it on navigating:
var message = new Page2ViewModelCreateMessage(myAvailableNotes, mySoundType)
Messenger.Default.Send(message);
On Page2 you have to register for recieving message of type Page2ViewModelCreateMessage:
Messenger.Default.Register<Page2ViewModelCreateMessage>(this, OnPage2ViewModelCreateMessage);
..
public void OnPage2ViewModelCreateMessage(Page2ViewModelCreateMessage message)
{
var page2ViewModel = new Page2ViewModel(messsage.AvailableNotes, message.SoundType);
}
As you can see I have replace your DoStuffViewModel with Page2ViewModel to be more clear.
I hope this will help you.
NOTE:I dont guarantee that code will work as its written in notepad.
The way I do this is to have a central controller class that the ViewModels all know about, via an interface. I then set state into this before having the phone perform the navigation for me. Each ViewModel then interrogates this central class for the state it needs.
There are a number of benefits to this for me:
It allows me to have non-static ViewModels.
I can use Ninject to inject the concrete implementation of the controller class and have it scoped as a singleton.
Most importantly, when tombstoning, I only need to grab the current ViewModel and the controller class.
I ran into a problem with messaging where my ViewModel was the registered listener, because I was View First and not ViewModel First, I was forced to use static ViewModel references. Otherwise the ViewModel wasn't created in time to receive the message.
I use the controller class in conjunction with messages (it is basically the recipient of all messages around the UI) so in future if I refactor, I don't need to change much, just the recipients of the messages.
Come to think of it, the controller class is also my navigation sink - as I have some custom navigation code that skips back paging on certain pages etc.
Here's an example of my current set up:
public interface IController
{
Foo SelectedFoo { get; }
}
public class ViewModel
{
private IController _controller;
public ViewModel(IController controller)
{
_controller = controller;
}
private void LoadData()
{
// Using selected foo, we load the bars.
var bars = LoadBars(_controller.SelectedFoo);
}
}
You could use PhoneApplicationService dictionary to save data you need when navigation from first event, and parse it when you navigateTo second page. you can also use that data in your ViewModels.
Something like this:
PhoneApplicationService.Current.State["DatatFromFirstPage"] = data;
and when navigating to second page:
if (PhoneApplicationService.Current.State.ContainsKey("DatatFromFirstPage"))
{
var dataUsedOnSeconPage= PhoneApplicationService.Current.State["DatatFromFirstPage"];
}
you can use this data globally in entire app

Resources