加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – iOS核心数据:为Rails多态关联设置关系的方法

发布时间:2020-12-17 02:10:43 所属栏目:百科 来源:网络整理
导读:我有一个iOS应用程序,其核心数据模型模仿我的Rails后端数据模型.在我的Rails后端模型中,我使用了多个实体的多态关联.我的Rails模型看起来像这样: Airport ActiveRecord::Basehas_many :reviews,:as = :reviewableRestaurant ActiveRecord::Basehas_many :re
我有一个iOS应用程序,其核心数据模型模仿我的Rails后端数据模型.在我的Rails后端模型中,我使用了多个实体的多态关联.我的Rails模型看起来像这样:

Airport < ActiveRecord::Base
has_many :reviews,:as => :reviewable

Restaurant < ActiveRecord::Base
has_many :reviews,:as => :reviewable

Review < ActiveRecord::Base
belongs_to :reviewable,:polymorphic => :true

在我的核心数据模型中,我有三个独立的实体,MyAirport,MyRestaurant和MyReview,具有如下所示的相关属性:

MyAirport
@property (nonatomic,retain) NSSet* reviews; //inverse is airport

MyRestaurant
@property (nonatomic,retain) NSSet* reviews; //inverse is restaurant

MyReview
@property (nonatomic,retain) NSNumber* reviewablId;
@property (nonatomic,retain) NSString* reviewableType;
@property (nonatomic,retain) MyAirport* airport; //inverse is reviews
@property (nonatomic,retain) MyRestaurant* restaurant; //inverse is reviews

我的问题与Core Data中的MyReview类有关.根据reviewableId和reviewableType中的值设置正确的核心数据关系(例如机场或餐厅)的最佳方法是什么?

我尝试过以下内容,但出于某种原因,所有人都显得有点不洁净.一般来说,在设置正确的关联之前,我需要确保我有可用的reviewableId和reviewableType,这似乎是与感知清洁度相关的主要问题.在从JSON中保护这些模型对象时,我并没有真正控制在新的MyReview对象上填充reviewableId和reviewableType的顺序.

1)在reviewableId和reviewableType中的一个或两个上的自定义setter – 我最终在每个setter方法中使用逻辑来检查其他属性的值,以确保在我可以在MyReview模型对象上设置机场或餐馆关系之前填充它.一般来说,这是有效的,但它感觉不对,同时在每个setter中也有一些丑陋的重复代码.

- (void)setReviewableId:(NSNumber*)reviewableId {
    [self willChangeValueForKey:@"reviewableId"];
    [self setPrimitiveReviewableId:reviewableId];
    [self didChangeValueForKey:@"reviewableId"];

    if (reviewableId && [reviewableId intValue] != 0 && self.reviewableType) {
        if (self.airport == nil && [self.reviewableType isEqualToString:@"Airport"]) {

            MyAirport myAirport = <... lookup MyAirport by airportId = reviewableId ...>
            if (myAirport) {
                self.airport = myAirport;
            }

        } else if (self.restaurant == nil && [self.reviewableType isEqualToString:@"Restaurant"]) {

            MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = reviewableId ...>
            if (myRestaurant) {
                self.restaurant = myRestaurant;
            }
        }
    }
}

- (void)setReviewableType:(NSString*)reviewableType {
    [self willChangeValueForKey:@"reviewableType"];
    [self setPrimitiveReviewableType:reviewableType];
    [self didChangeValueForKey:@"reviewableType"];

    if (self.reviewableId && [self.reviewableId intValue] != 0 && reviewableType) {
        if (self.airport == nil && [reviewableType isEqualToString:@"Airport"]) {

            MyAirport myAirport = <... lookup MyAirport by airportId = self.reviewableId ...>
            if (myAirport) {
                self.airport = myAirport;
            }

        } else if (self.restaurant == nil && [reviewableType isEqualToString:@"Restaurant"]) {

            MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = self.reviewableId ...>
            if (myRestaurant) {
                self.restaurant = myRestaurant;
            }
        }
    }
}

2)关于reviewableId和reviewableType的KVO – 在awakeFromInsert和awakeFromFetch中,我通过KVO将模型对象注册到观察者自己的reviewableId和reviewableType属性.这个对象观察自己感觉真的很难看,但至少我有一个处理填充关联的方法,这似乎比#1有点改进.请注意,我最终在这里使用removeObserver:forKeyPath:在dealloc方法中遇到了一些崩溃(例如崩溃表明我已经删除了一个不存在的观察者?),所以这远远不是经验证的代码.

- (void)awakeFromFetch {
    [super awakeFromFetch];
    [self addObserver:self forKeyPath:@"reviewableId" options:0 context:nil];
    [self addObserver:self forKeyPath:@"reviewableType" options:0 context:nil];
}

- (void)awakeFromInsert {
    [super awakeFromInsert];
    [self addObserver:self forKeyPath:@"reviewableId" options:0 context:nil];
    [self addObserver:self forKeyPath:@"reviewableType" options:0 context:nil];
}

- (void)dealloc {
    [self removeObserver:self forKeyPath:@"reviewableId"];
    [self removeObserver:self forKeyPath:@"reviewableType"];
    [super dealloc];
}

- (void)updatePolymorphicAssociations {
    if (self.reviewableId && [self.reviewableId intValue] != 0 && self.reviewableType) {
        if (self.airport == nil && [self.reviewableType isEqualToString:@"Airport"]) {

            MyAirport myAirport = <... lookup MyAirport by airportId = self.reviewableId ...>
            if (myAirport) {
                self.airport = myAirport;
            }

        } else if (self.restaurant == nil && [self.reviewableType isEqualToString:@"Restaurant"]) {

            MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = self.reviewableId ...>
            if (myRestaurant) {
                self.restaurant = myRestaurant;
            }
        }
    }
}

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
    [self updatePolymorphicAssociations];
}

3)使用上面的updatePolymorphicAssociations方法覆盖willSave.这似乎有效,但它推迟了对关联的所有更改,直到我们去保存对象,这通常不是我们对reviewableId和reviewableType进行初始更改时.这里似乎也存在一些限制,涉及通过后台线程插入一堆新的MyReview对象,可能与willSave相关,实际上导致我们刚刚保存的对象的更改,从而再次触发willSave.即使在updatePolymorphicAssociations中进行nil检查,我仍然可以使用这种方法使应用程序崩溃.

- (void)updatePolymorphicAssociations {
    if (self.reviewableId && [self.reviewableId intValue] != 0 && self.reviewableType) {
        if (self.airport == nil && [self.reviewableType isEqualToString:@"Airport"]) {

            MyAirport myAirport = <... lookup MyAirport by airportId = self.reviewableId ...>
            if (myAirport) {
                self.airport = myAirport;
            }

        } else if (self.restaurant == nil && [self.reviewableType isEqualToString:@"Restaurant"]) {

            MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = self.reviewableId ...>
            if (myRestaurant) {
                self.restaurant = myRestaurant;
            }
        }
    }
}

- (void)willSave {
    [self updatePolymorphicAssociations];
}

4)覆盖didSave,而不是willSave.这解决了我们在#3中使用后台进行大量导入的保存问题,但随后我们最终得到了未保存的更改,这很难看.

所以,我似乎在这里有很多选项,但是没有人能够解决在使用由Rails云数据库支持的Core Data的iOS应用程序中看起来常见的问题.我是否过度分析了这个?或者,还有更好的方法?

更新:请注意,目标是根据reviewableType是“Airport”还是“Restaurant”,仅在MyReview上设置其中一个关系.这种关系设置本身就很难看,但这就是我问这个问题的原因.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读